Как рассчитать кумулятивное нормальное распределение?

100

Я ищу функцию в Numpy или Scipy (или в любой строгой библиотеке Python), которая даст мне кумулятивную функцию нормального распределения в Python.

Мартино
источник

Ответы:

125

Вот пример:

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

Другими словами, приблизительно 95% стандартного нормального интервала лежит в пределах двух стандартных отклонений, центрированных на стандартном среднем значении нуля.

Если вам нужен обратный CDF:

>>> norm.ppf(norm.cdf(1.96))
array(1.9599999999999991)
Алекс Рейнольдс
источник
9
Кроме того, вы можете указать в качестве параметров среднее значение (местоположение) и дисперсию (масштаб). например, d = норма (loc = 10,0, масштаб = 2,0); d.cdf (12.0); Подробности здесь: docs.scipy.org/doc/scipy-0.14.0/reference/generated/...
Ирван
6
@Irvan, параметр масштаба на самом деле является стандартным отклонением, а НЕ дисперсией.
qkhhly 02
2
Почему scipy называет их как locи scale? Я использовал, help(norm.ppf)но тогда, черт возьми, locи scale- нужна помощь для помощи ..
javadba
2
@javadba - расположение и масштаб - это более общие термины в статистике, которые используются для параметризации широкого диапазона распределений. Для нормального распределения они совпадают со средним значением и sd, но не так для других распределений.
Майкл Олрогге
1
@MichaelOhlrogge. Спасибо! Вот страница из NIST, объясняющая дальнейшее itl.nist.gov/div898/handbook/eda/section3/eda364.htm
javadba
40

Возможно, уже слишком поздно отвечать на вопрос, но поскольку Google по-прежнему ведет сюда людей, я решаю написать здесь свое решение.

То есть, начиная с Python 2.7, mathбиблиотека интегрировала функцию ошибокmath.erf(x)

erf()Функция может быть использована для вычисления традиционных статистических функций , таких как кумулятивного стандартного нормального распределения:

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

Ссылка:

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

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

Как связаны функция ошибки и функция стандартного нормального распределения?

WTIFS
источник
3
Это было именно то, что я искал. Если кто-то другой, кроме меня, задается вопросом, как это можно использовать для расчета «процента данных, лежащих в пределах стандартного распределения», ну: 1 - (1 - phi (1)) * 2 = 0,6827 («68% данных в пределах 1 стандарта. deviation »)
Hannes Landeholm
1
Для общего нормального распределения это было бы def phi(x, mu, sigma): return (1 + erf((x - mu) / sigma / sqrt(2))) / 2.
Бернхард Баркер,
18

Адаптировано отсюда 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
Поскольку std lib реализует math.erf (), нет необходимости в реализации sep.
Marc
я не смог найти ответ, откуда берутся эти числа?
TmSmth,
17

Начиная Python 3.8, стандартная библиотека предоставляет NormalDistобъект как часть statisticsмодуля.

Его можно использовать для получения кумулятивной функции распределения ( cdf- вероятность того, что случайная выборка X будет меньше или равна x) для данного среднего ( mu) и стандартного отклонения ( sigma):

from statistics import NormalDist

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

Что можно упростить для стандартного нормального распределения ( mu = 0и sigma = 1):

NormalDist().cdf(1.96)
# 0.9750021048517796

NormalDist().cdf(-1.96)
# 0.024997895148220428
Ксавье Гихот
источник
15

Основываясь на примере Unknown, Python-эквивалент функции 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
источник
9

Ответ Алекса показывает вам решение для стандартного нормального распределения (среднее значение = 0, стандартное отклонение = 1). Если у вас нормальное распределение с meanи std(что есть sqr(var)) и вы хотите вычислить:

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)

Узнайте больше о cdf здесь и scipy реализации нормального распределения со многими формулами здесь .

Сальвадор Дали
источник
2

Взято сверху:

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

Для двустороннего теста:

Import numpy as np
z = 1.96
p_value = 2 * norm.cdf(-np.abs(z))
0.04999579029644087
Дэвид Миллер
источник
-9

Поскольку Google дает этот ответ для поискового netlogo pdf , вот версия netlogo вышеуказанного кода Python

    ;; Кумулятивная функция плотности нормального распределения
    сообщить normcdf [x mu sigma]
        пусть tx - мю
        пусть y 0.5 * erfcc [- t / (sigma * sqrt 2.0)]
        if (y> 1.0) [установить y 1.0]
        сообщить y
    конец

    ;; Функция плотности вероятности нормального распределения
    сообщить normpdf [x mu sigma]
        пусть u = (x - mu) / abs sigma
        пусть y = 1 / (sqrt [2 * pi] * abs sigma) * exp (- u * u / 2.0)
        сообщить y
    конец

    ;; Дополнительная функция ошибок
    сообщить erfcc [x]
        пусть z abs x
        пусть t 1.0 / (1.0 + 0.5 * z)
        пусть 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 +
            т * .17087277)))))))))
        ifelse (x> = 0) [отчет r] [отчет 2.0 - r]
    конец

платиподиум
источник
6
Речь идет о Python, а не о NetLogo. Такого ответа здесь быть не должно. И, пожалуйста, не редактируйте вопрос, чтобы изменить его смысл.
Interjay
Я знаю, что это не лучший способ, но я думаю, что он наиболее полезен, поскольку люди
перенаправляются