无法使用3D遮罩和索引为numpy数组分配值

时间:2019-06-26 13:06:46

标签: python numpy mask masking matrix-indexing

我有一个作为遮罩的3D阵列。另外,我有一些索引可以对应该保存一些值(数组位置)的位置进行编码。

除了将值分配给所需位置后输出矩阵仍然为空之外,一切似乎都工作正常。

我看不到我在这里想念的东西。我也尝试过numpy.put,但没有运气。

import numpy as np

# Initialize output matrix (here the results will be stored)
results = np.zeros((67, 67, 45))

# define the mask - where to put the calculated values in the results array
mask = np.random.randint(2, size=(67, 67, 45)).astype(bool)

# store the results only in these positions
index_keep = range(0, 13732)

values = np.ones((13732,))

results[mask][index_keep] = values.copy()

# the results array is still empty
print(results.sum())
#0

2 个答案:

答案 0 :(得分:3)

使用布尔掩码对数组进行索引时,将提取元素并将其放置到一维数组中。这几乎是必须的情况,因为蒙版的选定元素在任何维度上在我们上的分布都不均匀。表达式results[mask] = value等效于results.__setitem__(mask, value):显然是对result的就地修改。但是results[mask][index_keep] = value等效于result.__getitem__(mask).__setitem__(index_keep, value)。就地操作发生在完全丢弃的临时阵列上。

解决方案是处理索引,以单次调用所需对象上的__setitem__。一种实现方法是将index_keep应用于mask。您首先必须将mask转换为线性索引,例如与np.flatnonzero

result.ravel()[np.flatnonzero(mask)[index_keep]] = value

只要ravel返回一个视图(在大多数情况下都应如此),此方法就起作用。如果result是一个连续的数组,那么它将一直有效。如果result已经是较大数组的子集,则无法使用。

此方法的优势在于它仅使用单个索引数组,并且可用于任意数量的维。使用np.where可以做到相同,但需要更多的临时存储。缺点当然是这种方法仅限于连续数组。

P.S。您几乎肯定不需要复制value。它的元素将不会被修改,并且赋值已经将副本复制到result的适当位置。制作副本只会创建一个不必要的临时数组,该数组将立即丢弃。

答案 1 :(得分:2)

您可以在numpy.where上使用mask,这将使您可以查看results数组的视图以建立索引。

x, y, z = np.where(mask)

results[x[index_keep], y[index_keep], z[index_keep]] = values