2012-04-22 2 views
2

Для ряда значений угла в (-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 нуждается в дополнительном внимании :)

+0

Если я правильно понял, вы хотите вычислить данные данных, режим, std и т. Д. Из данных гистограммы? Если это так, мне это кажется невозможным, потому что вы теряете много информации, беря гистограмму данных. Все, что вы можете получить, - это приближение, которое ухудшается при использовании более широких ящиков. Или это то, что вы ищете? – dmytro

+0

Посмотрите дистрибутив Фон Мизеса: http://en.wikipedia.org/wiki/Von_Mises_distribution. Если вы хотите книгу, Статистический анализ Циркулярных данных Фишера является стандартным учебником и обычно довольно разумно оценен. –

ответ

1

. Как получить приблизительное значение.

С Var(x) = <x^2> - <x>^2, мы имеем:

meanX = N.sum(counts * bins[:-1])/N.sum(counts) 
meanX2 = N.sum(counts * bins[:-1]**2)/N.sum(counts) 
std = N.sqrt(meanX2 - meanX**2) 
+0

Те, кто не относится к круговым данным, не имеют значения. Среднее не просто среднее :) (например, 359 градусов и 0 градусов всего на 1 градус) –

+0

@JoeKington, достаточно справедливо. Автор, однако, упомянул непериодические данные и, по-видимому, отлично справляется со своей «суммой» (counts * bins [: - 1]) », поэтому я решил, что вопрос связан скорее с оценкой моментов из гистограммы. – dmytro

+0

@ dmytro: То, что я испортил в своем первоначальном вопросе, было способом вычисления среднего значения для непериодических данных (моя исходная гистограмма нормирована, и именно поэтому я пренебрег делением на сумму отсчетов). На самом деле в моем коде мне нужны оба случая: например, мне нужно обрабатывать периодические и непериодические данные, поэтому ваше решение для расчета stdev очень ценится. – krzym

5

Посмотрите scipy.stats.circmean и scipy.stats.circstd.

Или у вас есть только количество гистограмм, а не «сырые» данные? Если это так, вы можете поместить Von Mises distribution в число ваших гистограмм и приблизиться к среднему значению и stddev таким образом.

+0

Что делать, если данные далеки от нормального распределения? – dmytro

+0

@JoeKington: спасибо за указание scipy.stats. {Circmean, circstd}. Среднее значение I, которое мы вычисляем, точно такое же, как и circmean. Я рассмотрю код circstd, чтобы узнать, почему мои результаты разные. Я благодарен также за то, что привлек мое внимание к распространению фон Мизеса. Наконечник на фитинге тоже замечательный. На самом деле, прежде чем я придумаю частичное решение (см. Править), я самостоятельно ударил по подобной идее, и он отлично работает. – krzym

+0

@dmytro: вы правы, нормальное распределение не является общим решением, в моем случае я установил p [ 0] * sin (a) exp (-0.5 (a/p [0]) ** 2) с хорошим результатом. Таким образом, установка * функции * на данные гистограммы может быть решением в некоторых случаях. – krzym

Смежные вопросы