使用链式掩码替换numpy数组元素

3

考虑一个数组 arr 和高级索引蒙版 mask

import numpy as np

arr = np.arange(4).reshape(2, 2)
mask = A < 2

使用高级索引会创建一个数组的新副本。因此,不能通过"链接"一个掩码与另一个掩码或基本的切片操作来替换数组的元素:

submask = [False, True]
arr[mask][submask] = -1  # chaining 2 masks
arr[mask][:] = -1  # chaining a mask with a basic slicing operation

print(arr)
[[0 1]
 [2 3]]

我有两个相关的问题:

1/ 使用链式掩码替换数组元素的最佳方法是什么?

2/ 如果高级索引返回数组的副本,那么为什么以下内容有效?

arr[mask] = -1

print(arr)
[[-1 -1]
 [ 2  3]]
2个回答

3
简短回答:
  • 你需要想办法将掩码组合在一起。由于掩码可以以不同的方式“链接”,因此我认为没有一个简单的通用替代品。

  • 索引可以是__getitem__调用,也可以是__setitem__。您最后一个案例是一种设置。

使用链接索引,a[mask1][mask2] =value被转换为

a.__getitem__(mask1).__setitem__(mask2, value)

无论第一个getitem产生的是视图还是副本,a是否被修改取决于它。
In [11]: arr = np.arange(4).reshape(2,2)
In [12]: mask = arr<2
In [13]: mask
Out[13]: 
array([[ True,  True],
       [False, False]])
In [14]: arr[mask]
Out[14]: array([0, 1])

使用列表或数组进行索引可能会保留维数,但像此类的布尔值返回一个1d数组,其中掩码为真。

在您的示例中,我们可以调整mask(详细信息可能因第二个掩码的意图而异):

In [15]: mask[:,0]=False
In [16]: mask
Out[16]: 
array([[False,  True],
       [False, False]])
In [17]: arr[mask]
Out[17]: array([1])
In [18]: arr[mask] += 10
In [19]: arr
Out[19]: 
array([[ 0, 11],
       [ 2,  3]])

或者是掩码的逻辑组合:

In [26]: (np.arange(4).reshape(2,2)<2)&[False,True]
Out[26]: 
array([[False,  True],
       [False, False]])

我接受了这个通用的方法,但是请参考其他答案,以获取如何链接掩码的灵感,这可能在某些情况下有效。 - Bob
我已经为你的第一个示例添加了一个可能性。 - hpaulj

2
几个很好的问题!我的看法是:
  1. 我会做这样的事情:
x,y=np.where(mask)
arr[x[submask],y[submask]] = -1

根据官方文档

下面大多数示例展示了在数组中引用数据时使用索引的方法。当对数组进行赋值时,这些示例同样适用。请参阅结尾处的特定示例和解释,了解赋值的工作原理。

这意味着arr[mask]=1是引用,而arr[mask]是提取数据并创建副本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接