Bagaimana cara menghitung probabilitas dalam distribusi normal berdasarkan mean & deviasi standar?

91

Bagaimana cara menghitung probabilitas dalam distribusi normal yang diberikan mean, std dengan Python? Saya selalu dapat secara eksplisit mengkodekan fungsi saya sendiri sesuai dengan definisi seperti yang dilakukan OP dalam pertanyaan ini: Menghitung Probabilitas Variabel Acak dalam Distribusi dengan Python

Hanya ingin tahu apakah ada panggilan fungsi perpustakaan akan memungkinkan Anda melakukan ini. Dalam bayangan saya akan seperti ini:

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

Ada pertanyaan serupa di Perl: Bagaimana saya dapat menghitung probabilitas pada titik yang diberikan distribusi normal di Perl? . Tapi saya tidak melihatnya di Python.

Numpymemiliki random.normalfungsi, tetapi seperti pengambilan sampel, tidak persis seperti yang saya inginkan.

Clwen
sumber

Jawaban:

129

Ada satu di 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

[Satu hal yang harus diperhatikan - hanya tip - adalah parameter yang lewat agak luas. Karena cara kode disiapkan, jika Anda tidak sengaja menulis scipy.stats.norm(mean=100, std=12)alih-alih scipy.stats.norm(100, 12)atau scipy.stats.norm(loc=100, scale=12), maka ia akan menerimanya, tetapi secara diam-diam membuang argumen kata kunci tambahan tersebut dan memberikan default (0,1).]

DSM
sumber
3
Bagaimana Anda mendapatkan probabilitas dari jarak? Katakan dari 98 - 102?
Leon
2
@DSM: Dalam contoh di atas Anda, ketika Anda mengatakan scipy.stats.norm(100, 12).pdf(98), apakah itu berarti probabilitas mendapatkan 98 dalam distribusi dengan mean 100 dan stddev 12adalah 0.032?
Srivatsan
14
@ThePredator: tidak, kemungkinan mendapatkan 98 dalam distribusi normal dengan mean 100 dan stddev 12 adalah nol. :-) Kepadatan probabilitasnya adalah 0,032.
DSM
Kepadatan probabilitas dalam hal itu berarti nilai y, mengingat nilai x 1,42 untuk distribusi normal. cdf artinya apa yang kita sebut sebagai area di bawah kurva.
merobek
5
@ Leon, di rv.cdf(102) - rv.cdf(98)situlah rv = scipy.stats.norm(100, 12).
fuglede
46

Scipy.stats adalah modul yang bagus. Hanya untuk menawarkan pendekatan lain, Anda dapat menghitungnya langsung menggunakan

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

Ini menggunakan rumus yang ditemukan di sini: http://en.wikipedia.org/wiki/Normal_distribution#Probability_density_function

untuk menguji:

>>> normpdf(7,5,5)  
0.07365402806066466
>>> norm(5,5).pdf(7)
0.073654028060664664
jiminy_crist
sumber
Hei, ini jawaban yang sangat bagus. Maukah Anda memberikan penjelasan langkah demi langkah, mungkin?
Llamageddon
Metode ini membutuhkan waktu komputasi yang lebih sedikit daripada scipy
mkm
Tapi scipy dapat menangani array sarana, stdevs dan sampel: mean = [5, 10, 20] stddev = [20, 30, 40] untuk x in ([5, 10, 20], [10, 20, 40], [15, 30, 50],): prob = scipy.stats.norm (mean, stddev) .cdf (x) print (f'prob = {prob} ') keluaran: prob = [0,5 0,5 0,5] prob = [ 0,59870633 0.63055866 0.69146246] prob = [0.69146246 0.74750746 0.77337265]
John Deighan
16

Berikut info selengkapnya . Pertama, Anda berurusan dengan distribusi beku (dibekukan dalam kasus ini berarti parameternya disetel ke nilai tertentu). Untuk membuat distribusi beku:

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
J. Khoury
sumber
Saya tidak bisa cukup berterima kasih kepada siapa pun yang menulis jawaban ini. Saya mencari ke mana-mana untuk menyelesaikan ini tetapi tidak dapat menemukannya. Dan menambahkan komentar dengan kode sangat membantu saya memahami apa yang terjadi. Terima kasih banyak.
bhola prasad
Hanya ingin mengajukan satu pertanyaan, bagaimana cara menghitung probabilitas tersebut ketika data tidak berdistribusi normal? Apa yang harus saya lakukan dalam kasus ini?
bhola prasad
12

Memulai Python 3.8, pustaka standar menyediakan NormalDistobjek sebagai bagian dari statisticsmodul.

Ini dapat digunakan untuk mendapatkan fungsi kepadatan probabilitas ( pdf- kemungkinan bahwa sampel acak X akan mendekati nilai yang diberikan x) untuk mean ( mu) dan deviasi standar ( sigma) tertentu:

from statistics import NormalDist

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

Perhatikan juga bahwa NormalDistobjek tersebut juga menyediakan fungsi distribusi kumulatif ( cdf- probabilitas bahwa sampel acak X akan kurang dari atau sama dengan x):

NormalDist(mu=100, sigma=12).cdf(98)
# 0.43381616738909634
Xavier Guihot
sumber
4

Jika Anda ingin mencari luas antara 2 nilai x mean = 1; deviasi standar = 2; probabilitas x antara [0,5,2]

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

Rumus yang dikutip dari wikipedia yang disebutkan dalam jawaban tidak dapat digunakan untuk menghitung probabilitas normal. Anda harus menulis fungsi perkiraan integrasi numerik menggunakan rumus itu untuk menghitung probabilitas.

Rumus tersebut menghitung nilai untuk fungsi kepadatan probabilitas. Karena distribusi normal kontinu, Anda harus menghitung integral untuk mendapatkan probabilitas. Situs wikipedia menyebutkan CDF, yang tidak memiliki bentuk tertutup untuk distribusi normal.

pengguna2724943
sumber
3
Terima kasih atas kontribusi Anda, meskipun akan lebih cocok sebagai komentar untuk jawaban yang Anda maksud: jika saya mengerti dengan baik, Anda tidak benar-benar menjawab pertanyaan awal. Dengan cara ini, semua orang akan melihat sekilas apa yang Anda bicarakan.
Pierre Prinetti
1

Saya menulis program ini untuk menghitung untuk Anda. Masukkan saja statistik ringkasan. Tidak perlu menyediakan larik:

Uji Z Satu Sampel untuk Proporsi Populasi:

Untuk melakukan ini untuk mean daripada proporsi, ubah rumus z sesuai

EDIT:
Ini konten dari tautan:

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)
derrik bosse
sumber
2
Sementara link mungkin memberikan jawaban yang berharga, SO meminta pengguna untuk memposting kode mereka di sini di SO Link berguna sebagai referensi, tetapi mereka cenderung rusak setelah beberapa saat, membuat solusi tidak dapat diakses oleh pengunjung di masa mendatang.
Tn. T
0

Anda bisa menggunakan fungsi kesalahan yang ada di perpustakaan matematika, seperti yang dinyatakan di situs web mereka .

pengguna2340146
sumber
Tidak @ user2340146, juga dengan Python 2: docs.python.org/2/library/math.html#math.erf
BoltzmannBrain