Come calcolare la distribuzione normale cumulativa?


99

Sto cercando una funzione in Numpy o Scipy (o qualsiasi libreria Python rigorosa) che mi fornisca la funzione di distribuzione normale cumulativa in Python.

Risposte:


125

Ecco un esempio:

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

In altre parole, circa il 95% dell'intervallo normale standard si trova all'interno di due deviazioni standard, centrate su una media standard pari a zero.

Se hai bisogno del CDF inverso:

>>> norm.ppf(norm.cdf(1.96))
array(1.9599999999999991)

9
Inoltre, è possibile specificare la media (loc) e la varianza (scala) come parametri. ad esempio, d = norm (loc = 10.0, scale = 2.0); d.cdf (12.0); Dettagli qui: docs.scipy.org/doc/scipy-0.14.0/reference/generated/…
Irvan

6
@ Irvan, il parametro di scala è in realtà la deviazione standard, NON la varianza.
qkhhly

2
Perché Scipy li chiama loce scale? Ho usato il help(norm.ppf)ma poi che diamine sono loce scale- ho bisogno di aiuto per l'aiuto ..
javadba

2
@javadba: posizione e scala sono termini più generali nelle statistiche che vengono utilizzati per parametrizzare un'ampia gamma di distribuzioni. Per la distribuzione normale, si allineano con mean e sd, ma non così per altre distribuzioni.
Michael Ohlrogge

1
@MichaelOhlrogge. Grazie! Ecco una pagina del NIST che spiega ulteriormente itl.nist.gov/div898/handbook/eda/section3/eda364.htm
javadba

40

Potrebbe essere troppo tardi per rispondere alla domanda, ma poiché Google guida ancora le persone qui, decido di scrivere la mia soluzione qui.

Cioè, a partire da Python 2.7, la mathlibreria ha integrato la funzione di erroremath.erf(x)

La erf()funzione può essere utilizzata per calcolare le funzioni statistiche tradizionali come la distribuzione normale standard cumulativa:

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

Rif:

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

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

Come sono correlate la funzione di errore e la funzione di distribuzione normale standard?


3
Questo era esattamente quello che stavo cercando. Se qualcun altro di me si chiede come questo possa essere utilizzato per calcolare la "percentuale di dati che si trova all'interno della distribuzione standard", beh: 1 - (1 - phi (1)) * 2 = 0,6827 ("68% di dati all'interno di 1 standard deviazione ")
Hannes Landeholm

1
Per una distribuzione normale generale, sarebbe def phi(x, mu, sigma): return (1 + erf((x - mu) / sigma / sqrt(2))) / 2.
Bernhard Barker

19

Adattato da qui 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))

3
Poiché la libreria std implementa math.erf (), non è necessaria un'implementazione sep.
Marc

non sono riuscito a trovare una risposta, da dove vengono quei numeri?
TmSmth

15

Per basarsi sull'esempio di Unknown, l'equivalente Python della funzione normdist () implementata in molte librerie sarebbe:

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

15

Iniziando Python 3.8, la libreria standard fornisce l' NormalDistoggetto come parte distatistics modulo.

Può essere utilizzato per ottenere la funzione di distribuzione cumulativa ( cdf- probabilità che un campione casuale X sia minore o uguale ax) per una data media ( mu) e deviazione standard ( sigma):

from statistics import NormalDist

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

Che può essere semplificato per la distribuzione normale standard ( mu = 0e sigma = 1):

NormalDist().cdf(1.96)
# 0.9750021048517796

NormalDist().cdf(-1.96)
# 0.024997895148220428

9

La risposta di Alex ti mostra una soluzione per la distribuzione normale standard (media = 0, deviazione standard = 1). Se hai una distribuzione normale con meane std(che è sqr(var)) e vuoi calcolare:

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)

Maggiori informazioni su cdf qui e sull'implementazione scipy della distribuzione normale con molte formule qui .


2

Preso dall'alto:

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

Per un test a due code:

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


-9

Poiché Google fornisce questa risposta per la ricerca netlogo pdf , ecco la versione netlogo del codice python sopra

    ;; Funzione di densità cumulativa di distribuzione normale
    da segnalare normcdf [x mu sigma]
        lascia tx - mu
        sia y 0.5 * erfcc [- t / (sigma * sqrt 2.0)]
        if (y> 1.0) [set y 1.0]
        rapporto y
    fine

    ;; Funzione di densità di probabilità di distribuzione normale
    da segnalare normpdf [x mu sigma]
        sia u = (x - mu) / abs sigma
        sia y = 1 / (sqrt [2 * pi] * abs sigma) * exp (- u * u / 2.0)
        rapporto y
    fine

    ;; Funzione di errore complementare
    da segnalare erfcc [x]
        sia z abs x
        sia t 1,0 / (1,0 + 0,5 * z)
        let rt * exp (- z * z -1.26551223 + t * (1.00002368 + t * (0.37409196 +
            t * (0,09678418 + t * (-0,18628806 + t * (.27886807 +
            t * (-1,13520398 + t * (1,48851587 + t * (-0,82215223 +
            t * .17087277)))))))))
        ifelse (x> = 0) [report r] [report 2.0 - r]
    fine


6
La domanda riguarda Python, non NetLogo. Questa risposta non dovrebbe essere qui. E per favore non modificare la domanda per cambiarne il significato.
Interjay

Sono consapevole che questo non è il modo preferito, ma credo che sia molto utile in questo modo poiché le persone vengono indirizzate a questa pagina da Google (attualmente ...)
platipodium
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.