Ortalama ve standart sapma verilen normal bir dağılımda olasılık nasıl hesaplanır?


91

Python'da ortalama, std verilen normal dağılımdaki olasılık nasıl hesaplanır? Bu sorudaki OP'nin yaptığı gibi kendi fonksiyonumu her zaman açıkça kodlayabilirim: Python'da Bir Dağılımdaki Rastgele Bir Değişkenin Olasılığını Hesaplamak

Sadece bir kütüphane işlevi çağrısı olup olmadığını merak etmek bunu yapmanıza izin verecektir. Benim hayalime göre şöyle olurdu:

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

Perl'de de benzer bir soru var: Perl'de normal dağılım verilen bir noktada olasılığı nasıl hesaplayabilirim? . Ama Python'da bir tane görmedim.

Numpybir random.normalişlevi vardır, ancak örnekleme gibi, tam olarak istediğim gibi değil.

Yanıtlar:


129

Scipy.stats içinde bir tane var :

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

[Dikkat edilmesi gereken bir şey - sadece bir ipucu - parametre geçişinin biraz geniş olmasıdır. Kodun ayarlanma şekli nedeniyle, yanlışlıkla veya scipy.stats.norm(mean=100, std=12)yerine yazarsanız , o zaman kabul eder, ancak bu ekstra anahtar kelime argümanlarını sessizce atar ve size varsayılanı (0,1) verir.]scipy.stats.norm(100, 12)scipy.stats.norm(loc=100, scale=12)


3
Aralıklardan olasılıkları nasıl elde edersiniz? 98-102 arası mı?
Leon

2
@DSM: En Yukarıdaki örnekte, derken scipy.stats.norm(100, 12).pdf(98), bununla ilgili bir dağılımda 98 alma olasılığını demek mean 100 ve stddev 12bir 0.032?
Srivatsan

14
@ThePredator: hayır, ortalama 100 ve stddev 12 ile normal bir dağılımda 98 alma olasılığı sıfırdır. :-) Olasılık yoğunluğu 0,032'dir.
DSM

Bu durumda olasılık yoğunluğu, normal dağılım için 1.42 x değeri verildiğinde y değeri anlamına gelir. cdf, eğrinin altındaki alan dediğimiz şey anlamına gelir.
parçalama

5
@Leon, işte rv.cdf(102) - rv.cdf(98)burada rv = scipy.stats.norm(100, 12).
fuglede

47

Scipy.stats harika bir modüldür. Sadece başka bir yaklaşım sunmak için, bunu doğrudan kullanarak hesaplayabilirsiniz.

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

Bu, burada bulunan formülü kullanır: http://en.wikipedia.org/wiki/Normal_distribution#Probability_density_function

test etmek için:

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

Hey, bu gerçekten güzel bir cevap. Belki adım adım bir açıklama sağlar mısınız?
Llamageddon

Bu yöntem, scipy'den daha az hesaplama süresine ihtiyaç duyar
mkm

Ancak scipy, ortalamalar, stdevs ve örnek dizilerini işleyebilir: ortalama = [5, 10, 20] stddev = [20, 30, 40] x in ([5, 10, 20], [10, 20, 40] [15, 30, 50],): prob = scipy.stats.norm (ortalama, stddev) .cdf (x) print (f'prob = {prob} ') çıktıları: prob = [0.5 0.5 0.5] prob = [ 0.59870633 0.63055866 0.69146246] prob = [0.69146246 0.74750746 0.77337265]
John Deighan

16

İşte daha fazla bilgi . İlk önce donmuş bir dağıtımla uğraşıyorsunuz (bu durumda donmuş, bu dağıtımın parametrelerinin belirli değerlere ayarlandığı anlamına gelir). Dondurulmuş bir dağıtım oluşturmak için:

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

Bu cevabı yazan kişiye ne kadar teşekkür etsem azdır. Bunu çözmek için her yere bakıyordum ama bulamadım. Ve yorumları kodla birlikte eklemek, neler olduğunu anlamama gerçekten yardımcı oldu. Çok teşekkürler.
bhola prasad

Sadece bir soru sormak istiyorum, veriler normal olarak dağılmadığında bu olasılıklar nasıl hesaplanır? Bu durumda ne yapmalıyım?
bhola prasad

12

Başlangıç ​​olarak Python 3.8, standart kütüphane NormalDistnesneyi statisticsmodülün bir parçası olarak sağlar .

Belirli bir ortalama ( ) ve standart sapma ( ) için olasılık yoğunluk fonksiyonunu ( pdf- rastgele bir X örneğinin verilen x değerine yakın olma olasılığı) elde etmek için kullanılabilir :musigma

from statistics import NormalDist

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

Ayrıca NormalDistnesnenin kümülatif dağılım işlevini de sağladığına dikkat edin ( cdf- rastgele bir X örneğinin x'ten küçük veya ona eşit olma olasılığı):

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

4

2 x ortalama = 1 değeri arasındaki alanı bulmak isterseniz; standart sapma = 2; x'in [0.5,2] arasındaki olasılığı

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

3

Cevaplarda bahsedilen Wikipedia'dan alıntılanan formül normal olasılıkları hesaplamak için kullanılamaz. Olasılığı hesaplamak için bu formülü kullanarak bir sayısal entegrasyon yaklaşımı işlevi yazmanız gerekir.

Bu formül, olasılık yoğunluk fonksiyonunun değerini hesaplar. Normal dağılım sürekli olduğundan, olasılıkları elde etmek için bir integral hesaplamanız gerekir. Wikipedia sitesi, normal dağılım için kapalı bir formu olmayan CDF'den bahseder.


3
Katkınız için teşekkür ederiz, ancak atıfta bulunduğunuz yanıta bir yorum olarak daha uygun olacaktır: eğer iyi anlıyorsam , asıl soruyu gerçekten yanıtlamıyorsunuzdur . Bu şekilde, ne hakkında konuştuğunuzu herkes ilk bakışta görecek.
Pierre Prinetti

1

Bu programı sizin için matematik yapmak için yazdım. Özet istatistiklerini girmeniz yeterlidir. Bir dizi sağlamaya gerek yok:

Nüfus Oranı için Tek Örnekli Z Testi:

Bunu oran yerine ortalama için yapmak için, z formülünü uygun şekilde değiştirin

DÜZENLEME:
Bağlantının içeriği:

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
Bağlantı değerli bir yanıt sağlayabilirken, SO, kullanıcılardan kodlarını burada SO'ya göndermelerini ister. Bağlantılar bir referans olarak kullanışlıdır, ancak bir süre sonra kırılma eğilimindedirler ve bu da çözümleri gelecekteki ziyaretçiler için erişilemez hale getirir.
Bay T

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.