Для ряда значений угла в (-pi, pi) диапазоне, я делаю гистограмму. Существует ли эффективный способ вычисления среднего и модального (пост-вероятного) значения? Рассмотрим следующие примеры:статистика для гистограммы периодических данных
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
Теперь давайте гистограмму:
counts, bins = N.histogram(data, N.linspace(-N.pi, N.pi, 360))
Можно рассчитать средние, режим имеющих счетчики и баки для мусора? Для непериодических данных вычисление среднего значения является простым:
ave = sum(counts*bins[:-1])
Расчеты по модальной величине требуют больших усилий. На самом деле, я не уверен, что мой код ниже правильно: во-первых, я определяю бункера, которые встречаются наиболее часто, а затем рассчитать средний арифметический:
cmax = bins[N.argmax(counts)]
mode = N.mean(N.take(bins, N.nonzero(counts == cmax)[0]))
Я понятия не имею, как рассчитать стандартное отклонение от этих данных , хоть. Одним из очевидных решений для всех моих проблем (по крайней мере, описанных выше) является преобразование данных гистограммы в ряд данных, а затем их использование в расчетах. Однако это не изящно и неэффективно.
Любые советы будут очень полезными.
Это частичное решение, которое я написал.
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)
При запуске он дает следующие результаты:
mean: 175.840 85.843 175.360
stdev: 0.472 151.785 0.430
scipy: 175.840 (mean) 3.673 (stdev)
Несколько комментариев сейчас: первый столбец дает среднее/STDEV рассчитывается. Как видно, среднее значение хорошо согласуется с scipy.stats.circmean (спасибо JoeKington за указание на это). К сожалению stdev отличается. Я посмотрю на это позже. Второй столбец дает совершенно неправильные результаты (непериодическое среднее/std из numpy, очевидно, здесь не работает). Третий столбец дает sth, который я хотел получить из данных гистограммы (@JoeKington: мои исходные данные не будут соответствовать памяти моего компьютера .., @dmytro: спасибо за ваш вклад: конечно, размер бина будет влиять на результат, но в моем приложения у меня нет большого выбора, т. е. мне как-то нужно сводить данные). Как можно видеть, средний (3-й столбец) правильно рассчитан, stdev нуждается в дополнительном внимании :)
Если я правильно понял, вы хотите вычислить данные данных, режим, std и т. Д. Из данных гистограммы? Если это так, мне это кажется невозможным, потому что вы теряете много информации, беря гистограмму данных. Все, что вы можете получить, - это приближение, которое ухудшается при использовании более широких ящиков. Или это то, что вы ищете? – dmytro
Посмотрите дистрибутив Фон Мизеса: http://en.wikipedia.org/wiki/Von_Mises_distribution. Если вы хотите книгу, Статистический анализ Циркулярных данных Фишера является стандартным учебником и обычно довольно разумно оценен. –