Как я могу вывести эмпирический CDF на печать массива чисел в matplotlib в Python? Я ищу cdf аналог pylab's, "тсс" функционируют.
Одна вещь, о которой я могу думать:
from scipy.stats import cumfreq
a = array([...]) # my array of numbers
num_bins = 20
b = cumfreq(a, num_bins)
plt.plot(b)
Это корректно хотя? Существует ли более легкий/лучше путь?
спасибо.
Похоже, это (почти) именно то, что вы хотите. Два момента:
Во-первых, результаты представляют собой кортеж из четырех элементов. Третий - это размер бинов. Второй - начальная точка наименьшего бина. Первый - количество точек в или под каждым бином. (Последнее - количество точек вне пределов, но поскольку вы не задали их, все точки будут разбиты на бины.)
Во-вторых, вам нужно изменить масштаб результатов, чтобы конечное значение было равно 1, чтобы следовать обычным соглашениям CDF, но в остальном все правильно.
Вот что он делает под капотом:
def cumfreq(a, numbins=10, defaultreallimits=None):
# docstring omitted
h,l,b,e = histogram(a,numbins,defaultreallimits)
cumhist = np.cumsum(h*1, axis=0)
return cumhist,l,b,e
Он выполняет гистограммирование, затем выдает кумулятивную сумму подсчетов в каждом бине. Таким образом, i-е значение результата - это количество значений массива, меньших или равных максимуму i-го бина. Таким образом, конечное значение равно размеру исходного массива.
Наконец, чтобы построить график, вам нужно будет использовать начальное значение бина и размер бина, чтобы определить, какие значения оси x вам понадобятся.
Другой вариант - использовать numpy.histogram
, который может выполнить нормализацию и вернуть края бина. Вам нужно будет самостоятельно выполнить кумулятивную сумму результирующих отсчетов.
a = array([...]) # your array of numbers
num_bins = 20
counts, bin_edges = numpy.histogram(a, bins=num_bins, normed=True)
cdf = numpy.cumsum(counts)
pylab.plot(bin_edges[1:], cdf)
(bin_edges[1:]
- верхний край каждого бина.)
Что вы хотите сделать с CDF? Чтобы построить это, это только начало. Вы можете попробовать несколько разных значений, например:
from __future__ import division
import numpy as np
from scipy.stats import cumfreq
import pylab as plt
hi = 100.
a = np.arange(hi) ** 2
for nbins in ( 2, 20, 100 ):
cf = cumfreq(a, nbins) # bin values, lowerlimit, binsize, extrapoints
w = hi / nbins
x = np.linspace( w/2, hi - w/2, nbins ) # care
# print x, cf
plt.plot( x, cf[0], label=str(nbins) )
plt.legend()
plt.show()
Гистограмма
перечисляет различные правила для количества ящиков, например num_bins ~ sqrt (len (a))
.
(Мелкий шрифт: здесь происходят две совершенно разные вещи,
график
интерполирует плавную кривую через, скажем, 20 биннированных значений. Любой из них может уходить от "неуклюжих" данных
или имеет длинные хвосты, даже для одномерных данных - двухмерные, трехмерные данные становятся все труднее.
Смотрите также
Оценка плотности
а также
с использованием оценки плотности ядра scipy гаусса
).
Вы можете использовать функцию ECDF
из библиотеки scikits.statsmodels:
import numpy as np
import scikits.statsmodels as sm
import matplotlib.pyplot as plt
sample = np.random.uniform(0, 1, 50)
ecdf = sm.tools.ECDF(sample)
x = np.linspace(min(sample), max(sample))
y = ecdf(x)
plt.step(x, y)
В версии 0.4 scicits.statsmodels
была переименована в statsmodels
. ECDF
теперь находится в модуле distributions
(в то время как statsmodels.tools.tools.ECDF
обесценился).
import numpy as np
import statsmodels.api as sm # recommended import according to the docs
import matplotlib.pyplot as plt
sample = np.random.uniform(0, 1, 50)
ecdf = sm.distributions.ECDF(sample)
x = np.linspace(min(sample), max(sample))
y = ecdf(x)
plt.step(x, y)
plt.show()
У меня есть тривиальное дополнение к методу AFoglia, для нормализации CDF
n_counts,bin_edges = np.histogram(myarray,bins=11,normed=True)
cdf = np.cumsum(n_counts) # cdf not normalized, despite above
scale = 1.0/cdf[-1]
ncdf = scale * cdf
Нормализация histo делает его интеграл единицей, что означает, что cdf не будет нормализован. Приходится масштабировать его самостоятельно.