Python 多元KDE Scipy统计数据-如果它';它不是高斯分布?
我有一些我正在平滑使用的2D数据:Python 多元KDE Scipy统计数据-如果它';它不是高斯分布?,python,scipy,kernel-density,scipy.stats,Python,Scipy,Kernel Density,Scipy.stats,我有一些我正在平滑使用的2D数据: from scipy.stats import gaussian_kde kde = gaussian_kde(data) 但是如果我的数据不是高斯/tophat/其他选项呢?我的在平滑之前看起来更椭圆,所以我真的应该在x和y上有不同的带宽吗?一个方向上的方差要大得多,x轴的值也更高,所以感觉简单的高斯分布可能会遗漏一些东西?这就是我从定义的x和Y中得到的结果。看起来不错。你是不是期待一些不同的东西 import numpy as np from scipy
from scipy.stats import gaussian_kde
kde = gaussian_kde(data)
但是如果我的数据不是高斯/tophat/其他选项呢?我的在平滑之前看起来更椭圆,所以我真的应该在x和y上有不同的带宽吗?一个方向上的方差要大得多,x轴的值也更高,所以感觉简单的高斯分布可能会遗漏一些东西?这就是我从定义的
x
和Y
中得到的结果。看起来不错。你是不是期待一些不同的东西
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
def generate(n):
# generate data
np.random.seed(42)
x = np.random.normal(size=n, loc=1, scale=0.01)
np.random.seed(1)
y = np.random.normal(size=n, loc=200, scale=100)
return x, y
x, y = generate(100)
xmin = x.min()
xmax = x.max()
ymin = y.min()
ymax = y.max()
X, Y = np.mgrid[xmin:xmax:100j, ymin:ymax:100j]
positions = np.vstack([X.ravel(), Y.ravel()])
values = np.vstack([x, y])
kernel = stats.gaussian_kde(values)
Z = np.reshape(kernel(positions).T, X.shape)
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(np.rot90(Z), cmap=plt.cm.gist_earth_r,
extent=[xmin, xmax, ymin, ymax],
aspect='auto', alpha=.75
)
ax.plot(x, y, 'ko', ms=5)
ax.set_xlim([xmin, xmax])
ax.set_ylim([ymin, ymax])
plt.show()
x
和y
的分布为高斯分布。
您也可以使用seaborn
进行验证
import pandas as pd
import seaborn as sns
# I pass a DataFrame because passing
# (x,y) alone will be soon deprecated
g = sns.jointplot(data=pd.DataFrame({'x':x, 'y':y}), x='x', y='y')
g.plot_joint(sns.kdeplot, color="r", zorder=0, levels=6)
更新 二维数据的核密度估计沿每个轴分别进行,然后连接在一起 让我们用我们已经使用过的数据集做一个例子 正如我们在
seaborn
jointplot中所看到的,您不仅有估计的2d kde,还有x
和y
的边际分布(直方图)
因此,让我们一步一步地估计x
和y
的密度,然后在线性空间上计算密度
kde_x = sps.gaussian_kde(x)
kde_x_space = np.linspace(x.min(), x.max(), 100)
kde_x_eval = kde_x.evaluate(kde_x_space)
kde_x_eval /= kde_x_eval.sum()
kde_y = sps.gaussian_kde(y)
kde_y_space = np.linspace(y.min(), y.max(), 100)
kde_y_eval = kde_y.evaluate(kde_y_space)
kde_y_eval /= kde_y_eval.sum()
fig, ax = plt.subplots(1, 2, figsize=(12, 4))
ax[0].plot(kde_x_space, kde_x_eval, 'k.')
ax[0].set(title='KDE of x')
ax[1].plot(kde_y_space, kde_y_eval, 'k.')
ax[1].set(title='KDE of y')
plt.show()
现在我们有了x
和y
的边际分布。这些是概率密度函数,因此,x和y的联合概率可以看作是独立事件x
和y
的交集,因此我们可以在二维矩阵中乘以x和y的估计概率密度,并在三维投影上绘制
# Grid of x and y
X, Y = np.meshgrid(kde_x_space, kde_y_space)
# Grid of probability density
kX, kY = np.meshgrid(kde_x_eval, kde_y_eval)
# Intersection
Z = kX * kY
fig, ax = plt.subplots(
2, 2,
subplot_kw={"projection": "3d"},
figsize=(10, 10))
for i, (elev, anim, title) in enumerate(zip([10, 10, 25, 25],
[0, -90, 25, -25],
['y axis', 'x axis', 'view 1', 'view 2']
)):
# Plot the surface.
surf = ax.flat[i].plot_surface(X, Y, Z, cmap=plt.cm.gist_earth_r,
linewidth=0, antialiased=False, alpha=.75)
ax.flat[i].scatter(x, y, zs=0, zdir='z', c='k')
ax.flat[i].set(
xlabel='x', ylabel='y',
title=title
)
ax.flat[i].view_init(elev=elev, azim=anim)
plt.show()
这是一个非常简单的naif方法,但只是想了解它是如何工作的,以及为什么x和y比例对2d KDE不重要。请提供一个数据示例。概率密度函数的高斯核密度估计适用于单峰分布,正如您在文档中所读到的,双峰/多峰分布过于平滑。PS:如果您对
scipy
Gaussian KDE不满意,您可以尝试使用KDEpy
来选择不同的内核函数数据如下:X=np.random.normal(size=(100,1),loc=1,scale=0.01),Y=np.random.normal(size=(100,1),loc=200,scale=100)
也就是说,Y的大小要大得多,扩展得多,所以我不想要高斯KDE,更椭圆?我不知道你确切的意思是什么,我会用你的X和YYS发送一个答案,看起来不错,谢谢你,但我不知道我是怎么理解的!如果KDE将宽度sigma的高斯分布放在每个数据点上,然后将它们相加,如果我看x轴,我会说sigma约为0.001,但如果我看y轴,我会说它约为1。我只是对它必须使用的sigma近似值感到困惑,因为结果看起来不错,我只是想确定我不需要先规范化我的数据或者其他什么你可以在这里找到一个关于KDE如何工作以及不同的内核函数如何影响估计的非常好的交互式解释@Lizardinablizzard我添加了一个关于2d KDE基础的更新,解释了为什么x和y比例不重要