python - 一个numpy数组的 View 是一个 View 的副本?

标签 python numpy

如果更改 numpy 数组的 View ,原始数组也会更改。这是预期的行为。

arr = np.array([1,2,3])
mask = np.array([True, False, False])
arr[mask] = 0
arr
# Out: array([0, 2, 3])

但是,如果我查看这样的 View 并更改它,那么原始数组不会被更改:

arr = np.array([1,2,3])
mask_1 = np.array([True, False, False])
mask_1_arr = arr[mask_1]  # Becomes: array([1])
mask_2 = np.array([True])
mask_1_arr[mask_2] = 0
arr
# Out: array([1, 2, 3])

这对我来说意味着,当你查看一个 View 时,你实际上得到了一个副本。它是否正确?这是为什么?

如果我使用数字索引的 numpy 数组而不是 bool 值的 numpy 数组,则会发生相同的行为。 (例如 arr[np.array([0])][np.array([0])] = 0 不会将 arr 的第一个元素更改为 0 .)

最佳答案

选择 basic slicing总是返回一个 View 。选择 advanced indexing总是返回一个副本。 Selection by boolean mask是一种先进的形式 索引。 (另一种形式的高级索引是 selection by integer array 。)

但是,高级索引的赋值会影响原始数组。

所以

mask = np.array([True, False, False])
arr[mask] = 0

影响 arr 因为它是一个赋值。相比之下,

mask_1_arr = arr[mask_1]

是通过 bool 掩码选择的,所以 mask_1_arrarr 的一部分的副本。 一旦你有了一份副本,夹具就准备好了。当 Python 执行时

mask_2 = np.array([True])
mask_1_arr[mask_2] = 0

赋值会影响 mask_1_arr,但由于 mask_1_arr 是一个副本, 它对 arr 没有影响。


|            | basic slicing    | advanced indexing |
|------------+------------------+-------------------|
| selection  | view             | copy              |
| assignment | affects original | affects original  |

在幕后,arr[mask] = something 导致 Python 调用 arr.__setitem__(掩码,某物)ndarray.__setitem__ 方法是 实现修改 arr。毕竟,这是人们应该期待的自然之事 __setitem__ 做。

相反,作为表达式 arr[indexer] 导致 Python 调用 arr.__getitem__(索引器)。当 indexer 为切片时, elements 允许 NumPy 返回 View (通过修改步幅和偏移量)。当 indexer 是任意 bool 掩码或任意整数数组,通常有 选中的元素没有规律性,所以没有办法返回a 看法。因此必须归还副本。

关于python - 一个numpy数组的 View 是一个 View 的副本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38768815/

相关文章:

python - 仅使用 NumPy einsum 处理上三角元素

python - 避免在标准错误上打印 tensorflow

python - Django:如何在 View 中获取格式日期?

python - 如何从左侧实现对象与 Numpy 数组的乘法?

python - 点积的 numpy 机器精度?

Python:计算 numpy 数组(大数据集)中出现次数的更快方法

python - 通过 sys.modules 使虚拟包可用

python - 将二进制数据转换为utf-8

python - 允许用户搜索项目的最佳方式是什么

python - 当输入为不同类型时,Numpy matmul 需要的内存比所需的内存多