我有一个2D numpy数组,需要通过多层索引来更新元素的选择。对我来说,这样做的明显方法行不通,因为numpy似乎仅更新数组的副本,而不更新数组本身:
import numpy as np
# Create an array and indices that should be updated
arr = np.arange(9).reshape(3,3)
idx = np.array([[0,2], [1,1],[2,0]])
bool_idx = np.array([True, True, False])
# This line does not work as intended since the original array stays unchanged
arr[idx[:,0],idx[:,1]][bool_idx] = -1 * arr[idx[:,0],idx[:,1]][bool_idx]
这是结果输出:
>>> arr
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
但是,我希望得到这样的输出:
>>> arr
array([[0, 1, -2],
[3, -4, 5],
[6, 7, 8]])
答案 0 :(得分:1)
我们需要使用给定的mask
屏蔽索引,然后索引到arr
中并分配新值。对于索引,我们可以使用tuple(masked_indices)
进行索引或使用索引数组的两列进行整数索引,从而提供两种方法。
方法1:
arr[tuple(idx[bool_idx].T)] *= -1
方法2:
idx_masked = idx[bool_idx]
arr[idx_masked[:,0],idx_masked[:,1]] *= -1
为什么原始方法无效?
在LHS上,您正在执行arr[idx[:,0],idx[:,1]][bool_idx]
,这基本上是两个步骤:arr[idx[:,0],idx[:,1]]
,在幕后称为arr.__getitem__(indexer)
*。当indexer是切片时,元素的规则性允许NumPy返回视图(通过修改步幅和偏移量)。当索引器是任意布尔掩码或任意整数数组时,所选元素通常没有规律性,因此无法返回视图。让我们将arr[idx[:,0],idx[:,1]]
称为arr2
。
下一步,将arr[idx[:,0],idx[:,1]][bool_idx]
,即arr2[bool_idx]
组合起来,称为arr2.__setitem__(mask)
,它被实现来修改arr2
,因此不会。 t传播回arr
。
*灵感来自-https://stackoverflow.com/a/38768993/。
有关__getitem__
,__setitem__
的更多信息。
为什么此帖子中发布的方法有效?
因为两者都直接将indexer
上的arr
与修改arr.__setitem__(indexer)
的{{1}}使用。
答案 1 :(得分:1)
您只需要对自己的尝试做些小改动-您就需要在每个整数索引表达式上应用布尔值索引数组。换句话说,这应该起作用:
arr[idx[:,0][bool_idx],idx[:,1][bool_idx]] *= -1
(我刚刚将[bool_idx]
移到了方括号内,以将其应用于两个整数索引表达式-idx[:,0]
和idx[:,1]
)