2017-06-05 31 views
1

我想我誤解了Numpy的histogram2d rangebin的論點。Numpy 2d直方圖不總結爲1

下面是它的工作我怎麼會想到一個例子:

d, x_r, y_r = np.histogram2d(
    [0, 1, 3], 
    [0, 1, 3], 
    bins=[3, 3], 
    range=[[0, 3], [0, 3]], 
    normed=True) 

d 
array([[ 0.33333333, 0.  , 0.  ], 
     [ 0.  , 0.33333333, 0.  ], 
     [ 0.  , 0.  , 0.33333333]]) 
np.sum(d) 
1.0 

而這裏的事情開始土崩瓦解,我(增加的箱數):

d, x_r, y_r = np.histogram2d(
    [0, 1, 3], 
    [0, 1, 3], 
    bins=[3, 6], 
    range=[[0, 3], [0, 3]], 
    normed=True) 
d 
array([[ 0.66666667, 0., 0.  , 0., 0., 0.  ], 
     [ 0.  , 0., 0.66666667, 0., 0., 0.  ], 
     [ 0.  , 0., 0.  , 0., 0., 0.66666667]]) 
np.sum(d) 
2.0 

我本來期望:

d 
array([[ 0.33333333, 0., 0.  , 0., 0., 0.  ], 
     [ 0.  , 0., 0.33333333, 0., 0., 0.  ], 
     [ 0.  , 0., 0.  , 0., 0., 0.33333333]]) 

希望有任何幫助理解這一點,並得到我期待的結果。謝謝。

+0

難道你閱讀[文檔](https://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram.html)?看看規範與密度及其警告。 – sascha

+0

@sascha我確實閱讀過文檔。我會重讀這些部分並與他們一起玩。我不是一個統計學家,所以我很難理解他們。另外我使用的是沒有密度參數的2d函數。 – freebie

回答

0

np.histogram2d賦範ARG標準化如下

bin_count/sample_count/bin_area 

這需要一段時間才能理解,而source code並不在我看來,寫得很不錯(選擇不當的變量名)

  • bin_count is is the value in the histogram bin
  • sample_count是所有bin_counts的總和
  • bin_area是特定倉的區域

我們可以在這兩種情況下定義上述3個變量,而無需使用範ARG,看看怎麼回事:

案例1

bin_count, binsx, binsy = np.histogram2d([0,1,3], [0,1,3], 
    bins=[3,3], range=[[0,3],[0,3]], normed=False) 

如果你看看binsxbinsy你會看到每個區間的面積爲1

print(binsx, binsy) 
#In [54]: print (binsx, binsy) 
#(array([ 0., 1., 2., 3.]), array([ 0., 1., 2., 3.])) 

因此我們讓bin_area=1和2D直方圖標準化看起來像

bin_count/bin_count.sum()/bin_area 

#array([[ 0.33333333, 0.  , 0.  ], 
     #[ 0.  , 0.33333333, 0.  ], 
     #[ 0.  , 0.  , 0.33333333]]) 

案例2

bin_count, binsx, binsy = np.histogram2d([0,1,3], [0,1,3], 
    bins=[3,6], range=[[0,3],[0,3]], normed=False) 
print(binsx, binsy) 
#(array([ 0., 1., 2., 3.]), array([ 0. , 0.5, 1. , 1.5, 2. , 2.5, 3. ])) 

現在你可以看到你的bin_area已經通過的2倍下降(因爲你增加y-bin的數量減少2倍)

因此,我們讓bin_area=.5標準化 HIST看起來像

bin_count/bin_count.sum()/bin_area 

#array([[ 0.66666667, 0.  , 0.  , 0.  , 0.  , 
#   0.  ], 
#  [ 0.  , 0.  , 0.66666667, 0.  , 0.  , 
#   0.  ], 
#  [ 0.  , 0.  , 0.  , 0.  , 0.  , 
#   0.66666667]]) 

一般情況

一般來說,你可以有不同的尺寸的垃圾箱,因此bin_area可能是一個變量。考慮到一些非甚至垃圾桶:

bin_count, binsx, binsy = np.histogram2d([0,1,3], [0,1,3], 
    bins=([0.,1.5,3.],[0, .6, 1.7,3.]), 
    range=[[0,3],[0,3]], normed=False) 

在這種情況下,明確地計算每個區間的區域:

bin_area = np.array([ [(x1 -x0)* (y1-y0) 
    for y1,y0 in zip(binsy[1:], binsy[:-1])] 
     for x1,x0 in zip(binsx[1:], binsx[:-1]) ]) 

print(bin_area) 
#array([[ 0.9 , 1.65, 1.95], 
#  [ 0.9 , 1.65, 1.95]]) 

bin_count/bin_count.sum()/bin_area 
#array([[ 0.37037037, 0.2020202 , 0.  ], 
#  [ 0.  , 0.  , 0.17094017]]) 

事實上,如果我們設定的範ARG爲True

normed_bin_count, binsx, binsy = np.histogram2d([0,1,3], [0,1,3], 
    bins=([0.,1.5,3.],[0, .6, 1.7,3.]), 
    range=[[0,3],[0,3]], normed=True) 
print(normed_bin_count) 
#array([[ 0.37037037, 0.2020202 , 0.  ], 
#  [ 0.  , 0.  , 0.17094017]]) 
+0

太好了,謝謝。所以我需要將x和y乘以bin大小,以回到我的預期。 – freebie

+0

我認爲很容易理解,如果你認爲'bin_count'是一個bin中的樣本數,'sample_count'是樣本總數。 – Goyo

+0

@freebie如果你想要相對比例使用'normed = False',然後將每個bin數除以樣本數。這不會是一個規範直方圖。 – Goyo