【问题标题】:Updating elements in multiply indexed np.array更新多重索引 np.array 中的元素
【发布时间】:2019-03-23 13:00:53
【问题描述】:

我有一个 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]])

【问题讨论】:

    标签: python numpy indexing


    【解决方案1】:

    我们需要用给定的mask 屏蔽索引,然后索引到arr 并分配新值。对于索引,我们可以使用tuple(masked_indices)进行索引或者使用index-array的两列进行整数索引,从而给了我们两种方法。

    方法#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 返回一个视图(通过修改步幅和偏移量)。当 indexer 是任意布尔掩码或任意整数数组时,所选元素通常没有规律性,因此无法返回视图。让我们将arr[idx[:,0],idx[:,1]] 称为arr2

    在下一步中,结合arr[idx[:,0],idx[:,1]][bool_idx],即arr2[bool_idx],它在底层调用arr2.__setitem__(mask),实现修改arr2,因此不会传播回arr

    *灵感来自 - https://stackoverflow.com/a/38768993/

    更多关于__getitem__,__setitem__的信息。

    为什么这篇文章中发布的方法有效?

    因为两者都直接在arr 上使用indexer 和修改arr.__setitem__(indexer)arr.__setitem__(indexer)

    【讨论】:

    • 确实解决了这个问题,谢谢!你能解释一下为什么我最初的尝试没有成功吗?
    • @smonsays 在上面添加了一些 cmets。
    • @Divakar:如果这确实是 OP 的解决方案不起作用的原因,那么所有这些有效的解决方案都应该因同样的原因而失败。例如,在您的方法#2 中,您所做的确实是使用两个形状为(3,)(3,) 的整数索引数组进行高级索引。我认为 OP 的解决方案不起作用的真正原因是因为 OP 解决方案的最后一步应用了 boolean index,根据文档,布尔索引的结果始终是一维数组,没有引用回原始数组。对于 OP,bool 索引返回形状 (2,),在其上完成了标量 mul。
    • @fountainhead 是的,不完全正确。编辑了帖子。
    【解决方案2】:

    您只需要对您自己的尝试进行一些小改动——您需要在每个整数索引表达式上应用布尔索引数组。换句话说,这应该有效:

    arr[idx[:,0][bool_idx],idx[:,1][bool_idx]] *= -1
    

    (我刚刚将[bool_idx] 移动到方括号内,以将其应用于两个整数索引表达式——idx[:,0]idx[:,1]

    【讨论】:

      猜你喜欢
      • 2021-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-09
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      • 1970-01-01
      相关资源
      最近更新 更多