Эмпирическая функция распределения в Numpy
У меня есть следующий список значений:
x = [-0.04124324405924407, 0, 0.005249724476788287, 0.03599351958245578, -0.00252785423151014, 0.01007584102031178, -0.002510349639322063,...]
и я хочу вычислить эмпирическую функцию плотности, поэтому я думаю, что мне нужно вычислить эмпирическую интегральную функцию распределения, и я использовал этот код:
counts = np.asarray(np.bincount(x), dtype=float)
cdf = counts.cumsum() / counts.sum()
и тогда я вычисляю это значение:
print cdf[0.01007584102031178]
и я всегда получаю 1, поэтому я думаю, что сделал ошибку. Вы знаете, как это исправить? Спасибо!
2 ответа
Обычное определение эмпирического cdf - это число наблюдений, меньшее или равное данному значению, деленное на общее количество наблюдений. Используя 1d numpy массивы это x[x <= v].size / x.size
(деление поплавка, в Python2 вам нужно from __future__ import division
):
x = np.array([-0.04124324405924407, 0,
0.005249724476788287, 0.03599351958245578,
-0.00252785423151014, 0.01007584102031178,
-0.002510349639322063])
v = 0.01007584102031178
print(x[x <= v].size / x.size)
Будет печатать 0.857142857143
, (фактическое значение, если эмпирический cdf на 0.01007584102031178 составляет 6 / 7).
Это довольно дорого, если ваш массив большой, и вам нужно вычислить cdf для нескольких значений. В таких случаях вы можете сохранить отсортированную копию ваших данных и использовать np.searchsorted()
узнать количество наблюдений <= v:
def ecdf(x):
x = np.sort(x)
def result(v):
return np.searchsorted(x, v, side='right') / x.size
return result
cdf = ecdf(x)
print(cdf(v))
Здесь две вещи идут не так, как надо:
np.bincount имеет смысл только для массива целых чисел. Создает гистограмму значений массива, округленную до целого числа. Для более сложной гистограммы используйте np.histogram. Он может работать с плавающей точкой, и вы можете точно указать количество бинов или границы бинов, а также нормализацию.
Дополнительно, cdf
обозначает нормальный массив NumPy в вашем случае. Индексы массива могут быть только целыми числами, поэтому ваш запрос cdf[0.01007584102031178]
округляется до cdf[0]
,
Таким образом, в итоге ваш код сначала подсчитывает целые числа (все они округлены до 0), поэтому ваш нормализованный cdf впоследствии просто cdf == [ 1. ]
, Затем ваш индекс округляется в меньшую сторону, поэтому вы запрашиваете cdf[0]
который равен 1.