为什么stat_density(R; ggplot2)和gaussian_kde(Python; scipy)不同?

时间:2019-03-26 21:06:30

标签: python r ggplot2 scipy kde

我正在尝试对一系列可能不会正态分布的分布产生基于KDE的PDF估计。

我喜欢R中ggplot的stat_density似乎可以识别频率的每个增量变化,但是无法通过Python的scipy-stats-gaussian_kde方法来复制它,该方法似乎过于平滑。

我已经按照以下步骤设置了我的R代码:

ggplot(test, aes(x=Val, color = as.factor(Class), group=as.factor(Class))) +
             stat_density(geom='line',kernel='gaussian',bw='nrd0' 
                                                            #nrd0='Silverman'
                                                            ,size=1,position='identity')

R example

我的python代码是:

kde = stats.gaussian_kde(data.ravel())
kde.set_bandwidth(bw_method='silverman')

python example

统计文档显示here,nrd0是bw调整的silverman方法。

基于上面的代码,我使用的是相同的内核(高斯)和带宽方法(Silverman)。

谁能解释为什么结果如此不同?

1 个答案:

答案 0 :(得分:4)

对于Silverman的规则是什么,似乎存在分歧。

scipy docs说Silverman的规则是implemented as

d

其中neff是维度数(在您的情况下为1),而(n * 3 / 4) ^ (-1 / 5)是有效样本大小(点数,假设没有权重)。因此,scipy带宽为bw.nrd0(乘以标准差,用另一种方法计算得出)。

通过对比,R的stats package docs将Silverman的方法描述为“标准偏差和四分位数范围的最小值的0.9倍除以样本大小的1.34倍至负五分之一的幂”,这也可以得到验证在R代码中,在控制台中输入function (x) { if (length(x) < 2L) stop("need at least 2 data points") hi <- sd(x) if (!(lo <- min(hi, IQR(x)/1.34))) (lo <- hi) || (lo <- abs(x[1L])) || (lo <- 1) 0.9 * lo * length(x)^(-0.2) } 会得到:

1.06 * sigma * n ^ (-1 / 5)
另一方面,

Wikipedia将“ Silverman的经验法则”作为估计器的许多可能名称之一:

(4 / 3) ^ (1 / 5) * sigma * n ^ (-1 / 5) ~= 1.06 * sigma * n ^ (-1 / 5)

维基百科版本等同于scipy版本。

所有三个来源都引用了相同的参考文献:Silverman,B.W. (1986)。 统计和数据分析的密度估算。伦敦:查普曼和霍尔/ CRC。 p。 48. ISBN 978-0-412-24620-3。 Wikipedia和R特别引用了第48页,而scipy的文档未提及页码。 (我已向Wikipedia提交了修改,以将其页面引用更新为第45页,请参见下文。)


附录

我找到了Silverman参考资料的PDF。

在第45页上,公式3.28是Wikipedia文章(3 / 4) ^ (-1 / 5)中使用的公式。 Scipy使用相同的方法,将(4 / 3) ^ (1 / 5)重写为等效的h = 0.9 * A * n ^ (-1 / 5) # A defined on previous page, eqn 3.30 A = min(standard deviation, interquartile range / 1.34) 。 Silverman将这种方法描述为:

  

如果总体上呈正态分布,则(3.28)会很好地工作,但是如果总体上是多峰的,它可能会在某种程度上过度平滑...随着混合物变得更加强烈的双峰,相对于公式(3.28)而言,越来越多的平滑平滑参数的最佳选择。

scipy文档reference this weakness,说明:

  

它包括自动确定带宽。估计最适合单峰分布;双峰或多峰分布趋于平滑。

Silverman文章继续激发R和Stata使用的方法。在第48页上,我们得到等式3.31:

{{1}}

Silverman将该方法描述为:

  

两全其美...总而言之,平滑参数的选择([eqn] 3.31)在很大的密度范围内都非常适用,并且很容易评估。对于许多目的来说,这当然是适当选择窗口宽度的方法,对于其他目的,则是进行后续微调的良好起点。

因此,似乎Wikipedia和Scipy使用了Silverman提出的简单估计量。 R和Stata使用了更完善的版本。