Jak obliczyć prawdopodobieństwo w rozkładzie normalnym przy średniej i odchyleniu standardowym?


91

Jak obliczyć prawdopodobieństwo w rozkładzie normalnym przy danej średniej, standardowej w Pythonie? Zawsze mogę jawnie zakodować własną funkcję zgodnie z definicją, tak jak zrobił to OP w tym pytaniu: Obliczanie prawdopodobieństwa zmiennej losowej w dystrybucji w Pythonie

Zastanawiam się tylko, czy istnieje wywołanie funkcji biblioteki, które pozwoli ci to zrobić. W moim wyobrażeniu wyglądałoby to tak:

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

W Perlu pojawia się podobne pytanie: jak mogę obliczyć prawdopodobieństwo w punkcie, który ma rozkład normalny w Perlu? . Ale nie widziałem żadnego w Pythonie.

Numpyma random.normalfunkcję, ale przypomina próbkowanie, a nie jest dokładnie tym, czego chcę.

Odpowiedzi:


129

Jest jeden w 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

[Jedną rzeczą, na którą należy uważać - tylko wskazówka - jest to, że przekazywanie parametrów jest trochę szerokie. Ze względu na sposób, w jaki kod jest skonfigurowany, jeśli przypadkowo napiszesz scipy.stats.norm(mean=100, std=12)zamiast scipy.stats.norm(100, 12)lub scipy.stats.norm(loc=100, scale=12), to zaakceptuje go, ale po cichu odrzuci te dodatkowe argumenty słów kluczowych i poda wartość domyślną (0,1).]


3
Jak uzyskać prawdopodobieństwa na podstawie zakresów? Powiedz od 98 do 102?
Leon

2
@DSM: W powyższym przykładzie, kiedy mówisz scipy.stats.norm(100, 12).pdf(98), czy oznacza to prawdopodobieństwo uzyskania 98 w dystrybucji z mean 100 i stddev 12wynosi 0.032?
Srivatsan

14
@ThePredator: nie, prawdopodobieństwo uzyskania 98 w rozkładzie normalnym ze średnią 100 i odchyleniem standardowym wynosi zero. :-) Gęstość prawdopodobieństwa wynosi 0,032.
DSM

Gęstość prawdopodobieństwa w tym przypadku oznacza wartość y przy wartości x 1,42 dla rozkładu normalnego. cdf oznacza to, co nazywamy obszarem pod krzywą.
niszczenie

5
@Leon, właśnie rv.cdf(102) - rv.cdf(98)tam rv = scipy.stats.norm(100, 12).
fuglede

46

Scipy.stats to świetny moduł. Aby zaoferować inne podejście, możesz to obliczyć bezpośrednio za pomocą

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

Wykorzystuje wzór znaleziony tutaj: http://en.wikipedia.org/wiki/Normal_distribution#Probability_density_function

testować:

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

Hej, to naprawdę fajna odpowiedź. Czy mógłbyś przedstawić wyjaśnienie krok po kroku?
Llamageddon

Ta metoda wymaga mniej czasu obliczeń niż scipy
mkm

Ale scipy może obsługiwać tablice średnich, odchyleń standardowych i próbek: 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} ') dane wyjściowe: prob = [0,5 0,5 0,5] prob = [ 0,59870633 0,63055866 0,69146246] prob = [0,69146246 0,74750746 0,77337265]
John Deighan

16

Tutaj jest więcej informacji . Najpierw mamy do czynienia z rozkładem zamrożonym (w tym przypadku zamrożony oznacza, że ​​jego parametry są ustawione na określone wartości). Aby utworzyć zamrożoną dystrybucję:

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

Nie mogę wystarczająco podziękować temu, kto napisał tę odpowiedź. Szukałem wszędzie rozwiązania tego problemu, ale nie mogłem go znaleźć. Dodanie komentarzy do kodu naprawdę pomogło mi zrozumieć, co się dzieje. Wielkie dzięki.
bhola prasad

Chcę tylko zadać jedno pytanie, jak obliczyć te prawdopodobieństwa, gdy dane nie mają rozkładu normalnego? Co mam zrobić w tym przypadku?
bhola prasad

12

Zaczynając Python 3.8, biblioteka standardowa udostępnia NormalDistobiekt jako część statisticsmodułu.

Można go użyć do uzyskania funkcji gęstości prawdopodobieństwa ( pdf- prawdopodobieństwo, że próbka losowa X będzie blisko podanej wartości x) dla danej średniej ( mu) i odchylenia standardowego ( sigma):

from statistics import NormalDist

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

Należy również zauważyć, że NormalDistobiekt zapewnia również skumulowaną funkcję rozkładu ( cdf- prawdopodobieństwo, że losowa próbka X będzie mniejsza lub równa x):

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

4

W przypadku, gdy chciałbyś znaleźć obszar pomiędzy 2 wartościami x średnia = 1; odchylenie standardowe = 2; prawdopodobieństwo x między [0,5,2]

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

3

Cytowany w odpowiedziach wzór z Wikipedii nie może być użyty do obliczenia normalnych probabilitów. Aby obliczyć prawdopodobieństwo, należałoby napisać funkcję przybliżania całkowania numerycznego przy użyciu tego wzoru.

Ta formuła oblicza wartość funkcji gęstości prawdopodobieństwa. Ponieważ rozkład normalny jest ciągły, aby otrzymać prawdopodobieństwa, musisz obliczyć całkę. Witryna wikipedii wspomina o CDF, który nie ma zamkniętej formy dla normalnej dystrybucji.


3
Dziękuję za twój wkład, chociaż lepiej by pasował jako komentarz do odpowiedzi, o której się odnosisz: jeśli dobrze rozumiem, tak naprawdę nie odpowiadasz na pierwotne pytanie. W ten sposób wszyscy od razu zobaczą, o czym mówisz.
Pierre Prinetti

1

Napisałem ten program, żeby zrobić dla ciebie matematykę. Wystarczy wejść w podsumowanie statystyk. Nie ma potrzeby dostarczania tablicy:

Test Z dla jednej próbki dla proporcji populacji:

Aby to zrobić dla średniej zamiast proporcji, odpowiednio zmień wzór na z

EDYCJA:
Oto treść z linku:

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
Chociaż odsyłacz może dostarczyć cennej odpowiedzi, SO prosi użytkowników o umieszczenie swojego kodu tutaj, na SO. Linki są przydatne jako odniesienie, ale po pewnym czasie często się psują, uniemożliwiając przyszłym odwiedzającym rozwiązania.
Pan T

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.