如何在Python中计算正态累积分布函数的反函数?

107

我该如何在Python中计算正态分布累积分布函数(CDF)的反函数?

我应该使用哪个库?可能是scipy?


1
你是指反高斯分布(http://en.wikipedia.org/wiki/Inverse_Gaussian_distribution),还是正态分布的累积分布函数的反函数(http://en.wikipedia.org/wiki/Normal_distribution),或者其他什么? - Warren Weckesser
@WarrenWeckesser 第二个:正态分布的累积分布函数的反函数 - Yueyoum
1
@WarrenWeckesser 我的意思是 Excel 中 "normsinv" 函数的 Python 版本。 - Yueyoum
3个回答

171

NORMSINV(在评论中提到)是标准正态分布的累积分布函数的反函数。使用scipy,您可以通过scipy.stats.norm对象的ppf方法计算这个函数。缩写ppf代表百分点函数,也称为分位数函数

In [20]: from scipy.stats import norm

In [21]: norm.ppf(0.95)
Out[21]: 1.6448536269514722

确认它是CDF的反函数:

In [34]: norm.cdf(norm.ppf(0.95))
Out[34]: 0.94999999999999996

默认情况下,norm.ppf使用均值=0和标准差=1,即“标准”正态分布。您可以通过分别指定locscale参数来使用不同的均值和标准偏差。

In [35]: norm.ppf(0.95, loc=10, scale=2)
Out[35]: 13.289707253902945

如果您查看scipy.stats.norm的源代码,您会发现ppf方法最终调用scipy.special.ndtri。 因此,要计算标准正态分布的CDF的反函数,您可以直接使用该函数:

In [43]: from scipy.special import ndtri

In [44]: ndtri(0.95)
Out[44]: 1.6448536269514722

ndtrinorm.ppf 快得多:

In [46]: %timeit norm.ppf(0.95)
240 µs ± 1.75 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

In [47]: %timeit ndtri(0.95)
1.47 µs ± 1.3 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

29
我认为“百分点函数”(ppf)是个糟糕的名称。大多数统计学家使用“分位数函数”来代替。 - William Zhang
你不需要在ppf和cdf上指定均值和标准差吗? - bones.felipe
@bones.felipe,“标准”正态分布的均值为0,标准差为1。这些是scipy.stats.norm方法位置和规模的默认值。 - Warren Weckesser
我看到了这个代码 norm.cdf(norm.ppf(0.95, loc=10, scale=2)),觉得很奇怪 norm.cdf 没有 loc=10scale=2,我认为它应该有。 - bones.felipe

39

Python 3.8开始,标准库提供了NormalDist对象作为statistics模块的一部分。

它可以用来获取给定平均值(mu)和标准差(sigma)的反累积分布函数(inv_cdf - cdf的反函数),也称为分位函数百分点函数

from statistics import NormalDist

NormalDist(mu=10, sigma=2).inv_cdf(0.95)
# 13.289707253902943

可以简化为标准正态分布 (mu = 0sigma = 1):

NormalDist().inv_cdf(0.95)
# 1.6448536269514715

4
太好了!这让我可以放弃对scipy的依赖,因为我只需要单独使用stats.norm.ppf方法。 - Jethro Cao
你能用它将具有均匀分布的数据转换为正态分布吗? - vanetoj

21
# given random variable X (house price) with population muy = 60, sigma = 40
import scipy as sc
import scipy.stats as sct
sc.version.full_version # 0.15.1

#a. Find P(X<50)
sct.norm.cdf(x=50,loc=60,scale=40) # 0.4012936743170763

#b. Find P(X>=50)
sct.norm.sf(x=50,loc=60,scale=40) # 0.5987063256829237

#c. Find P(60<=X<=80)
sct.norm.cdf(x=80,loc=60,scale=40) - sct.norm.cdf(x=60,loc=60,scale=40)

#d. how much top most 5% expensive house cost at least? or find x where P(X>=x) = 0.05
sct.norm.isf(q=0.05,loc=60,scale=40)

#e. how much top most 5% cheapest house cost at least? or find x where P(X<=x) = 0.05
sct.norm.ppf(q=0.05,loc=60,scale=40)

6
请将英语翻译成中文。仅返回翻译后的文本:PS:您可以将“loc”视为“平均值”,将“scale”视为“标准偏差”。 - Suresh2692

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接