Python 如何计算累积正态分布?

Python 如何计算累积正态分布?,python,numpy,scipy,statistics,Python,Numpy,Scipy,Statistics,我正在寻找Numpy或Scipy(或任何严格的Python库)中的函数,它将为我提供Python中的累积正态分布函数。从此处改编 下面是一个例子: >>> from scipy.stats import norm >>> norm.cdf(1.96) 0.9750021048517795 >>> norm.cdf(-1.96) 0.024997895148220435 换句话说,大约95%的标准正态区间位于两个标准偏差内,以标准平均值为零为

我正在寻找Numpy或Scipy(或任何严格的Python库)中的函数,它将为我提供Python中的累积正态分布函数。

从此处改编

下面是一个例子:

>>> from scipy.stats import norm
>>> norm.cdf(1.96)
0.9750021048517795
>>> norm.cdf(-1.96)
0.024997895148220435
换句话说,大约95%的标准正态区间位于两个标准偏差内,以标准平均值为零为中心

如果需要反向CDF:

>>> norm.ppf(norm.cdf(1.96))
array(1.9599999999999991)

以Unknown的示例为基础,在许多库中实现的函数normdist()的Python等价物是:

def normcdf(x, mu, sigma):
    t = x-mu;
    y = 0.5*erfcc(-t/(sigma*sqrt(2.0)));
    if y>1.0:
        y = 1.0;
    return y

def normpdf(x, mu, sigma):
    u = (x-mu)/abs(sigma)
    y = (1/(sqrt(2*pi)*abs(sigma)))*exp(-u*u/2)
    return y

def normdist(x, mu, sigma, f):
    if f:
        y = normcdf(x,mu,sigma)
    else:
        y = normpdf(x,mu,sigma)
    return y

现在回答这个问题可能已经太晚了,但由于谷歌仍然是这里的领导者,我决定在这里写下我的解决方案

也就是说,自Python 2.7以来,
math
库集成了错误函数
math.erf(x)

erf()
函数可用于计算传统统计函数,如累积标准正态分布:

from math import *
def phi(x):
    #'Cumulative distribution function for the standard normal distribution'
    return (1.0 + erf(x / sqrt(2.0))) / 2.0
参考:


Alex的回答为您展示了标准正态分布(平均值=0,标准偏差=1)的解决方案。如果正态分布为
平均值
标准值
(即
sqr(var)
),则需要计算:

from scipy.stats import norm

# cdf(x < val)
print norm.cdf(val, m, s)

# cdf(x > val)
print 1 - norm.cdf(val, m, s)

# cdf(v1 < x < v2)
print norm.cdf(v2, m, s) - norm.cdf(v1, m, s)
来自scipy.stats导入规范
#cdf(xval)
打印1-标准cdf(val、m、s)
#cdf(v1
阅读更多关于正态分布和许多公式的scipy实现的信息。

摘自上文:

from scipy.stats import norm
>>> norm.cdf(1.96)
0.9750021048517795
>>> norm.cdf(-1.96)
0.024997895148220435
对于双尾试验:

Import numpy as np
z = 1.96
p_value = 2 * norm.cdf(-np.abs(z))
0.04999579029644087

从Python 3.8开始,标准库将对象作为模块的一部分提供

它可用于获得给定平均值(
mu
)和标准偏差(
sigma
)的累积分布函数()(-随机样本X小于或等于X的概率):

对于标准正态分布(
mu=0
sigma=1
),可以对其进行简化:

简单地说:

import math
def my_cdf(x):
    return 0.5*(1+math.erf(x/math.sqrt(2)))

我在本页找到了公式

此外,您可以指定平均值(loc)和方差(scale)作为参数。e、 g,d=标准值(loc=10.0,标度=2.0);d、 cdf(12.0);此处的详细信息:@Irvan,scale参数实际上是标准偏差,而不是方差。为什么scipy将其命名为
loc
scale
?我使用了
帮助(norm.ppf)
,但接下来是
loc
scale
-需要帮助。@javadba-位置和比例是用于参数化广泛分布的更一般的统计术语。“对于正态分布,它们与均值和标准差一致,但对于其他分布则不是这样。”@MichaelOhlrogge。谢谢!这是NIST的一页进一步解释,因为std库实现了math.erf(),所以不需要sep实现。我找不到答案,这些数字是从哪里来的?@TmSmth如果我不得不猜测,这看起来像是某种指数内的近似值,所以你可能可以在稍微修改一下你的函数(改变变量,然后说r=t*exp(-z**2-f(t))后,用某种泰勒展开式来计算它们,然后做f的泰勒展开式(可以在数字上找到),这正是我想要的。如果有人不知道如何用它来计算的话“在标准分布范围内的数据百分比”,好:1-(1-φ(1))*2=0.6827(“在1个标准偏差范围内的数据的68%”对于一般正态分布,它将是
defφ(x,mu,sigma):返回(1+erf((x-mu)/sigma/sqrt(2)))/2
。根据一些快速检查,这比scipy.stats中的norm.cdf快得多,比erf的scipy和math实现快得多。这是矢量化的吗?或者如果需要计算数组中所有点的计算cdf,是否应该使用scipy实现?
from statistics import NormalDist

NormalDist(mu=0, sigma=1).cdf(1.96)
# 0.9750021048517796
NormalDist().cdf(1.96)
# 0.9750021048517796

NormalDist().cdf(-1.96)
# 0.024997895148220428
import math
def my_cdf(x):
    return 0.5*(1+math.erf(x/math.sqrt(2)))