【问题标题】:Smooth Approximation of KDE in pythonpython中KDE的平滑逼近
【发布时间】:2021-01-24 02:39:28
【问题描述】:

我试图在我的 KDE 绘图的 x 轴上只获取非负值。我知道我可以限制 x 轴值,但我不希望那样。有没有办法平滑地逼近 KDE,使得没有非负值?我所有的数据都是非负的,但我没有很多样本点(最多 500 个,我无法获得更多)。我也试过调整带宽,看起来不太好。

for i in range(len(B)):
    ax = sns.kdeplot(data[i],shade=True)   
ax.set_xlabel('Maimum detection time')
ax.legend(['N=25,R=20', 'N=30,R=20', 'N=35,R=20'],fontsize=5)
plt.show()

【问题讨论】:

  • 这能回答你的问题吗? Change y range to start from 0 with matplotlib
  • Seaborn 的 kdeplot 有一个可能有用的 clip= 参数。请注意,获取更多数据只会有一点帮助,因为高斯 kde 只假设平滑分布,没有截止。

标签: python seaborn statsmodels kde scipy.stats


【解决方案1】:

kdeplot 背后发生的事情是,内核密度与许多小正态密度(参见 this illustration)相匹配,并且截断截止点边缘的密度溢出。

使用示例数据:

import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
import statsmodels.api as sm
from scipy.stats import norm

np.random.seed(999)

data = pd.DataFrame({'a':np.random.exponential(0.3,100),
                     'b':np.random.exponential(0.5,100)})  

如果您使用clip=,它不会停止对负值的评估:

for i in data.columns:
    ax = sns.kdeplot(data[i],shade=True,gridsize=200)

如果你添加cut=0,它看起来会很奇怪。正如您所指出的,您可以在 0 处截断它:

post on cross-validated 提出了两种解决方案。我编写了@whuber 提供的R 代码的python 实现:

def trunc_dens(x):
    kde = sm.nonparametric.KDEUnivariate(x)
    kde.fit()
    h = kde.bw
    w = 1/(1-norm.cdf(0,loc=x,scale=h))
    d = sm.nonparametric.KDEUnivariate(x)
    d = d.fit(bw=h,weights=w / len(x),fft=False)
    d_support = d.support
    d_dens = d.density
    d_dens[d_support<0] = 0
    return d_support,d_dens

我们可以查看data['a'] 的样子:

kde = sm.nonparametric.KDEUnivariate(data['a'])
kde.fit()
plt.plot(kde.support,kde.density)
_x,_y = trunc_dens(data['a'])
plt.plot(_x,_y)

您可以为两者绘制它:

fig,ax = plt.subplots()
for i in data.columns:
    _x,_y = trunc_dens(data[i])
    ax.plot(_x,_y)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-19
    • 2016-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-20
    相关资源
    最近更新 更多