平均と標準偏差が与えられた正規分布で確率を計算する方法は?


91

Pythonで平均、stdが与えられた場合、正規分布で確率を計算する方法は?この質問のOPのように、定義に従って自分の関数をいつでも明示的にコーディングできます。Pythonでの分布における確率変数の確率の計算

ライブラリ関数呼び出しがあるかどうか疑問に思うだけで、これを行うことができます。私の想像では、これは次のようになります。

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

Perlにも同様の質問があります。Perlの正規分布が与えられた時点での確率を​​計算するにはどうすればよいですか?。しかし、Pythonでは見当たりませんでした。

Numpyrandom.normal機能はありますが、サンプリングのようなもので、私が欲しいものとは限りません。

回答:


129

scipy.statsに1つあります

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

[注意すべきことの1つは、ヒントですが、パラメーターの受け渡しが少し広いことです。コードの設定方法が原因scipy.stats.norm(mean=100, std=12)で、scipy.stats.norm(100, 12)またはの代わりに誤って記述した場合、コードはscipy.stats.norm(loc=100, scale=12)受け入れられますが、それらの余分なキーワード引数を黙って破棄し、デフォルト(0,1)を提供します。]


3
範囲からどのように確率を取得しますか?98-102から言う?
レオン

2
@DSM:あなたの上記の例では、あなたが言うときscipy.stats.norm(100, 12).pdf(98)、それはで配布して98を得る確率を意味しているのmean 100 stddev 12ありますか0.032
Srivatsan 2015年

14
@ThePredator:いいえ、平均100および標準偏差12の正規分布で98を取得する確率はゼロです。:-)確率密度は0.032です。
DSM 2015年

その場合の確率密度は、正規分布のx値1.42が与えられた場合のy値を意味します。cdfは、曲線の下の領域と呼ばれるものを意味します。
2017年

5
@レオン、それはrv.cdf(102) - rv.cdf(98)どこrv = scipy.stats.norm(100, 12)です。
fuglede

46

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

ねえ、これは本当にいい答えです。おそらく、段階的な説明を提供していただけませんか?
llamageddon 2016年

この方法では、scipyよりも計算時間が少なくて済みます
mkm 2018年

ただし、scipyは、平均、標準偏差、およびサンプルの配列を処理できます。 [15、30、50]、):prob = scipy.stats.norm(mean、stddev).cdf(x)print(f'prob = {prob} ')出力:prob = [0.5 0.5 0.5] prob = [ 0.59870633 0.63055866 0.69146246] prob = [0.69146246 0.74750746 0.77337265]
John Deighan

16

詳細はこちらです。まず、凍結された分布を処理します(この場合、凍結とは、そのパラメーターが特定の値に設定されていることを意味します)。凍結されたディストリビューションを作成するには:

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

この答えを書いた人には十分に感謝できません。私はこれを解決するためにどこでも探していましたが、それを見つけることができませんでした。そして、コードにコメントを追加することで、何が起こっているのかを理解するのに本当に役立ちました。どうもありがとう。
bhola prasad

データが正規分布していないときにこれらの確率を計算する方法を1つ質問したいだけですか?この場合、私は何をしなければなりませんか?
bhola prasad

12

からPython 3.8、標準ライブラリはモジュールのNormalDist一部としてオブジェクトを提供しますstatistics

これを使用して、特定の平均()および標準偏差()の確率密度関数pdf-ランダムサンプルXが特定の値xに近くなる可能性)を取得できます。musigma

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

4

xの2つの値の間の領域を見つけたい場合は平均= 1; 標準偏差= 2; [0.5,2]の間のxの確率

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

3

回答に記載されているウィキペディアから引用された式は、通常の確率を計算するために使用することはできません。確率を計算するには、その式を使用して数値積分近似関数を作成する必要があります。

この式は、確率密度関数の値を計算します。正規分布は連続であるため、確率を取得するには積分を計算する必要があります。ウィキペディアのサイトでは、正規分布の閉じた形式を持たないCDFについて言及しています。


3
あなたが参照している答えへのコメントとしてよりよく合うでしょうが、あなたの貢献に感謝します:私がよく理解しているなら、あなたは元の質問に本当に答えていません。このようにして、誰もがあなたが話していることを一目で見ることができます。
ピエールプリネッティ2015年

1

私はあなたのために数学をするためにこのプログラムを書きました。要約統計量を入力するだけです。配列を提供する必要はありません:

母比率の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)

2
リンクは貴重な答えを提供するかもしれませんが、SOはユーザーにここにコードを投稿するように求めます。リンクは参照として役立ちますが、しばらくすると壊れて、将来の訪問者がソリューションにアクセスできなくなる傾向があります。
ミスター

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.