numpy:布尔索引和内存使用

Posted

技术标签:

【中文标题】numpy:布尔索引和内存使用【英文标题】:numpy: boolean indexing and memory usage 【发布时间】:2011-08-23 03:31:01 【问题描述】:

考虑以下numpy 代码:

A[start:end] = B[mask]

这里:

AB 是列数相同的二维数组; startend 是标量; mask 是一维布尔数组; (end - start) == sum(mask)

上述操作原则上可以使用O(1)临时存储进行,将B的元素直接复制到A中。

这是实际发生的情况,还是numpyB[mask] 构造了一个临时数组?如果是后者,有没有办法通过重写语句来避免这种情况?

【问题讨论】:

【参考方案1】:

线

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 或更高版本中可用。

【讨论】:

当然,“产生一个包含 B 的选定行并占用额外内存的新数组”是不合理的吗?由B.__getitem__() 选择它想要返回的内容。例如,如果maskslice,则将返回代理(视图),并且不会进行复制。 @aix:根据 OP,mask 是一维布尔数组。我错过了什么吗? @aix:哦,我明白了。语言定义的部分有点模棱两可。它只是指“首先评估右手边”的部分。 是的,我想我们彼此了解。【参考方案2】:

使用布尔数组作为索引是一种花哨的索引,因此 numpy 需要进行复制。 如果您遇到内存问题,您可以编写一个 cython 扩展来处理它。

【讨论】:

+1 用于引入 Cython。它擅长的正是这种循环。

以上是关于numpy:布尔索引和内存使用的主要内容,如果未能解决你的问题,请参考以下文章

具有 1 位条目的 numpy 布尔数组

只有整数、切片 (`:`)、省略号 (`...`)、numpy.newaxis (`None`) 和整数或布尔数组是有效的索引

在 numpy 中从具有索引的 2D 矩阵构建 3D 布尔矩阵

numpy切片和布尔型索引

Numpy 布尔型数组

Python 中的二级内存索引表示