替代scipy.stats.norm.ppf?

zpf6vheq  于 2022-12-18  发布在  其他
关注(0)|答案(1)|浏览(226)

有人知道scipy.stats.norm.ppf()的另一种Python实现吗?我正在构建一个EXE,我希望避免为这个函数添加scipy。
这里有一个很好的scipy.stats.norm.pdf()的替代方法:Alternative for scipy.stats.norm.pdf?

hpxqektj

hpxqektj1#

你可以安装pyerf模块,它是erferfinv函数的纯python实现,使用和scipy完全相同的公式。
当然,它是另一个模块而不是scipy,但它是纯python的,所以依赖性没有问题,而且它更小,因为它只包含你需要的东西。
然后,从erfinvnorm.ppf,这只是一个经典公式,在维基上,你可以看到x = cdf(y) = 0.5+0.5*erf(y/√2),所以从那里,你可以推导出x-0.5 = 0.5erf(y/√2)2x-1 = erf(y/√2)erfinv(2x-1) = y/√2y=√2×erfinv(2x-1)
所以

import pyerf
import math

def myppf(x):
    return math.sqrt(2)*pyerf.erfinv(2*x-1)

核查

>> myppf(0.1)
-1.2815515655446004
>> scipy.stats.norm.ppf(0.1)
-1.2815515655446004

没有派尔夫

这有点天真,但是如果性能不是问题,可以通过从math.erf进行二分法来计算erfinv(或者直接计算ppf,请参见下文
一个二个一个一个

直接多项式实现

或者您可以直接实现polynomial approximation of erfinv

import math

def erfinv(x):
    w = - math.log((1-x)*(1+x))
    if w < 5:
        w = w - 2.5
        p = 2.81022636e-08
        p = 3.43273939e-07 + p*w
        p = -3.5233877e-06 + p*w
        p = -4.39150654e-06 + p*w
        p = 0.00021858087 + p*w
        p = -0.00125372503 + p*w
        p = -0.00417768164 + p*w
        p = 0.246640727 + p*w
        p = 1.50140941 + p*w
    else:
        w = math.sqrt(w) - 3
        p = -0.000200214257
        p = 0.000100950558 + p*w
        p = 0.00134934322 + p*w
        p = -0.00367342844 + p*w
        p = 0.00573950773 + p*w
        p = -0.0076224613 + p*w
        p = 0.00943887047 + p*w
        p = 1.00167406 + p*w
        p = 2.83297682 + p*w
    return p*x

def myppf(x):
    return math.sqrt(2)*erfinv(2*x-1)
>> myppf(0.1)
-1.2815516851619244

相关问题