2011-05-11 78 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