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

Replacing numpy array elements with chained masks

考虑一些数组 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/ 如果高级索引 returns 数组的副本,为什么下面的工作?

arr[mask] = -1

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

几个好问题!我的看法:

  1. 我会这样做:
x,y=np.where(mask)
arr[x[submask],y[submask]] = -1
  1. 来自official document

Most of the following examples show the use of indexing when referencing data in an array. The examples work just as well when assigning to an array. See the section at the end for specific examples and explanations on how assignments work.

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

简短回答:

  • 你必须想出一种组合面具的方法。由于面具可以以不同的方式“链接”,我认为没有简单的通用替代品。

  • 索引可以是 __getitem__ 调用,也可以是 __setitem__。你最后一个案例是一组。

使用链式索引,a[mask1][mask2] =value 被翻译成

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

a 是否被修改取决于第一个 getitem 产生的内容(视图与副本)。

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])

使用列表或数组建立索引可能会保留维数,但是像这样的布尔值 returns 一维数组,掩码为真的项目。

在您的示例中,我们可以调整 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]])