2010-02-16 26 views
13

我想獲取包含在直方圖庫中的數據的列表。我使用numpy和Matplotlib。我知道如何遍歷數據並檢查垃圾箱邊緣。但是,我想爲2D直方圖做這件事,而代碼做這件事相當醜陋。 numpy是否有任何構造使這更容易?如何在直方圖庫中獲取數據

對於一維情況,我可以使用searchsorted()。但是邏輯並沒有那麼好,而且我不想在每個數據點上進行二進制搜索。

大部分討厭的邏輯是由於bin邊界區域。所有地區都有這樣的邊界:[左邊緣,右邊緣]。除了最後一個箱子,它有這樣一個區域:[左邊緣,右邊緣]。

這裏是一維情況下,一些示例代碼:

import numpy as np 

data = [0, 0.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 3] 

hist, edges = np.histogram(data, bins=3) 

print 'data =', data 
print 'histogram =', hist 
print 'edges =', edges 

getbin = 2 #0, 1, or 2 

print '---' 
print 'alg 1:' 

#for i in range(len(data)): 
for d in data: 
    if d >= edges[getbin]: 
     if (getbin == len(edges)-2) or d < edges[getbin+1]: 
      print 'found:', d 
     #end if 
    #end if 
#end for 

print '---' 
print 'alg 2:' 

for d in data: 
    val = np.searchsorted(edges, d, side='right')-1 
    if val == getbin or val == len(edges)-1: 
     print 'found:', d 
    #end if 
#end for 

下面是2D情況下,一些示例代碼:

import numpy as np 

xdata = [0, 1.5, 1.5, 2.5, 2.5, 2.5, \ 
     0.5, 0.5, 0.5, 0.5, 1.5, 1.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, \ 
     0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 3] 
ydata = [0, 5,5, 5, 5, 5, \ 
     15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, \ 
     25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 30] 

xbins = 3 
ybins = 3 
hist2d, xedges, yedges = np.histogram2d(xdata, ydata, bins=(xbins, ybins)) 

print 'data2d =', zip(xdata, ydata) 
print 'hist2d =' 
print hist2d 
print 'xedges =', xedges 
print 'yedges =', yedges 

getbin2d = 5 #0 through 8 

print 'find data in bin #', getbin2d 

xedge_i = getbin2d % xbins 
yedge_i = int(getbin2d/xbins) #IMPORTANT: this is xbins 

for x, y in zip(xdata, ydata): 
    # x and y left edges 
    if x >= xedges[xedge_i] and y >= yedges[yedge_i]: 
     #x right edge 
     if xedge_i == xbins-1 or x < xedges[xedge_i + 1]: 
      #y right edge 
      if yedge_i == ybins-1 or y < yedges[yedge_i + 1]: 
       print 'found:', x, y 
      #end if 
     #end if 
    #end if 
#end for 

是否有一個更清潔/更有效的方式來做到這一點?看起來numpy似乎會有這個東西。

+3

只是出於好奇;爲什麼在代碼中使用#end這樣的註釋? 「每一個像素點」通過這樣做,你忽略了縮進的目的。 – 2010-02-16 23:18:42

+3

2個原因。我是第一個C++開發人員,第二個是Python開發人員。 Python缺乏支撐激怒了我。當我有複雜的代碼塊有很多不同的縮進,我不想計算空白。我在Emacs中做了大部分的開發工作。通過在代碼塊中加入關閉註釋,它可以讓我在每行上按TAB,並且Emacs不會錯誤地縮進某些東西。 – Ben 2010-02-19 02:53:35

回答

21

digitize,從核心NumPy的,會給你指數到您的直方圖中的每個值所屬的倉

import numpy as NP 
A = NP.random.randint(0, 10, 100) 

bins = NP.array([0., 20., 40., 60., 80., 100.]) 

# d is an index array holding the bin id for each point in A 
d = NP.digitize(A, bins)  
+0

這幾乎完美!如果在這裏有任何numpy開發者,這個函數應該真正進入直方圖文檔的「另見」部分。 儘管如此,數字化()二進制邏輯與直方圖()二進制邏輯不完全匹配的結果是非常糟糕的。所以這會導致與上述其他示例一樣尷尬的代碼。 – Ben 2010-02-19 02:48:10

+1

與bins.searchsorted(A,'right')'完全不一樣嗎? – 2012-02-29 23:38:15

4

怎麼是這樣的:

In [1]: data = numpy.array([0, 0.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 3]) 
In [2]: hist, edges = numpy.histogram(data, bins=3) 
In [3]: for l, r in zip(edges[:-1], edges[1:]): 
    print(data[(data > l) & (data < r)]) 
    ....:  
    ....:  
[ 0.5] 
[ 1.5 1.5 1.5] 
[ 2.5 2.5 2.5] 
In [4]: 

有一些代碼來處理邊緣情況。

0

pyplot.hist在matplotlib中創建一個直方圖(但也將其繪製到屏幕上,您可能不需要)。對於垃圾箱,您可以使用numpy.histogram,如其他答案中所述。

Here是一個比較pyploy.hist和numpy.histogram的例子。

相關問題