Bagaimana cara menghitung distribusi normal kumulatif?

99

Saya mencari fungsi di Numpy atau Scipy (atau pustaka Python yang ketat) yang akan memberi saya fungsi distribusi normal kumulatif dengan Python.

martineau.dll
sumber

Jawaban:

125

Berikut contohnya:

>>> from scipy.stats import norm
>>> norm.cdf(1.96)
0.9750021048517795
>>> norm.cdf(-1.96)
0.024997895148220435

Dengan kata lain, kira-kira 95% dari interval normal standar terletak dalam dua deviasi standar, berpusat pada mean standar nol.

Jika Anda membutuhkan CDF terbalik:

>>> norm.ppf(norm.cdf(1.96))
array(1.9599999999999991)
Alex Reynolds
sumber
9
Selain itu, Anda dapat menentukan mean (loc) dan variance (scale) sebagai parameter. misalnya, d = norma (loc = 10.0, skala = 2.0); d.cdf (12.0); Detail di sini: docs.scipy.org/doc/scipy-0.14.0/reference/generated/…
Irvan
6
@ Irvan, parameter skala sebenarnya adalah deviasi standar, BUKAN varians.
qkhhly
2
Mengapa scipy menamai ini sebagai locdan scale? Saya menggunakan help(norm.ppf)tapi kemudian apa itu locdan scale- butuh bantuan untuk bantuan ..
javadba
2
@javadba - lokasi dan skala adalah istilah yang lebih umum dalam statistik yang digunakan untuk membuat parameter dalam berbagai distribusi. Untuk distribusi normal, mereka berbaris dengan mean dan sd, tetapi tidak demikian untuk distribusi lain.
Michael Ohlrogge
1
@Tokopedia Terima kasih! Berikut adalah halaman dari NIST yang menjelaskan lebih lanjut itl.nist.gov/div898/handbook/eda/section3/eda364.htm
javadba
40

Mungkin sudah terlambat untuk menjawab pertanyaan tersebut tetapi karena Google masih mengarahkan orang ke sini, saya memutuskan untuk menulis solusi saya di sini.

Artinya, sejak Python 2.7, mathpustaka telah mengintegrasikan fungsi kesalahanmath.erf(x)

The erf()fungsi dapat digunakan untuk menghitung fungsi statistik tradisional seperti kumulatif distribusi normal standar:

from math import *
def phi(x):
    #'Cumulative distribution function for the standard normal distribution'
    return (1.0 + erf(x / sqrt(2.0))) / 2.0

Ref:

https://docs.python.org/2/library/math.html

https://docs.python.org/3/library/math.html

Bagaimana hubungan Fungsi Kesalahan dan fungsi distribusi Normal Standar?

WTIFS
sumber
3
Inilah yang saya cari. Jika orang lain selain saya bertanya-tanya bagaimana ini dapat digunakan untuk menghitung "persentase data yang berada dalam distribusi standar", maka: 1 - (1 - phi (1)) * 2 = 0,6827 ("68% data dalam 1 standar deviasi ")
Hannes Landeholm
1
Untuk distribusi normal umum, itu akan menjadi def phi(x, mu, sigma): return (1 + erf((x - mu) / sigma / sqrt(2))) / 2.
Bernhard Barker
19

Diadaptasi dari sini http://mail.python.org/pipermail/python-list/2000-June/039873.html

from math import *
def erfcc(x):
    """Complementary error function."""
    z = abs(x)
    t = 1. / (1. + 0.5*z)
    r = t * exp(-z*z-1.26551223+t*(1.00002368+t*(.37409196+
        t*(.09678418+t*(-.18628806+t*(.27886807+
        t*(-1.13520398+t*(1.48851587+t*(-.82215223+
        t*.17087277)))))))))
    if (x >= 0.):
        return r
    else:
        return 2. - r

def ncdf(x):
    return 1. - 0.5*erfcc(x/(2**0.5))
Tidak diketahui
sumber
3
Karena std lib mengimplementasikan math.erf (), tidak diperlukan implementasi sep.
Marc
saya tidak dapat menemukan jawaban, darimana angka-angka itu berasal?
TmSmth
15

Untuk membangun di atas contoh Unknown, Python yang setara dengan fungsi normdist () yang diterapkan di banyak perpustakaan adalah:

def normcdf(x, mu, sigma):
    t = x-mu;
    y = 0.5*erfcc(-t/(sigma*sqrt(2.0)));
    if y>1.0:
        y = 1.0;
    return y

def normpdf(x, mu, sigma):
    u = (x-mu)/abs(sigma)
    y = (1/(sqrt(2*pi)*abs(sigma)))*exp(-u*u/2)
    return y

def normdist(x, mu, sigma, f):
    if f:
        y = normcdf(x,mu,sigma)
    else:
        y = normpdf(x,mu,sigma)
    return y
Cerin
sumber
15

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

Ini dapat digunakan untuk mendapatkan fungsi distribusi kumulatif ( cdf- probabilitas bahwa sampel acak X akan kurang dari atau sama dengan x) untuk mean ( mu) dan deviasi standar ( sigma) tertentu:

from statistics import NormalDist

NormalDist(mu=0, sigma=1).cdf(1.96)
# 0.9750021048517796

Yang dapat disederhanakan untuk distribusi normal standar ( mu = 0dan sigma = 1):

NormalDist().cdf(1.96)
# 0.9750021048517796

NormalDist().cdf(-1.96)
# 0.024997895148220428
Xavier Guihot
sumber
9

Jawaban Alex menunjukkan solusi untuk distribusi normal standar (rata-rata = 0, simpangan baku = 1). Jika Anda memiliki distribusi normal dengan meandan std(yang mana sqr(var)) dan Anda ingin menghitung:

from scipy.stats import norm

# cdf(x < val)
print norm.cdf(val, m, s)

# cdf(x > val)
print 1 - norm.cdf(val, m, s)

# cdf(v1 < x < v2)
print norm.cdf(v2, m, s) - norm.cdf(v1, m, s)

Baca lebih lanjut tentang cdf di sini dan implementasi scipy dari distribusi normal dengan banyak rumus di sini .

Salvador Dali
sumber
2

Diambil dari atas:

from scipy.stats import norm
>>> norm.cdf(1.96)
0.9750021048517795
>>> norm.cdf(-1.96)
0.024997895148220435

Untuk pengujian dua sisi:

Import numpy as np
z = 1.96
p_value = 2 * norm.cdf(-np.abs(z))
0.04999579029644087
David Miller
sumber
-9

Saat Google memberikan jawaban ini untuk pencarian netlogo pdf , inilah versi netlogo dari kode python di atas

    ;; Fungsi kepadatan kumulatif distribusi normal
    untuk melaporkan normcdf [x mu sigma]
        biarkan tx - mu
        misalkan y 0,5 * erfcc [- t / (sigma * sqrt 2.0)]
        if (y> 1.0) [set y 1.0]
        laporkan y
    akhir

    ;; Fungsi kepadatan probabilitas distribusi normal
    untuk melaporkan normpdf [x mu sigma]
        misalkan u = (x - mu) / abs sigma
        misalkan y = 1 / (akar [2 * pi] * abs sigma) * exp (- u * u / 2.0)
        laporkan y
    akhir

    ;; Fungsi kesalahan pelengkap
    untuk melaporkan erfcc [x]
        biarkan z abs x
        misalkan t 1.0 / (1.0 + 0.5 * z)
        biarkan rt * exp (- z * z -1.26551223 + t * (1.00002368 + t * (0.37409196 +
            t * (0,09678418 + t * (-0,18628806 + t * (0,27886807 +
            t * (-1.13520398 + t * (1.48851587 + t * (-0.82215223 +
            t * .17087277)))))))))
        ifelse (x> = 0) [report r] [report 2.0 - r]
    akhir

platipodium.dll
sumber
6
Pertanyaannya adalah tentang Python, bukan NetLogo. Jawaban ini seharusnya tidak ada di sini. Dan tolong jangan edit pertanyaan untuk mengubah artinya.
interjay
Saya sadar bahwa ini bukan cara yang disukai, tapi saya rasa cara ini paling membantu karena orang diarahkan ke halaman ini oleh google (saat ini ...)
platipodium