大阵列的密度估计

时间:2013-08-23 12:14:09

标签: python numpy scipy

我正在使用SciPy中的gaussian_kde函数生成内核密度估算值:

from scipy.stats.kde import gaussian_kde
from scipy.stats import norm
from numpy import linspace,hstack
from pylab import plot,show,hist

# creating data with two peaks
sampD1 = norm.rvs(loc=-1.0,scale=1,size=300)
sampD2 = norm.rvs(loc=2.0,scale=0.5,size=300)
samp = hstack([sampD1,sampD2])

# obtaining the pdf (my_pdf is a function!)
my_pdf = gaussian_kde(samp)

# plotting the result
x = linspace(-5,5,100)
plot(x,my_pdf(x),'r') # distribution function
hist(samp,normed=1,alpha=.3) # histogram
show()

上面的代码可以正常工作,但是如果样本量非常大,可能会非常慢。

我没有将我的样本存储在数组中,而是拥有一个键值/值对为value: counts的字典。例如,数组[1, 1, 1, 2, 2, 3]将在此直方图字典中编码为:

{1:3, 2:2, 3:1}

我的问题是,如何使用字典数据结构生成内核密度估算?作为一个示例输入,请考虑这个字典,其中6的值被看到2081次:

samp = {1: 1000, 2: 2800, 3: 6900, 4: 4322:, 5: 2300, 6: 2081}

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

你可以自己做高斯KDE:你首先需要创建一个足够小的步长的简单直方图。然后使用fftconvolve将结果与高斯卷积 (scipy.signal.fftconvolve)

import numpy as np, numpy.random,scipy,scipy.stats,scipy.signal,matplotlib.pyplot as plt
N = 1e5
minx = -10
maxx = 10
bins = 10000
w = 0.1 # kernel sigma

xs1 = np.random.normal(0, 1, size=N)
xs2 = np.random.normal(1.9, 0.01, size=N)
xs = np.r_[xs1, xs2]
hh,loc = scipy.histogram(xs, range=(minx, maxx), bins=bins)
kernel = scipy.stats.norm.pdf((loc[1:]+loc[:-1]) * .5, 0, w)
kde = scipy.signal.fftconvolve(hh, kernel, 'same')
plt.plot((loc[1:] + loc[:-1])*.5, kde)

答案 1 :(得分:1)

对第一个问题:

如果您的数据是单变量的,那么您可以使用fft版本的核密度估计,这种速度要快得多。 例如,在statsmodels http://statsmodels.sourceforge.net/devel/generated/statsmodels.nonparametric.kde.KDEUnivariate.html

第二个问题:

如果已经有直方图作为数据,则可以使用直方图平滑。但是我不知道python中的任何功能都会开箱即用。 statsmodels中的fft版本首先对数据进行分箱。第二步类似于直方图的卷积。也许可以使用类似的直方图数据。