无法使用 3D 掩蔽和索引将值分配给 numpy 数组
Cannot assign values to numpy array using 3D masking and 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
当您使用布尔掩码索引数组时,元素将被提取并放入一维数组中。这几乎必须是这种情况,因为蒙版的选定元素在我们的任何维度内都不是均匀的 space。表达式 results[mask] = value
等同于 results.__setitem__(mask, value)
:显然是对 result
的 in-place 修改。但是 results[mask][index_keep] = value
等同于 result.__getitem__(mask).__setitem__(index_keep, value)
。 in-place 操作发生在完全丢弃的临时数组上。
解决方案是使用索引对所需对象进行一次 __setitem__
调用。一种方法是将 index_keep
应用于 mask
。您首先必须将 mask
转换为线性索引,例如np.flatnonzero
:
result.ravel()[np.flatnonzero(mask)[index_keep]] = value
只要 ravel
returns 一个视图,它就可以工作,在大多数情况下应该如此。如果 result
是一个连续的数组,这将一直有效。如果 result
已经是更大数组的子集,它将无法工作。
这种方法的优点是它只使用一个索引数组,并且适用于任意数量的维度。使用 np.where
可以做同样的事情,但需要更多的临时存储空间。缺点当然是这种方法仅限于连续的数组。
P.S。您几乎可以肯定不需要复制 value
。它的元素不会被修改,并且赋值已经将副本复制到 result
的适当位置。制作副本只会创建一个不必要的临时数组,该数组将立即被丢弃。
您可以在 mask
上使用 numpy.where
,这样您就可以查看要索引的 results
数组。
x, y, z = np.where(mask)
results[x[index_keep], y[index_keep], z[index_keep]] = values
我有一个 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
当您使用布尔掩码索引数组时,元素将被提取并放入一维数组中。这几乎必须是这种情况,因为蒙版的选定元素在我们的任何维度内都不是均匀的 space。表达式 results[mask] = value
等同于 results.__setitem__(mask, value)
:显然是对 result
的 in-place 修改。但是 results[mask][index_keep] = value
等同于 result.__getitem__(mask).__setitem__(index_keep, value)
。 in-place 操作发生在完全丢弃的临时数组上。
解决方案是使用索引对所需对象进行一次 __setitem__
调用。一种方法是将 index_keep
应用于 mask
。您首先必须将 mask
转换为线性索引,例如np.flatnonzero
:
result.ravel()[np.flatnonzero(mask)[index_keep]] = value
只要 ravel
returns 一个视图,它就可以工作,在大多数情况下应该如此。如果 result
是一个连续的数组,这将一直有效。如果 result
已经是更大数组的子集,它将无法工作。
这种方法的优点是它只使用一个索引数组,并且适用于任意数量的维度。使用 np.where
可以做同样的事情,但需要更多的临时存储空间。缺点当然是这种方法仅限于连续的数组。
P.S。您几乎可以肯定不需要复制 value
。它的元素不会被修改,并且赋值已经将副本复制到 result
的适当位置。制作副本只会创建一个不必要的临时数组,该数组将立即被丢弃。
您可以在 mask
上使用 numpy.where
,这样您就可以查看要索引的 results
数组。
x, y, z = np.where(mask)
results[x[index_keep], y[index_keep], z[index_keep]] = values