Python 无法使用三维遮罩和索引将值指定给numpy数组

Python 无法使用三维遮罩和索引将值指定给numpy数组,python,numpy,mask,masking,matrix-indexing,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 -

我有一个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

使用布尔掩码对数组进行索引时,将提取元素并将其放置到一维数组中。这几乎是必须的,因为蒙版的选定元素在任何维度内都不是均匀地分布在整个屏幕上。表达式
results[mask]=value
相当于
results.\uuuuu setitem\uuuuu(mask,value)
:显然是对
result
的就地修改。但是,
results[mask][index\u keep]=value
相当于
result.\uuuuuu getitem\uuuuuuuuuuu(mask)。\uuuuu setitem\uuuuuuuuuuuuuu(index\u keep,value)
。就地操作发生在完全丢弃的临时阵列上

解决方案是使用索引来获得对所需对象的
\uuuuu setitem\uuuu
的单个调用。一种方法是将
index\u keep
应用于
mask
。首先必须将
掩码
转换为线性索引,例如:

只要返回一个视图(在大多数情况下应该是这样的),这就可以工作。如果
result
是一个连续数组,则该操作将一直有效。如果
result
已经是一个较大数组的子集,则它将不起作用

这种方法的优点是,它只使用一个索引数组,并且适用于任意数量的维度。使用
np.where
也可以进行调整,但需要更多的临时存储。缺点当然是这种方法仅限于连续数组


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

您可以在
掩码上使用
numpy.where
,这将允许您查看要索引的
结果

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

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

results[mask][index\u keep]
是数组的一个副本,这就是为什么您在
result
中没有看到任何更改的原因真的吗?在其他情况下,
results[mask]=values.copy()
对我有效,但是,
results[mask][index\u keep]=values.copy()
失败。那我怎么做呢?太棒了。非常感谢。我接受答案。我知道我返回的副本,但找不到使用这些双索引方法来分配我的值的方法,
ravel
主要返回一个视图(:@piRSquared.Yep。它尽最大努力获取指向缓冲区的指针,并适当设置步幅。不过,我不确定它对切片的影响有多大。例如,
np.arange(12)。重塑(4,3)[:,::2]。ravel()
不能是视图,但
np.arange(12)。重塑(3,4)[:,::2]
可以。我只是不确定它是否会。据我所知,
ravel
保证了一个连续的结果,因此它只会在数组开始时是连续的情况下给你一个视图。你可以始终检查
arr.ravel()。base是None
vs
arr.ravel().base是arr
,用于副本与视图。就答案而言,一个关键组件是布尔索引数组总是触发奇特的索引,从而创建副本。例如,如果第一次订阅使用了切片,则双索引分配会起作用。这对其他读者来说可能不明显。(cc@piRSquared)@我对另一个答案的最后一点评论有帮助吗?对于一个简单的应用程序,这实际上是一种更易于维护和易读的方法
x, y, z = np.where(mask)

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