如何计算给定均值和标准差的正态分布中的概率?
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)
来计算它。
【讨论】:
以上是关于如何计算给定均值和标准差的正态分布中的概率?的主要内容,如果未能解决你的问题,请参考以下文章