如果更改 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_arr
是 arr
的一部分的副本。
一旦你有了一份副本,夹具就准备好了。当 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/