Làm thế nào để tính toán xác suất trong một phân phối chuẩn cho giá trị trung bình & độ lệch chuẩn?


91

Làm thế nào để tính toán xác suất trong phân phối chuẩn cho trước trung bình, std trong Python? Tôi luôn có thể viết mã rõ ràng hàm của riêng mình theo định nghĩa như OP trong câu hỏi này đã làm: Tính xác suất của một biến ngẫu nhiên trong một phân phối bằng Python

Chỉ cần tự hỏi nếu có một lệnh gọi hàm thư viện sẽ cho phép bạn làm điều này. Trong tưởng tượng của tôi, nó sẽ như thế này:

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

Có một câu hỏi tương tự trong Perl: Làm cách nào tôi có thể tính xác suất tại một điểm cho trước có phân phối chuẩn trong Perl? . Nhưng tôi không thấy một cái nào bằng Python.

Numpycó một random.normalchức năng, nhưng nó giống như lấy mẫu, không chính xác như những gì tôi muốn.

Câu trả lời:


129

Có một trong 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

[Một điều cần lưu ý - chỉ là một mẹo - là tham số truyền hơi rộng. Do cách thiết lập mã, nếu bạn vô tình viết scipy.stats.norm(mean=100, std=12)thay vì scipy.stats.norm(100, 12)hoặc scipy.stats.norm(loc=100, scale=12), thì nó sẽ chấp nhận nó, nhưng âm thầm loại bỏ các đối số từ khóa bổ sung đó và cung cấp cho bạn giá trị mặc định (0,1).]


3
Làm thế nào bạn có được xác suất từ ​​các phạm vi? Nói từ 98 - 102?
Leon

2
@DSM: Trong ví dụ trên của bạn, khi bạn nói scipy.stats.norm(100, 12).pdf(98), điều đó có nghĩa là xác suất nhận được 98 trong phân phối với mean 100 stddev 120.032?
Srivatsan

14
@ThePredator: không, xác suất nhận được 98 trong phân phối chuẩn với trung bình 100 và stddev 12 là 0. :-) Mật độ xác suất là 0,032.
DSM

Mật độ xác suất trong trường hợp đó có nghĩa là giá trị y, cho giá trị x 1,42 cho phân phối chuẩn. cdf có nghĩa là những gì chúng tôi gọi là khu vực dưới đường cong.
băm nhỏ

5
@Leon, đó là rv.cdf(102) - rv.cdf(98)nơi rv = scipy.stats.norm(100, 12).
fuglede

46

Scipy.stats là một mô-đun tuyệt vời. Chỉ để đưa ra một cách tiếp cận khác, bạn có thể tính toán nó trực tiếp bằng cách sử dụng

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

Điều này sử dụng công thức được tìm thấy tại đây: http://en.wikipedia.org/wiki/Normal_distribution#Probability_density_ Chức năng

để kiểm tra:

>>> normpdf(7,5,5)  
0.07365402806066466
>>> norm(5,5).pdf(7)
0.073654028060664664

Này, đây là một câu trả lời rất hay. Bạn có thể vui lòng cung cấp giải thích từng bước không?
Llamageddon

Phương pháp này cần ít thời gian tính toán hơn so với scipy
mkm

Nhưng scipy có thể xử lý mảng phương tiện, stdev và mẫu: mean = [5, 10, 20] stddev = [20, 30, 40] for x in ([5, 10, 20], [10, 20, 40], [15, 30, 50],): prob = scipy.stats.norm (mean, stddev) .cdf (x) print (f'prob = {prob} ') đầu ra: prob = [0,5 0,5 0,5] prob = [ 0,59870633 0,63055866 0,69146246] prob = [0,69146246 0,74750746 0,77337265]
John Deighan

16

Đây là thông tin thêm . Trước tiên, bạn đang xử lý một phân phối cố định (đóng băng trong trường hợp này có nghĩa là các tham số của nó được đặt thành các giá trị cụ thể). Để tạo phân phối cố định:

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

Tôi không thể cảm ơn đủ người đã viết câu trả lời này. Tôi đã tìm khắp nơi để giải quyết vấn đề này nhưng không thể tìm thấy nó. Và thêm các bình luận với mã thực sự đã giúp tôi hiểu những gì đang xảy ra. Cảm ơn rất nhiều.
bhola prasad

Chỉ muốn hỏi một câu, làm thế nào để tính toán các xác suất này khi dữ liệu không được phân phối chuẩn? Tôi phải làm gì trong trường hợp này?
bhola prasad

11

Bắt đầu Python 3.8, thư viện chuẩn cung cấp NormalDistđối tượng như một phần của statisticsmô-đun.

Nó có thể được sử dụng để lấy hàm mật độ xác suất ( pdf- khả năng một mẫu ngẫu nhiên X sẽ gần giá trị x cho trước) cho một giá trị trung bình nhất định ( mu) và độ lệch chuẩn ( sigma):

from statistics import NormalDist

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

Cũng lưu ý rằng NormalDistđối tượng cũng cung cấp hàm phân phối tích lũy ( cdf- xác suất để một mẫu ngẫu nhiên X sẽ nhỏ hơn hoặc bằng x):

NormalDist(mu=100, sigma=12).cdf(98)
# 0.43381616738909634

4

Trong trường hợp bạn muốn tìm vùng giữa 2 giá trị của x mean = 1; độ lệch chuẩn = 2; xác suất của x trong khoảng [0,5,2]

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

3

Công thức được trích dẫn từ wikipedia được đề cập trong các câu trả lời không thể được sử dụng để tính toán xác suất bình thường. Bạn sẽ phải viết một hàm xấp xỉ tích phân số bằng công thức đó để tính xác suất.

Công thức đó tính giá trị cho hàm mật độ xác suất. Vì phân phối chuẩn là liên tục, bạn phải tính tích phân để có xác suất. Trang wikipedia đề cập đến CDF, không có dạng đóng cho phân phối chuẩn.


3
Cảm ơn bạn đã đóng góp, mặc dù nó sẽ phù hợp hơn khi là một nhận xét cho câu trả lời bạn đang tham khảo: nếu tôi hiểu rõ, bạn không thực sự trả lời câu hỏi ban đầu. Bằng cách này, ngay từ cái nhìn đầu tiên, mọi người sẽ nhìn thấy những gì bạn đang nói.
Pierre Prinetti

1

Tôi đã viết chương trình này để làm toán cho bạn. Chỉ cần nhập thống kê tóm tắt. Không cần cung cấp một mảng:

Kiểm tra Z một mẫu cho một tỷ lệ dân số:

Để làm điều này cho giá trị trung bình thay vì tỷ lệ, hãy thay đổi công thức cho z cho phù hợp

CHỈNH SỬA:
Đây là nội dung từ liên kết:

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)

2
Mặc dù liên kết có thể cung cấp một câu trả lời có giá trị, SO yêu cầu người dùng đăng mã của họ tại đây trên SO Các liên kết hữu ích như một tài liệu tham khảo, nhưng chúng có xu hướng bị hỏng sau một thời gian, khiến các giải pháp không thể truy cập được đối với những khách truy cập trong tương lai.
Ông T

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.