如何在给定均值和标准差的情况下计算正态分布的概率?

问题描述 投票:0回答:11

如何在 Python 中计算给定平均值、std 的正态分布概率?我总是可以根据定义显式地编写自己的函数,就像这个问题中的OP所做的那样:Calculate Probability of a Random Variable in a Distribution in Python

只是想知道是否有库函数调用可以让你做到这一点。在我的想象中它会是这样的:

nd = NormalDistribution(mu=100, std=12)
p = nd.prob(98)

Perl 中有一个类似的问题:如何在 Perl 中计算给定正态分布的点的概率?。但我在 Python 中没有看到。

Numpy
random.normal
功能,但是就像采样一样,不完全是我想要的。

python statistics scipy probability
11个回答
168
投票

scipy.stats中有一个:

>>> import scipy.stats
>>> scipy.stats.norm(0, 1)
<scipy.stats.distributions.rv_frozen object at 0x928352c>
>>> scipy.stats.norm(0, 1).pdf(0)
0.3989422804014327
>>> scipy.stats.norm(0, 1).cdf(0)
0.5
>>> scipy.stats.norm(100, 12)
<scipy.stats.distributions.rv_frozen object at 0x928352c>
>>> scipy.stats.norm(100, 12).pdf(98)
0.032786643008494994
>>> scipy.stats.norm(100, 12).cdf(98)
0.43381616738909634
>>> scipy.stats.norm(100, 12).cdf(100)
0.5

[需要注意的一件事——只是一个提示——是参数传递有点宽泛。 由于代码的设置方式,如果您不小心写了

scipy.stats.norm(mean=100, std=12)
而不是
scipy.stats.norm(100, 12)
scipy.stats.norm(loc=100, scale=12)
,那么它会接受它,但会默默地丢弃这些额外的关键字参数并给您默认值 (0,1 ).]


61
投票

Scipy.stats 是一个很棒的模块。只是提供另一种方法,您可以直接使用

计算
import math
def normpdf(x, mean, sd):
    var = float(sd)**2
    denom = (2*math.pi*var)**.5
    num = math.exp(-(float(x)-float(mean))**2/(2*var))
    return num/denom

这使用此处找到的公式:http://en.wikipedia.org/wiki/Normal_distribution#Probability_ Density_function

测试:

>>> normpdf(7,5,5)  
0.07365402806066466
>>> norm(5,5).pdf(7)
0.073654028060664664

48
投票

这里是更多信息。 首先,您正在处理冻结分布(在这种情况下冻结意味着其参数设置为特定值)。要创建冻结分布:

import scipy.stats
scipy.stats.norm(loc=100, scale=12)
#where loc is the mean and scale is the std dev
#if you wish to pull out a random number from your distribution
scipy.stats.norm.rvs(loc=100, scale=12)

#To find the probability that the variable has a value LESS than or equal
#let's say 113, you'd use CDF cumulative Density Function
scipy.stats.norm.cdf(113,100,12)
Output: 0.86066975255037792
#or 86.07% probability

#To find the probability that the variable has a value GREATER than or
#equal to let's say 125, you'd use SF Survival Function 
scipy.stats.norm.sf(125,100,12)
Output: 0.018610425189886332
#or 1.86%

#To find the variate for which the probability is given, let's say the 
#value which needed to provide a 98% probability, you'd use the 
#PPF Percent Point Function
scipy.stats.norm.ppf(.98,100,12)
Output: 124.64498692758187

33
投票

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

它可用于获取给定 mean (pdf) 和 standard 的

概率密度函数
mu
- 随机样本 X 接近给定值 x 的可能性)偏差
sigma
):

from statistics import NormalDist

NormalDist(mu=100, sigma=12).pdf(98)
# 0.032786643008494994

另请注意,

NormalDist
对象还提供累积分布函数
cdf
- 随机样本 X 小于或等于 x 的概率):

NormalDist(mu=100, sigma=12).cdf(98)
# 0.43381616738909634

13
投票

如果您想找到 x 平均值 = 1 的 2 个值之间的面积; 标准差 = 2; x 在 [0.5,2] 之间的概率

import scipy.stats
scipy.stats.norm(1, 2).cdf(2) - scipy.stats.norm(1,2).cdf(0.5)

6
投票

请注意,概率与之前的一些答案提到的概率密度

pdf()
不同。 概率是变量具有特定值的机会,而概率密度是变量接近特定值的机会,意味着一定范围内的概率。因此,要获得概率,您需要计算给定区间内概率密度函数的积分。作为近似值,您只需将概率密度乘以您感兴趣的区间即可得到实际概率。

import numpy as np
from scipy.stats import norm

data_start = -10
data_end = 10
data_points = 21
data = np.linspace(data_start, data_end, data_points)

point_of_interest = 5
mu = np.mean(data)
sigma = np.std(data)                                   
interval = (data_end - data_start) / (data_points - 1)
probability = norm.pdf(point_of_interest, loc=mu, scale=sigma) * interval

上面的代码将给出变量在 -10 到 10 之间的正态分布中具有 21 个数据点(意味着间隔为 1)的精确值为 5 的概率。您可以使用固定的间隔值,具体取决于您想要实现的结果。


4
投票

答案中提到的维基百科引用的公式不能用于计算正态概率。 您必须使用该公式编写数值积分近似函数才能计算概率。

该公式计算概率密度函数的值。 由于正态分布是连续的,因此您必须计算积分才能获得概率。 维基百科网站提到了 CDF,它没有正态分布的闭合形式。


2
投票

我想说:提问者问的是“在给定平均值和标准差的情况下,如何计算给定数据点在正态分布中的可能性?”而不是“如何计算给定均值和标准差的正态分布中的概率?”。

对于“概率”,它必须在 0 和 1 之间,但对于“可能性”,它必须是非负的(不一定在 0 和 1 之间)。

您可以使用

scipy.stats.multivariate_normal
中的 multivariate_normal.pdf(x, mean= mean_vec, cov=cov_matrix) 来计算它。


1
投票

我写这个程序是为了给你做数学计算。只需输入摘要统计数据即可。无需提供数组:

人口比例的单样本 Z 检验:

要对平均值而不是比例执行此操作,请相应地更改 z 的公式

编辑:
以下是链接内容:

import scipy.stats as stats
import math

def one_sample_ztest_pop_proportion(tail, p, pbar, n, alpha):
    #Calculate test stat

    sigma = math.sqrt((p*(1-p))/(n))
    z = round((pbar - p) / sigma, 2)

    if tail == 'lower':
        pval = round(stats.norm(p, sigma).cdf(pbar),4)
        print("Results for a lower tailed z-test: ")


    elif tail == 'upper':
        pval = round(1 - stats.norm(p, sigma).cdf(pbar),4)
        print("Results for an upper tailed z-test: ")


    elif tail == 'two':
        pval = round(stats.norm(p, sigma).cdf(pbar)*2,4)
        print("Results for a two tailed z-test: ")


    #Print test results
    print("Test statistic = {}".format(z))   
    print("P-value = {}".format(pval))
    print("Confidence = {}".format(alpha))

    #Compare p-value to confidence level
    if pval <= alpha:
        print("{} <=  {}. Reject the null hypothesis.".format(pval, alpha))
    else:
        print("{} > {}. Do not reject the null hypothesis.".format(pval, alpha))


#one_sample_ztest_pop_proportion('upper', .20, .25, 400, .05)

#one_sample_ztest_pop_proportion('two', .64, .52, 100, .05)

0
投票

您可以使用数学库中内置的误差函数,如其网站上所述。


0
投票
from scipy.stats import norm 
probability_pdf = norm.pdf(3, loc=mean, scale=std) 
print(probability_pdf)
© www.soinside.com 2019 - 2024. All rights reserved.