R的nrd0是否有一个scipy / numpy替代品?

时间:2016-07-12 19:55:02

标签: python r numpy scipy

来自R Documentation ...

  

bw.nrd0实现了选择a的带宽的经验法则   高斯核密度估计。默认为0.9倍   最小标准偏差和四分位数范围划分   样本大小的1.34倍到负的五分之一功率(=   西尔弗曼的“经验法则”,西尔弗曼(1986年,第48页,方程(3.31))   除非四分位数与正数结果重合   保证。

在1到400(相当于np.arange(1,401))的数组上,nrd0将返回31.39367。当我尝试在python中实现类似的东西时......

def nrd0_python(x):

    X = min(np.std(x), np.percentile(x,25))

    top = 0.9*X
    bottom = 1.34*len(x)**(-0.2)

    return top/bottom

我高达200(准确地说,224.28217762858455)

对于silverman的经验法则,是否有任何已知的python函数?

3 个答案:

答案 0 :(得分:3)

英语句子中操作符的优先级不明确。

这是一个返回您期望的值的实现:

In [201]: x = np.arange(1, 401)

In [202]: 0.9*min(np.std(x, ddof=1), (np.percentile(x, 75) - np.percentile(x, 25))/1.349)*len(x)**(-0.2)
Out[202]: 31.393668650034652

我没有Silverman参考。我在http://darp.lse.ac.uk/papersdb/Cowell-Flachaire_Handbook.pdf(第21页)中找到了。

答案 1 :(得分:2)

您没有正确的IQR计算:

import numpy

def bw_nrd0(x):

    if len(x) < 2:
        raise(Exception("need at least 2 data points"))

    hi = numpy.std(x, ddof=1)
    q75, q25 = numpy.percentile(x, [75 ,25])
    iqr = q75 - q25
    lo = min(hi, iqr/1.34)

    if not ((lo == hi) or (lo == abs(x[0])) or (lo == 1)):
        lo = 1

    return 0.9 * lo *len(x)**-0.2

返回与R函数相同的内容,其名称为:

> bw.nrd0
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)
}
<bytecode: 0x0000000010c688b0>
<environment: namespace:stats>

编辑:我对if代码中第二个R语句的原始读数不正确,请参阅this question。它旨在捕获lo == 0(因为sd(x) == 0)的情况,在这种情况下,向量全部为零。如果我的理解是正确的,那应该是:

if not lo:
    if hi:
        lo = hi
    elif abs(x[0]):
        lo = abs(x[0])
    else:
        lo = 1

R代码一样,您可以将其缩短为:

lo = lo or hi or abs(x[0]) or 1

包括这些检查以及检查向量的长度非常重要。

答案 2 :(得分:-1)

如果您正在使用KDE,可以使用scipy.stats.gaussian_kde吗?它实现了Silverman和Scott的带宽选择规则。

http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.gaussian_kde.html