2012-11-20 95 views
1

我有一個二維numpy數組(MxN)和另外兩個一維數組(Mx1),它們分別表示二維數組的每一行的開始和結束索引我想總結一下。我正在尋找在大數組中執行此操作的最有效方法(最好不必使用循環,這正是我目前所做的)。我想要做的一個例子是以下內容。二維數組中的索引對之間的Numpy和

>>> random.seed(1234) 
>>> a = random.rand(4,4) 
>>> print a 
[[ 0.19151945 0.62210877 0.43772774 0.78535858] 
[ 0.77997581 0.27259261 0.27646426 0.80187218] 
[ 0.95813935 0.87593263 0.35781727 0.50099513] 
[ 0.68346294 0.71270203 0.37025075 0.56119619]] 
>>> b = array([1,0,2,1]) 
>>> c = array([3,2,4,4]) 
>>> d = empty(4) 
>>> for i in xrange(4): 
    d[i] = sum(a[i, b[i]:c[i]]) 

>>> print d 
[ 1.05983651 1.05256841 0.8588124 1.64414897] 

我的問題類似於下面的問題,但是,我不認爲那裏提出的解決方案會非常有效。 Numpy sum of values in subarrays between pairs of indices在這個問題中,他們想要找到同一行的多個子集的總和,所以可以使用cumsum()。但是,我只會在每行中找到一筆金額,所以我不認爲這是計算總和的最有效方法。

編輯:對不起,我在我的代碼中犯了一個錯誤。循環內部的行先前爲d[i] = sum(a[b[i]:c[i]])。我忘記了第一維的索引。每組起始和結束索引對應於二維數組中的新行。

+0

每次迭代做一個大幅度的矢量化操作不應該太慢。你有沒有分析你的代碼,發現循環開銷很大? – japreiss

+0

總和通常超過20-30個元素,但對於每個函數調用(1200x1200二維數組),完成1200次。此外,每次仿真都會調用約600次函數,並執行了一些仿真,因此循環變得不可忽略。 – user1554752

回答

1

你可以做這樣的事情:

from numpy import array, random, zeros 
random.seed(1234) 
a = random.rand(4,4) 
b = array([1,0,2,1]) 
c = array([3,2,4,4]) 

lookup = zeros(len(a) + 1, a.dtype) 
lookup[1:] = a.sum(1).cumsum() 
d = lookup[c] - lookup[b] 
print d 

這可能幫助,如果你的B/C數組很大,你求和的窗戶都很大。因爲你的窗口可能會重疊,例如2:4和1:4大部分是相同的,所以你基本上在重複操作。通過將cumsum作爲每個處理步驟,可以減少重複操作的次數,並且可以節省時間。如果你的窗口很小並且B/C很小,這將不會有太大的幫助,主要是因爲你將總結一個你不太在乎的矩陣的部分。希望有所幫助。

+0

對不起,這解決了代碼中出現錯誤時的問題。我已更正了代碼併發布了新輸出,這正是我試圖實現的目標。 – user1554752