我有一个NumPy数组arr
和一个(反向)掩码mask
。为简单起见,我们假设它们都是1d。我想更改n
中的arr
非屏蔽值。
一个例子:
import numpy as np
arr = np.arange(5)
mask = np.array((True, False, True, True, False))
不幸的是,
arr[mask][-1] = 100
我希望返回
array([0, 1, 2, 100, 4])
由于NumPy array views on non-consecutive items中列出的原因,无效。
解决方法是将允许的值存储在新变量中,更改相应的值,并将所有值复制回原始数组中:
tmp = arr[mask]
tmp[-1] = 100
arr[mask] = tmp
然而,这个解决方案是丑陋而低效的,因为我必须复制许多我根本不想改变的值。
有没有人有一种优雅的方式来处理这类问题?我会对最通用的解决方案感兴趣,这样我就可以使用tmp
完成所有经典赋值操作。但是,如果有一种有效的方法只适用于具体的案例,我仍然会对它感兴趣!
答案 0 :(得分:2)
一种选择是使用np.where
获取mask
条件为True
的索引集。然后,您可以使用这些索引的子集索引到arr
并进行分配:
# np.where returns a tuple of index arrays, one per dimension
arr[np.where(mask)[0][-1]] = 100
print(repr(arr))
# array([ 0, 1, 2, 100, 4])
您可以将此方法与切片索引,布尔索引等结合使用。例如:
arr[np.where(mask)[0][::-1]] = 100, 200, 300
print(repr(arr))
# array([300, 1, 200, 100, 4])
答案 1 :(得分:0)
您还可以使用np.nonzero
从掩码中获取索引吗?
index = mask.nonzero()[0][-1]
arr[index] = 100
In [29]: arr
Out[29]: array([ 0, 1, 2, 100, 4])
或者您可以将np.array
转换为列表并使用列表中的index
方法查找最后一个值的索引:
index = arr.tolist().index(arr[mask][-1])
arr[index] = 100
In [78]: arr
Out[78]: array([ 0, 1, 2, 100, 4])
<强>基准强>:
In [87]: %timeit arr[mask.nonzero()[0][-1]] = 100
1000000 loops, best of 3: 897 ns per loop
In [88]: %timeit arr[np.where(mask)[0][-1]] = 100
1000000 loops, best of 3: 980 ns per loop
In [91]: %timeit arr[arr.tolist().index(arr[mask][-1])] = 100
100000 loops, best of 3: 2.44 us per loop
所以nonzero
方法比np.where
快一点。
修改强>
我认为nonzero
有点快,因为来自docs的np.where
:
如果仅提供条件,请返回
condition.nonzero()
。
所以基本上你通过np.nonzero
召唤np.where
,因为在这种情况下你只传递一个条件。