Wie berechnet man die kumulative Normalverteilung?

99

Ich suche nach einer Funktion in Numpy oder Scipy (oder einer strengen Python-Bibliothek), die mir die kumulative Normalverteilungsfunktion in Python bietet.

Martineau
quelle

Antworten:

125

Hier ist ein Beispiel:

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

Mit anderen Worten, ungefähr 95% des Standardnormalintervalls liegen innerhalb von zwei Standardabweichungen, zentriert auf einem Standardmittelwert von Null.

Wenn Sie die inverse CDF benötigen:

>>> norm.ppf(norm.cdf(1.96))
array(1.9599999999999991)
Alex Reynolds
quelle
9
Sie können auch den Mittelwert (loc) und die Varianz (Skala) als Parameter angeben. zB d = Norm (loc = 10,0, Skala = 2,0); d.cdf (12,0); Details hier: docs.scipy.org/doc/scipy-0.14.0/reference/generated/…
Irvan
6
@Irvan, der Skalierungsparameter ist tatsächlich die Standardabweichung, NICHT die Varianz.
Qkhhly
2
Warum nennt scipy diese als locund scale? Ich benutzte das help(norm.ppf)aber dann was zum Teufel ist locund scale- brauche eine Hilfe für die Hilfe ..
javadba
2
@javadba - Ort und Maßstab sind allgemeinere Begriffe in Statistiken, die zur Parametrisierung einer Vielzahl von Verteilungen verwendet werden. Für die Normalverteilung stimmen sie mit Mittelwert und SD überein, für andere Verteilungen jedoch nicht.
Michael Ohlrogge
1
@ MichaelOhlrogge. Vielen Dank! Hier ist eine Seite von NIST, die weitere itl.nist.gov/div898/handbook/eda/section3/eda364.htm
javadba
40

Es mag zu spät sein, um die Frage zu beantworten, aber da Google immer noch Leute hierher führt, entscheide ich mich, meine Lösung hier zu schreiben.

Das heißt, seit Python 2.7 hat die mathBibliothek die Fehlerfunktion integriertmath.erf(x)

Die erf()Funktion kann verwendet werden, um traditionelle statistische Funktionen wie die kumulative Standardnormalverteilung zu berechnen:

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

Wie hängen die Fehlerfunktion und die Standardnormalverteilungsfunktion zusammen?

WTIFS
quelle
3
Genau das habe ich gesucht. Wenn sich jemand anders als ich fragt, wie dies zur Berechnung des "Prozentsatzes der Daten, die innerhalb der Standardverteilung liegen" verwendet werden kann, gilt Folgendes: 1 - (1 - phi (1)) * 2 = 0,6827 ("68% der Daten innerhalb eines Standards" Abweichung ")
Hannes Landeholm
1
Für eine allgemeine Normalverteilung wäre es def phi(x, mu, sigma): return (1 + erf((x - mu) / sigma / sqrt(2))) / 2.
Bernhard Barker
19

Angepasst von hier 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))
Unbekannt
quelle
3
Da die std lib math.erf () implementiert, ist keine sep-Implementierung erforderlich.
Marc
Ich konnte keine Antwort finden. Woher kommen diese Zahlen?
TmSmth
15

Um auf dem Beispiel von Unknown aufzubauen, wäre das Python-Äquivalent der in vielen Bibliotheken implementierten Funktion normdist ():

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

Ab Python 3.8dem Start stellt die Standardbibliothek das NormalDistObjekt als Teil des statisticsModuls bereit .

Es kann verwendet werden, um die kumulative Verteilungsfunktion ( cdf- Wahrscheinlichkeit, dass eine Zufallsstichprobe X kleiner oder gleich x ist) für einen gegebenen Mittelwert ( mu) und eine Standardabweichung ( sigma) zu erhalten:

from statistics import NormalDist

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

Was für die Standardnormalverteilung ( mu = 0und sigma = 1) vereinfacht werden kann :

NormalDist().cdf(1.96)
# 0.9750021048517796

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

Alex 'Antwort zeigt Ihnen eine Lösung für die Standardnormalverteilung (Mittelwert = 0, Standardabweichung = 1). Wenn Sie eine Normalverteilung mit meanund std(was ist sqr(var)) haben und berechnen möchten:

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)

Lesen Sie hier mehr über cdf und die einfache Implementierung der Normalverteilung mit vielen Formeln hier .

Salvador Dali
quelle
2

Von oben genommen:

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

Für einen zweiseitigen Test:

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

Da Google diese Antwort für das Such- Netlogo-PDF gibt , finden Sie hier die Netlogo-Version des obigen Python-Codes

    ;; Funktion der kumulativen Dichte der Normalverteilung
    zu melden normcdf [x mu sigma]
        lass tx - mu
        sei y 0,5 * erfcc [- t / (Sigma * sqrt 2,0)]
        if (y> 1.0) [setze y 1.0]
        Bericht y
    Ende

    ;; Normalverteilungswahrscheinlichkeitsdichtefunktion
    zu melden normpdf [x mu sigma]
        sei u = (x - mu) / abs Sigma
        sei y = 1 / (sqrt [2 * pi] * abs sigma) * exp (- u * u / 2,0)
        Bericht y
    Ende

    ;; Ergänzende Fehlerfunktion
    zu melden erfcc [x]
        sei z abs x
        sei t 1,0 / (1,0 + 0,5 * z)
        sei 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) [Bericht r] [Bericht 2.0 - r]
    Ende

Platipodium
quelle
6
Die Frage bezieht sich auf Python, nicht auf NetLogo. Diese Antwort sollte nicht hier sein. Und bitte bearbeiten Sie die Frage nicht, um ihre Bedeutung zu ändern.
Interjay
Ich bin mir bewusst, dass dies nicht der bevorzugte Weg ist, aber ich denke, es ist am hilfreichsten, da die Leute von Google (derzeit ...) auf diese Seite geleitet werden
Platipodium