2011-05-11 29 views
6

考慮以下numpy代碼:numpy的:布爾索引和存儲器使用

A[start:end] = B[mask] 

這裏:

  • AB是2D陣列具有相同的列數;
  • startend是標量;
  • mask是一維布爾數組;
  • (end - start) == sum(mask)

在原理上,上面的操作,可以使用O(1)臨時存儲通過複製的B元件直接進入A進行。

這是實際發生的實際情況,還是numpy構建了一個臨時數組B[mask]?如果是後者,是否有辦法通過重寫語句來避免這種情況?

回答

2

使用布爾數組作爲索引花哨的索引,所以numpy需要做一個副本。 如果你遇到內存問題,你可以編寫一個cython擴展來處理它。

+0

+1引入Cython。它擅長於這種循環。 – 2011-05-11 09:58:05

3

A[start:end] = B[mask] 

將 - 根據Python語言定義 - 第一評價右手側,得到含有B所選行和佔用額外的存儲器的新數組。最有效的純Python的方式我知道的避免這種情況是使用顯式循環:

from itertools import izip, compress 
for i, b in izip(range(start, end), compress(B, mask)): 
    A[i] = b 

當然,這將是時間效率大大低於原來的代碼,但只使用O( 1)額外的內存。另請注意,itertools.compress()可用於Python 2.7或3.1或更高版本。

+1

當然,「產生一個包含B的選定行並佔用額外內存的新數組」是不合理的?這取決於'B .__ getitem __()'選擇它想要返回的內容。例如,如果'mask'是'slice',則將返回代理(視圖),並且不會發生副本。 – NPE 2011-05-11 11:52:36

+0

@aix:根據OP,「mask」是一維布爾數組。我錯過了什麼嗎? – 2011-05-11 12:12:26

+0

@aix:哦,我明白了。具有語言定義的部分有點模糊。它僅僅是指「首先評估右側」部分。 – 2011-05-11 12:14:11