Berechnen Sie die Wahrscheinlichkeit in der Normalverteilung bei gegebenem Mittelwert, Standard in Python

87

Wie berechnet man die Wahrscheinlichkeit in der Normalverteilung bei gegebenem Mittelwert, Standard in Python? Ich kann meine eigene Funktion immer explizit gemäß der Definition codieren, wie es das OP in dieser Frage getan hat: Berechnung der Wahrscheinlichkeit einer Zufallsvariablen in einer Verteilung in Python

Wenn Sie sich nur fragen, ob es einen Bibliotheksfunktionsaufruf gibt, können Sie dies tun. In meiner Vorstellung würde es so aussehen:

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

In Perl gibt es eine ähnliche Frage: Wie kann ich die Wahrscheinlichkeit an einem Punkt berechnen, an dem eine Normalverteilung in Perl gegeben ist? . Aber ich habe keinen in Python gesehen.

Numpyhat eine random.normalFunktion, aber es ist wie Sampling, nicht genau das, was ich will.

Clwen
quelle

Antworten:

127

Es gibt eine in 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

[Eine Sache, auf die Sie achten sollten - nur ein Tipp - ist, dass die Parameterübergabe etwas breit ist. Wenn Sie versehentlich scipy.stats.norm(mean=100, std=12)anstelle von scipy.stats.norm(100, 12)oder schreiben, wird der Code aufgrund der Art und Weise, wie er eingerichtet ist, scipy.stats.norm(loc=100, scale=12)akzeptiert. Verwerfen Sie diese zusätzlichen Schlüsselwortargumente jedoch stillschweigend und geben Sie den Standardwert (0,1) an.]

DSM
quelle
3
Wie würden Sie Wahrscheinlichkeiten aus Bereichen erhalten? Sprich von 98 - 102?
Leon
2
@DSM: In Ihrem obigen Beispiel, wenn Sie sagen scipy.stats.norm(100, 12).pdf(98), bedeutet , dass die Wahrscheinlichkeit , mit 98 in einer Verteilung bekommen mean 100 und stddev 12ist 0.032?
Srivatsan
14
@ThePredator: Nein, die Wahrscheinlichkeit, 98 in einer Normalverteilung mit Mittelwert 100 und Standard 12 zu erhalten, ist Null. :-) Die Wahrscheinlichkeitsdichte beträgt 0,032.
DSM
Wahrscheinlichkeitsdichte bedeutet in diesem Fall den y-Wert bei einem x-Wert von 1,42 für die Normalverteilung. cdf bedeutet das, was wir als Fläche unter der Kurve bezeichnen.
Zerkleinern
4
@Leon, rv.cdf(102) - rv.cdf(98)dort ist rv = scipy.stats.norm(100, 12).
Fuglede
43

Scipy.stats ist ein großartiges Modul. Um einen anderen Ansatz anzubieten, können Sie ihn direkt mit berechnen

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

Hierbei wird die hier angegebene Formel verwendet: http://en.wikipedia.org/wiki/Normal_distribution#Probability_density_function

zu testen:

>>> normpdf(7,5,5)  
0.07365402806066466
>>> norm(5,5).pdf(7)
0.073654028060664664
jiminy_crist
quelle
Hey, das ist eine wirklich schöne Antwort. Würde es Ihnen vielleicht etwas ausmachen, eine schrittweise Erklärung abzugeben?
Llamageddon
Diese Methode benötigt weniger Rechenzeit als scipy
mkm
Aber scipy kann mit Arrays von Mittelwerten, stdevs und Stichproben umgehen: mean = [5, 10, 20] stddev = [20, 30, 40] für x in ([5, 10, 20], [10, 20, 40], [15, 30, 50],): prob = scipy.stats.norm (Mittelwert, stddev) .cdf (x) print (f'prob = {prob} ') gibt aus: prob = [0,5 0,5 0,5] prob = [ 0,59870633 0,63055866 0,69146246] prob = [0,69146246 0,74750746 0,77337265]
John Deighan
13

Hier gibt es mehr Infos . Zuerst haben Sie es mit einer eingefrorenen Verteilung zu tun (eingefroren bedeutet in diesem Fall, dass ihre Parameter auf bestimmte Werte eingestellt sind). So erstellen Sie eine eingefrorene Verteilung:

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

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

Es kann verwendet werden, um die Wahrscheinlichkeitsdichtefunktion ( pdf- Wahrscheinlichkeit, dass eine Zufallsstichprobe X nahe dem gegebenen Wert x liegt) für einen gegebenen Mittelwert ( mu) und eine gegebene Standardabweichung ( sigma) zu erhalten:

from statistics import NormalDist

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

Beachten Sie auch, dass das NormalDistObjekt auch die kumulative Verteilungsfunktion bereitstellt ( cdf- Wahrscheinlichkeit, dass eine Zufallsstichprobe X kleiner oder gleich x ist):

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

Falls Sie den Bereich zwischen 2 Werten von x mean = 1 finden möchten; Standardabweichung = 2; die Wahrscheinlichkeit von x zwischen [0,5,2]

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

Die in den Antworten erwähnte Formel aus Wikipedia kann nicht zur Berechnung normaler Wahrscheinlichkeiten verwendet werden. Sie müssten eine numerische Integrationsnäherungsfunktion unter Verwendung dieser Formel schreiben, um die Wahrscheinlichkeit zu berechnen.

Diese Formel berechnet den Wert für die Wahrscheinlichkeitsdichtefunktion. Da die Normalverteilung stetig ist, müssen Sie ein Integral berechnen, um Wahrscheinlichkeiten zu erhalten. Die Wikipedia-Site erwähnt die CDF, die keine geschlossene Form für die Normalverteilung hat.

user2724943
quelle
3
Vielen Dank für Ihren Beitrag, obwohl er besser als Kommentar zu der Antwort passt, auf die Sie sich beziehen: Wenn ich das gut verstehe, beantworten Sie die ursprüngliche Frage nicht wirklich . Auf diese Weise sieht jeder auf den ersten Blick, wovon Sie sprechen.
Pierre Prinetti
1

Ich habe dieses Programm geschrieben, um die Mathematik für Sie zu erledigen. Geben Sie einfach die zusammenfassende Statistik ein. Sie müssen kein Array bereitstellen:

Z-Test mit einer Stichprobe für einen Bevölkerungsanteil:

Um dies eher für den Mittelwert als für den Anteil zu tun, ändern Sie die Formel für z entsprechend

EDIT:
Hier ist der Inhalt des Links:

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
quelle
2
Während der Link möglicherweise eine wertvolle Antwort liefert, bittet SO Benutzer, ihren Code hier auf SO zu veröffentlichen. Links sind als Referenz nützlich, brechen jedoch nach einer Weile ab und machen Lösungen für zukünftige Besucher unzugänglich.
Herr T