为什么 numpy 不允许分配双索引的 numpy 数组?



我想将数组的值arr_2分配给不同的数组arr_1。但是,我想根据 2 个选择标准来做到这一点。作为工作示例,我这样定义我的选择标准

import numpy as np
# An array of -1 values of shape(10,): [-1 -1 -1 -1 -1 -1 -1 -1 -1 -1]
arr_1 = np.zeros(10, dtype=int) - 1
# An array of 0-9 values of shape(10,): [0 1 2 3 4 5 6 7 8 9]
arr_2 = np.arange(10)
# Create an initial selection of values we want to change
# In this example: even indices: [ T F T F T F T F T F]
selection_a = np.arange(10) % 2 == 0
# Create a second selection based on selection_a: [F F F T T]
selection_b = arr_2[selection_a] > 5

基于这两个选择标准,我想将两个条件都成立的arr_2的值分配给数组arr_1,即等同于[F F F F F F T F T F]

arr_1[selection_a][selection_b] = arr_2[selection_a][selection_b]

如果我在赋值前检查等式的两边,它们会产生我期望的值:

print(arr_1[selection_a][selection_b]) # yields [-1 -1]
print(arr_2[selection_a][selection_b]) # yields [ 6, 8]

但是,赋值本身不会分配值,即arr_1保持不变。我的问题是,为什么会这样?

注意:我知道在大多数情况下(甚至可能所有情况下(这可以通过创建一个标准来规避,但是我想知道为什么使用 2 个单独的标准不起作用。

如果有任何不清楚的地方,请告诉我,我会尽力澄清。

编辑

我对此进行了进一步调查,问题似乎在等式的左侧,如下所示

arr_1[selection_a][selection_b] = 5

也不起作用。

单次使用[...]运算符会在数组中创建一个选择,您可以从中读取和写入。第二次使用[...]将毫无问题地读取值。但就写入而言,第二次访问将是您的情况中为匹配选择规则而创建的临时数组(即形状(2,)的临时数组,即原始数据的副本(。

编辑:布尔索引是所谓的"高级索引"的一部分。将索引保留为简单切片可避免这些复制问题。

添加到皮埃尔·德·布伊尔解决方案中,如果您想获得更改数组arr_1所需的结果。您可以按如下方式使用np.where

arr_1[selection_a] = np.where(arr_2[selection_a]>5,arr_2[selection_a],arr_1[selection_a])
arr_1

这给了

array([-1, -1, -1, -1, -1, -1,  6, -1,  8, -1])

它与python中的=被解释为.__setitem__()有关,它可以从分配的变量中挑选内存地址。 但是,它不会递归地执行此操作,因此虽然

a[boolean_mask] = 0 

工作,因为索引指向a中的内存,

a[mask1][mask2] = 0

不会,因为索引指向a[mask1]中的内存,这是一个副本。

由于selection_aselection_b的条件不相互依赖,因此您可以创建一个组合掩码

selection_c = (np.arange(10) % 2 == 0) & (arr_2 >  5)

并像使用它一样使用

arr_1[selection_c] = 5

最新更新