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

Posted

技术标签:

【中文标题】如何计算给定均值和标准差的正态分布中的概率?【英文标题】:How to calculate probability in a normal distribution given mean & standard deviation? 【发布时间】:2012-09-06 22:22:52 【问题描述】:

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

只是想知道是否有库函数调用将允许您执行此操作。在我的想象中它会是这样的:

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

Perl 中有一个类似的问题:How can I compute the probability at a point given a normal distribution in Perl?。但我在 Python 中没有看到。

Numpy 有一个random.normal 函数,但它就像采样,不是我想要的。

【问题讨论】:

【参考方案1】:

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 ).]

【讨论】:

如何从范围中获得概率?从 98 到 102 说? @DSM:在你上面的例子中,当你说scipy.stats.norm(100, 12).pdf(98)时,这是否意味着在mean 100 stddev 12的分布中得到98的概率是0.032 @ThePredator:不,在平均值为 100 且标准差为 12 的正态分布中得到 98 的概率为零。 :-) 密度的概率是0.032。 这种情况下的概率密度是指 y 值,给定正态分布的 x 值 1.42。 cdf 表示我们所说的曲线下面积。 @Leon,那是rv.cdf(102) - rv.cdf(98) rv = scipy.stats.norm(100, 12)【参考方案2】:

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

【讨论】:

嘿,这是一个非常好的答案。或许您介意提供一步一步的解释吗? 这个方法比scipy需要更少的计算时间 但是 scipy 可以处理均值、标准差和样本数组:mean = [ 5, 10, 20] stddev = [20, 30, 40] for x in ( [ 5, 10, 20], [10, 20, 40], [15, 30, 50], ): prob = scipy.stats.norm(mean, stddev).cdf(x) print(f'prob = prob') 输出:prob = [0.5 0.5 0.5]概率=[0.59870633 0.63055866 0.69146246]概率=[0.69146246 0.74750746 0.77337265]【参考方案3】:

您可以只使用数学库中内置的错误函数,如他们的website 所述。

【讨论】:

不,@user2340146,也在 Python 2 中:docs.python.org/2/library/math.html#math.erf【参考方案4】:

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

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

【讨论】:

感谢您的贡献,尽管它更适合作为对您所指答案的评论:如果我理解得很好,您并没有真正回答原始问题。这样,每个人都会第一眼看到你在说什么。【参考方案5】:

这里是more info。 首先,您正在处理一个冻结分布(在这种情况下冻结意味着它的参数设置为特定值)。创建冻结分布:

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

【讨论】:

我非常感谢写这个答案的人。我到处寻找解决这个问题但无法找到它。添加带有代码的 cmets 确实帮助我理解了正在发生的事情。非常感谢。 只想问一个问题,当数据不是正态分布时,这些概率如何计算?在这种情况下我该怎么办?【参考方案6】:

我编写了这个程序来为你做数学。只需输入摘要统计信息。无需提供数组:

One-Sample Z-Test for a Population Proportion:

要对平均值而不是比例执行此操作,请相应地更改 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)

【讨论】:

虽然该链接可能会提供有价值的答案,但 SO asks users to post their code here on SO 链接可用作参考,但它们往往会在一段时间后断开,从而使未来的访问者无法访问解决方案。【参考方案7】:

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

它可用于获取给定 概率密度函数pdf - 随机样本 X 接近给定值 x 的可能性) em>平均值 (mu) 和标准差 (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

【讨论】:

【参考方案8】:

如果您想找到 x mean = 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)

【讨论】:

【参考方案9】:

请注意,probability 不同于 probability density 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 个数据点的精确值 5 的概率(意味着间隔为 1)。您可以使用固定的间隔值,具体取决于您想要达到的结果。

【讨论】:

我认为提问者指的是“可能性”而不是真正的“概率”。【参考方案10】:

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

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

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

【讨论】:

以上是关于如何计算给定均值和标准差的正态分布中的概率?的主要内容,如果未能解决你的问题,请参考以下文章

如何找出标准误差与正态分布的特定量相关的概率?

r语言中随机正态分布均值

如何在Matlab中生成具有对数正态分布和指定几何平均数和几何标准差的随机数

谁能总结下 正态分布计算题公式

怎样求正态分布的平均值与方差

正态分布和中心极限定理