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



如何在Python中计算给定平均值,std的正态分布中的概率?我总是可以根据定义显式编写自己的函数,就像这个问题中的 OP 所做的那样: 在 Python 中计算分布中随机变量的概率

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

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

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

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

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)。

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

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

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

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

它可以用来得到给定平均值mu)和标准差sigma)的概率密度函数pdf - 随机样本X接近给定值x的可能性):

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
如果您想

找到 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)

注意概率不同于概率密度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 之间的正态分布中具有 5 的确切值的概率,其中包含 21 个数据点(意味着间隔为 1)。您可以使用固定的间隔值,具体取决于要实现的结果。

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

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

我想

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

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

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

我写这个程序是为了为你做数学运算。只需输入汇总统计信息。无需提供数组:

总体比例的单样本 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)

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

最新更新