Pour une série de valeurs d'angle dans la gamme (-pi, pi), je fais un histogramme. Existe-t-il un moyen efficace de calculer une valeur moyenne et modale (post-probable)? Considérons les exemples suivants:statistiques pour l'histogramme des données périodiques
import numpy as N, cmath
deg = N.pi/180.
d = N.array([-175., 170, 175, 179, -179])*deg
i = N.sum(N.exp(1j*d))
ave = cmath.phase(i)
i /= float(d.size)
stdev = -2. * N.log(N.sqrt(i.real**2 + i.imag**2))
print ave/deg, stdev/deg
Maintenant, nous allons avoir un histogramme:
counts, bins = N.histogram(data, N.linspace(-N.pi, N.pi, 360))
Est-il possible de calculer la moyenne, le mode ayant compte et bacs? Pour les données non périodiques, le calcul d'une moyenne est simple:
ave = sum(counts*bins[:-1])
Le calcul d'une valeur modale nécessite plus d'efforts. En fait, je ne suis pas sûr que mon code ci-dessous est correcte: tout d'abord, j'identifie les bacs qui se produisent le plus souvent, puis-je calculer une moyenne arithmétique:
cmax = bins[N.argmax(counts)]
mode = N.mean(N.take(bins, N.nonzero(counts == cmax)[0]))
Je ne sais pas, comment calculer l'écart-type à partir de ces données , bien que. Une solution évidente à tous mes problèmes (au moins ceux décrits ci-dessus) est de convertir les données d'histogramme en une série de données et ensuite l'utiliser dans les calculs. Ce n'est pas élégant, cependant, et inefficace.
Tous les conseils seront très appréciés.
C'est la solution partielle que j'ai écrite.
import numpy as N, cmath
import scipy.stats as ST
d = [-175, 170.2, 175.57, 179, -179, 170.2, 175.57, 170.2]
deg = N.pi/180.
data = N.array(d)*deg
i = N.sum(N.exp(1j*data))
ave = cmath.phase(i) # correct and exact mean for periodic data
wrong_ave = N.mean(d)
i /= float(data.size)
stdev = -2. * N.log(N.sqrt(i.real**2 + i.imag**2))
wrong_stdev = N.std(d)
bins = N.linspace(-N.pi, N.pi, 360)
counts, bins = N.histogram(data, bins, normed=False)
# consider it weighted vector addition
nz = N.nonzero(counts)[0]
weight = counts[nz]
i = N.sum(weight * N.exp(1j*bins[nz])/len(nz))
pave = cmath.phase(i) # correct and approximated mean for periodic data
i /= sum(weight)/float(len(nz))
pstdev = -2. * N.log(N.sqrt(i.real**2 + i.imag**2))
print
print 'scipy: %12.3f (mean) %12.3f (stdev)' % (ST.circmean(data)/deg, \
ST.circstd(data)/deg)
Lorsqu'il est exécuté, il donne des résultats suivants:
mean: 175.840 85.843 175.360
stdev: 0.472 151.785 0.430
scipy: 175.840 (mean) 3.673 (stdev)
Quelques commentaires maintenant: la première colonne moyenne/stdev calculé. Comme on peut le voir, la moyenne concorde bien avec scipy.stats.circmean (merci JoeKington pour l'avoir signalé). Malheureusement, stdev diffère. Je le regarderai plus tard. La deuxième colonne donne des résultats complètement faux (moyenne non-périodique/std de numpy évidemment ne fonctionne pas ici). La 3ème colonne donne sth je voulais obtenir à partir des données de l'histogramme (@JoeKington: mes données brutes ne correspondent pas à la mémoire de mon ordinateur .., @dmytro: merci pour votre contribution: bien sûr, la taille de la poubelle influencera le résultat mais dans mon application je n'ai pas beaucoup de choix, c'est à dire que je dois réduire les données en quelque sorte). Comme on peut le voir, la moyenne (3e colonne) est calculée correctement, stdev nécessite plus d'attention :)
Si j'ai bien compris, vous voulez calculer la moyenne des données, le mode, std, etc. à partir des données de l'histogramme? Si c'est le cas, cela ne me semble pas possible, car vous perdez beaucoup d'informations en prenant l'histogramme des données. Tout ce que vous pouvez obtenir est une approximation qui s'aggrave avec des bacs plus larges. Ou est-ce ce que vous cherchez? – dmytro
Jetez un oeil à la distribution de Von Mises: http://en.wikipedia.org/wiki/Von_Mises_distribution. Si vous voulez un livre, l'analyse statistique des données circulaires de Fisher est le manuel standard, et est généralement assez raisonnable. –