1. 程式人生 > 程式設計 >使用python繪製cdf的多種實現方法

使用python繪製cdf的多種實現方法

首先我們先用隨機函式編造一個包含1000個數值的一維numpy陣列,如下:

// An highlighted block
rng = np.random.RandomState(seed=12345)
samples = stats.norm.rvs(size=1000,random_state=rng)

接下來我們將使用各種方法畫出以上資料的累積分佈圖

1、matplotlib.pyplot.hist()

  def hist(self,x,bins=None,range=None,density=None,weights=None,cumulative=False,bottom=None,histtype='bar',align='mid',orientation='vertical',rwidth=None,log=False,color=None,label=None,stacked=False,normed=None,**kwargs):

第一種方法,我們使用matplotlib圖形庫中的hist函式,熟悉該庫的人應該知道這是一個直方圖繪製函式,以上是從API中找到的hist函式的所有引數,我們給出一維陣列或者列表x,使用hist畫出該資料的直方圖。

直方圖有兩種形式,分別是概率分佈直方圖和累積分佈直方圖(可能說的不準確- -!),可以通過引數cucumulative來調節,預設為False,畫出的是PDF,那麼True畫出的便是CDF直方圖。

PDF(figure1)可以觀察到整個資料在橫軸範圍內的分佈,CDF(figure2)則可以看出不同的資料分佈間的差異性,也可以觀察到整個資料的增長趨勢和波動情況。

使用python繪製cdf的多種實現方法

上圖是概率分佈直方圖,縱軸代表概率,如果置引數normed=False,縱軸代表頻數

使用python繪製cdf的多種實現方法

如果我們要觀察兩種資料分佈的差異,可能使用直方圖就不是很直觀,各種直方柱會相互重疊,我們只需更改直方圖的影象型別,令histtype=‘step',就會畫出一條曲線來(Figure3,實際上就是將直方柱並在一起,除邊界外顏色透明),類似於累積分佈曲線。這時,我們就能很好地觀察到不同資料分佈曲線間的差異。

使用python繪製cdf的多種實現方法

2、numpy.histogram

def histogram(a,bins=10,normed=False,density=None)

第二種方法我們使用numpy中畫直方圖的函式histogram,該函式不是一個直接的繪圖函式(廢話- -!過渡句,哈哈),給定一組資料a,它會返回兩個陣列hist和bin_edges,預設情況下hist是資料在各個區間上的頻率,bin_edges是劃分的各個區間的邊界,說到這我們大概可以想到其實該函式算是上一個函式的底層函式,我們可以依據得到的這兩個陣列來畫直方圖,我們也可以用頻率陣列來直接畫分佈曲線(Figure4)

使用python繪製cdf的多種實現方法

這裡我只給出了一個最原始的影象,直接用hist陣列畫的,如果想要變成合格的累積分佈曲線圖,縱軸為概率(頻率乘區間長度),橫軸為區間(從bin_edges陣列中取n-1個)就可以了

3、stats.relfreq

def relfreq(a,numbins=10,defaultreallimits=None,weights=None)
Returns
-------
frequency : ndarray
  Binned values of relative frequency.
lowerlimit : float
  Lower real limit
binsize : float
  Width of each bin.
extrapoints : int
  Extra points.

第三種方法我們使用stats中的relfreq函式,該函式和第二種的方法類似,也並非是直接畫圖,而是返回關於直方圖的一些資料,這裡的frequency直接是概率而非頻率,可以直接作為CDF圖的縱軸,但是橫軸需要自己計算,計算公式:

res.lowerlimit + np.linspace(0,res.binsize*res.frequency.size,res.frequency.size)

這個公式應該很好理解,我就不多說了,當然這些返回值都要依賴我們所給出的bins的數目。下面我給出一段程式碼,便是使用stats.relfreq畫出概率分佈直方圖和累積分佈曲線圖。

rng = np.random.RandomState(seed=12345)
samples = stats.norm.rvs(size=1000,random_state=rng)
res = stats.relfreq(samples,numbins=25)
x = res.lowerlimit + np.linspace(0,res.frequency.size)
fig = plt.figure(figsize=(5,4))
ax = fig.add_subplot(1,1,1)
ax.bar(x,res.frequency,width=res.binsize)
ax.set_title('Relative frequency histogram')
ax.set_xlim([x.min(),x.max()])
plt.show()

使用python繪製cdf的多種實現方法

rng = np.random.RandomState(seed=12345)
samples = stats.norm.rvs(size=1000,res.frequency.size)
y=np.cumsum(res.frequency)
plt.plot(x,y)
plt.title('Figure6 累積分佈直方圖')
plt.show()

使用python繪製cdf的多種實現方法

以上就是本人整理出來的關於畫cdf直方圖和曲線的三種方法,整理這方面東西的初忠是在發現在進行資料分析的時候,概率分佈直方圖只能觀察到資料大概的分佈情況,而在不同的資料樣本進行比較時卻很難直觀滴反映其差異性,通過看論文發現cdf可以做到這一點。

本人並不是數學專業出身,想要表達其意義,但有些描述和用詞不當,大家借鑑就好。希望大家多多支援我們!