2013-03-14 869 views
12

我正在做一個使用python的項目,其中有兩個數據數組。我們稱它們爲pcpnc。我需要在同一個圖表上繪製這兩者的累積分佈。對於pc它應該小於圖,即在(x,y)處,y點在pc必須具有小於x的值。對於pnc它應該是比圖更多的圖,即在(x,y)處,y點在pnc必須具有大於x的值。累積分佈圖python

我試過使用直方圖功能 - pyplot.hist。有沒有更好更簡單的方法來做我想做的事?此外,它必須在x軸上以對數刻度繪製。

+1

它會幫助,如果你表現你的企圖到目前爲止 - 樣本輸入數據,期望的輸出等...否則,這會讀作「顯示我的代碼」問題 – 2013-03-14 11:49:00

+1

爲了擴展Jon的評論,人們很高興地幫助您修復您擁有的代碼,而不是從頭開始生成代碼。不管你的代碼有多麼多的功能和非功能性,展示它並解釋你期望它做什麼和b)它目前在做什麼。 – tacaswell 2013-03-14 13:14:22

回答

24

你就近了。你不應該使用plt.hist作爲numpy.histogram,是提供給你的價值觀和垃圾箱,比你可以繪製累計輕鬆:

import numpy as np 
import matplotlib.pyplot as plt 

# some fake data 
data = np.random.randn(1000) 
# evaluate the histogram 
values, base = np.histogram(data, bins=40) 
#evaluate the cumulative 
cumulative = np.cumsum(values) 
# plot the cumulative function 
plt.plot(base[:-1], cumulative, c='blue') 
#plot the survival function 
plt.plot(base[:-1], len(data)-cumulative, c='green') 

plt.show() 

enter image description here

+0

僅供參考,您忘記在cumsum之前包含np,因爲您的np.histogram命令意味着需要。 – ehsteve 2013-12-19 18:27:21

+0

@ehsteve修復答案。 – Gabriel 2014-02-05 18:26:19

+1

@加布裏埃爾謝謝! – ehsteve 2014-02-05 22:07:52

15

使用直方圖是真的不必要的沉重,不精確(分箱會使數據模糊):您可以對所有x值進行排序:每個值的索引是較小的值的數量。這更短,更簡單的方案是這樣的:

import numpy as np 
import matplotlib.pyplot as plt 

# Some fake data: 
data = np.random.randn(1000) 

sorted_data = np.sort(data) # Or data.sort(), if data can be modified 

# Cumulative counts: 
plt.step(sorted_data, np.arange(sorted_data.size)) # From 0 to the number of data points-1 
plt.step(sorted_data[::-1], np.arange(sorted_data.size)) # From the number of data points-1 to 0 

plt.show() 

此外,一個更合適的打印樣式確實plt.step()而不是plt.plot(),因爲數據是離散的位置。

結果是:

enter image description here

你可以看到它是比EnricoGiampieri的答案的輸出更破爛,但是這一次是真正的直方圖(而不是作爲一個近似的,模糊的版本)。

PS:正如SebastianRaschka指出的,最後一點應理想地顯示總計數(而不是總計數-1)。這可以通過以下方式實現:

plt.step(np.concatenate([sorted_data, sorted_data[[-1]]]), 
     np.arange(sorted_data.size+1)) 
plt.step(np.concatenate([sorted_data[::-1], sorted_data[[0]]]), 
     np.arange(sorted_data.size+1)) 

有在data這麼多點的效果是不可見,但不縮放,但是當數據只包含幾個點,或總數的最後一點事情做。

+1

但是,對於大型數組,您希望使用直方圖方法,因爲它不需要太多內存。 'plt.step'方法爲我提供了一個6000萬個元素數組的內存錯誤。 – aaren 2014-03-26 10:52:26

+0

同意。我不確定問題出在'plt.step'還是這個確切的方法使用的可能性是陣列的內存的3倍,或者兩者都是...... – EOL 2014-03-26 14:05:52

+0

我同意:plt.step可能是更合適的方法密謀「計數」。一個問題:你不需要使用'plt.step(sorted_data,np.arange(1,data.size + 1))'來獲得正確的計數嗎? – Sebastian 2014-07-02 20:53:26

10

與@EOL確鑿的討論後,我想使用隨機高斯樣本的彙總後我的解決方案(左上):

enter image description here

import numpy as np 
import matplotlib.pyplot as plt 
from math import ceil, floor, sqrt 

def pdf(x, mu=0, sigma=1): 
    """ 
    Calculates the normal distribution's probability density 
    function (PDF). 

    """ 
    term1 = 1.0/(sqrt(2*np.pi) * sigma) 
    term2 = np.exp(-0.5 * ((x-mu)/sigma)**2) 
    return term1 * term2 


# Drawing sample date poi 
################################################## 

# Random Gaussian data (mean=0, stdev=5) 
data1 = np.random.normal(loc=0, scale=5.0, size=30) 
data2 = np.random.normal(loc=2, scale=7.0, size=30) 
data1.sort(), data2.sort() 

min_val = floor(min(data1+data2)) 
max_val = ceil(max(data1+data2)) 

################################################## 




fig = plt.gcf() 
fig.set_size_inches(12,11) 

# Cumulative distributions, stepwise: 
plt.subplot(2,2,1) 
plt.step(np.concatenate([data1, data1[[-1]]]), np.arange(data1.size+1), label='$\mu=0, \sigma=5$') 
plt.step(np.concatenate([data2, data2[[-1]]]), np.arange(data2.size+1), label='$\mu=2, \sigma=7$') 

plt.title('30 samples from a random Gaussian distribution (cumulative)') 
plt.ylabel('Count') 
plt.xlabel('X-value') 
plt.legend(loc='upper left') 
plt.xlim([min_val, max_val]) 
plt.ylim([0, data1.size+1]) 
plt.grid() 

# Cumulative distributions, smooth: 
plt.subplot(2,2,2) 

plt.plot(np.concatenate([data1, data1[[-1]]]), np.arange(data1.size+1), label='$\mu=0, \sigma=5$') 
plt.plot(np.concatenate([data2, data2[[-1]]]), np.arange(data2.size+1), label='$\mu=2, \sigma=7$') 

plt.title('30 samples from a random Gaussian (cumulative)') 
plt.ylabel('Count') 
plt.xlabel('X-value') 
plt.legend(loc='upper left') 
plt.xlim([min_val, max_val]) 
plt.ylim([0, data1.size+1]) 
plt.grid() 


# Probability densities of the sample points function 
plt.subplot(2,2,3) 

pdf1 = pdf(data1, mu=0, sigma=5) 
pdf2 = pdf(data2, mu=2, sigma=7) 
plt.plot(data1, pdf1, label='$\mu=0, \sigma=5$') 
plt.plot(data2, pdf2, label='$\mu=2, \sigma=7$') 

plt.title('30 samples from a random Gaussian') 
plt.legend(loc='upper left') 
plt.xlabel('X-value') 
plt.ylabel('probability density') 
plt.xlim([min_val, max_val]) 
plt.grid() 


# Probability density function 
plt.subplot(2,2,4) 

x = np.arange(min_val, max_val, 0.05) 

pdf1 = pdf(x, mu=0, sigma=5) 
pdf2 = pdf(x, mu=2, sigma=7) 
plt.plot(x, pdf1, label='$\mu=0, \sigma=5$') 
plt.plot(x, pdf2, label='$\mu=2, \sigma=7$') 

plt.title('PDFs of Gaussian distributions') 
plt.legend(loc='upper left') 
plt.xlabel('X-value') 
plt.ylabel('probability density') 
plt.xlim([min_val, max_val]) 
plt.grid() 

plt.show()