วิธีคำนวณการแจกแจงปกติสะสม


101

ฉันกำลังมองหาฟังก์ชันใน Numpy หรือ Scipy (หรือไลบรารี Python ที่เข้มงวด) ซึ่งจะให้ฟังก์ชันการแจกแจงปกติแบบสะสมใน Python

คำตอบ:


127

นี่คือตัวอย่าง:

>>> 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)

10
นอกจากนี้คุณสามารถระบุค่าเฉลี่ย (loc) และความแปรปรวน (มาตราส่วน) เป็นพารามิเตอร์ เช่น d = norm (loc = 10.0, scale = 2.0); d.cdf (12.0); ดูรายละเอียดที่นี่: docs.scipy.org/doc/scipy-0.14.0/reference/generated/…
Irvan

7
@Irvan พารามิเตอร์มาตราส่วนเป็นค่าเบี่ยงเบนมาตรฐานไม่ใช่ความแปรปรวน
qkhhly

2
ทำไม scipy จึงตั้งชื่อสิ่งเหล่านี้ว่าlocและscale? ฉันใช้help(norm.ppf)แต่แล้วห่าคืออะไรlocและscale- ต้องการความช่วยเหลือเพื่อขอความช่วยเหลือ ..
javadba

3
@javadba - ตำแหน่งและมาตราส่วนเป็นคำศัพท์ทั่วไปในสถิติที่ใช้ในการกำหนดพารามิเตอร์การแจกแจงที่หลากหลาย สำหรับการแจกแจงแบบปกติพวกมันจะสอดคล้องกับค่าเฉลี่ยและ sd แต่ไม่ใช่สำหรับการแจกแจงแบบอื่น
Michael Ohlrogge

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

ฟังก์ชันข้อผิดพลาดและฟังก์ชันการแจกแจงปกติมาตรฐานเกี่ยวข้องกันอย่างไร


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สำหรับการกระจายปกติทั่วไปก็จะเป็น
Bernhard Barker

20

เริ่มต้น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

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

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

10

คำตอบของอเล็กซ์แสดงวิธีแก้ปัญหาสำหรับการแจกแจงปกติมาตรฐาน (ค่าเฉลี่ย = 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


-8

เนื่องจาก Google ให้คำตอบนี้สำหรับการค้นหาnetlogo pdfนี่คือเวอร์ชัน netlogo ของโค้ด python ด้านบน

    ;; ฟังก์ชันความหนาแน่นสะสมการแจกแจงปกติ
    รายงาน normcdf [x mu sigma]
        ให้ tx - mu
        ให้ y 0.5 * erfcc [- t / (sigma * sqrt 2.0)]
        ถ้า (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 +
            เสื้อ * (0.09678418 + เสื้อ * (-0.18628806 + เสื้อ * (.27886807 +
            เสื้อ * (-1.13520398 + t * (1.48851587 + t * (-0.82215223 +
            t * .17087277))))))))
        ifelse (x> = 0) [รายงาน r] [รายงาน 2.0 - r]
    จบ


6
คำถามเกี่ยวกับ Python ไม่ใช่ NetLogo คำตอบนี้ไม่ควรอยู่ที่นี่ และโปรดอย่าแก้ไขคำถามเพื่อเปลี่ยนความหมาย
interjay

ฉันทราบว่านี่ไม่ใช่วิธีที่ต้องการ แต่ฉันคิดว่าวิธีนี้มีประโยชน์มากที่สุดเนื่องจาก Google นำผู้คนไปที่หน้านี้ (ปัจจุบัน ... )
platipodium
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.