2014-07-11 22 views
1

我有一個2D數組(array1),它有任意數量的行,並且在第一列中我嚴格單調增加數字(但不是線性),它們代表我的系統中的位置,而第二個給我一個值,它表示我的系統在第一列中的位置及其周圍的狀態。用numpy替換循環廣播 - >內存錯誤

現在我有第二個數組(array2);其範圍通常應與第一個數組的第一列相同,但無關緊要,如下所示。 我現在對array2中的每個元素感興趣: 1. array1 [:,0]中的參數與array2中的當前元素有最接近的值是什麼? 2.這些元素的值(array1 [:,1])是什麼。

由於通常array2將比array1中的行數更長,所以如果我從array1中獲取一個參數多於一次,那就非常好了。事實上,這是我所期望的。 2.的值寫在第二列和第三列,如下所示。

我條紋的代碼如下所示:

from numpy import arange, zeros, absolute, argmin, mod, newaxis, ones 


ysize1 = 50 
array1 = zeros((ysize1+1,2)) 


array1[:,0] = arange(ysize1+1)**2  
    # can be any strictly monotonic increasing array 
array1[:,1] = mod(arange(ysize1+1),2) 
    # in my current case, but could also be something else 



ysize2  = (ysize1)**2 
array2  = zeros((ysize2+1,3)) 
array2[:,0] = arange(0,ysize2+1)     
# is currently uniformly distributed over the whole range, but does not necessarily have to be 


a = 0 
for i, array2element in enumerate(array2[:,0]): 
    a = argmin(absolute(array1[:,0]-array2element)) 
    array2[i,1] = array1[a,1] 

它的工作原理,但需要相當多的時間來處理大型陣列。然後我試圖實現廣播,這似乎與下面的代碼工作:

indexarray = argmin(absolute(ones(array2[:,0].shape[0])[:,newaxis]*array1[:,0]-array2[:,0][:,newaxis]),1) 
array2[:,2]=array1[indexarray,1] # just to compare the results 

不幸的是,現在我似乎遇到不同的問題:我得到我使用的線陣列的尺寸內存錯誤的代碼與廣播。 對於小尺寸,它適用,但對於len(array2 [:,0])類似於2 ** 17(甚至可能更大)和len(array1 [:,0])約爲2 **的較大尺寸14。我得到,數組的大小比可用內存大。有沒有一種優雅的方式或加快循環? 我不需要存儲中間數組,我只是對結果感興趣。

謝謝!

回答

0

首先讓簡化這一行:

argmin(absolute(ones(array2[:,0].shape[0])[:,newaxis]*array1[:,0]-array2[:,0][:,newaxis]),1) 

它應該是:

a = array1[:, 0] 
b = array2[:, 0] 
argmin(abs(a - b[:, newaxis]), 1) 

但簡化,即使,你要創建兩個大的臨時數組。如果ab具有大小M和N,則b - aabs(...)各自創建大小(M,N)的臨時數組。因爲你說過a單調遞增,所以可以通過使用二分查找(排序搜索)來避免所有問題,反正快得多。看看我寫回question的答案。使用這個答案的功能,試試這個:

closest = find_closest(array1[:, 0], array2[:, 0]) 
array2[:, 2] = array1[closest, 1] 
+0

哇,這是一個驚人的加速! :)偉大的解決方案和偉大的解釋它是如何工作的!非常感謝你! – freeone