一个numpy数组的视图视图是一个副本吗? [英] View of a view of a numpy array is a copy?

查看:81
本文介绍了一个numpy数组的视图视图是一个副本吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果更改numpy数组的视图,则原始数组也会更改.这是预期的行为.

If you change a view of a numpy array, the original array is also altered. This is intended behaviour.

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

但是,如果我查看这种视图的视图并进行更改,则原始数组不会被更改: :

However, if I take a view of such a view, and change that, then the original array is not altered:

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])

这对我来说意味着,当您查看某个视图时,您实际上会获得一份副本.这样对吗?为什么会这样?

This implies to me that, when you take a view of a view, you actually get back a copy. Is this correct? Why is this?

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

The same behaviour occurs if I use numpy arrays of numerical indices instead of a numpy array of boolean values. (E.g. arr[np.array([0])][np.array([0])] = 0 doesn't change the first element of arr to 0.)

推荐答案

通过高级进行选择 索引始终返回一个副本. 通过布尔掩码选择是一种形式先进的 索引. (高级索引的另一种形式是通过整数选择数组.)

Selection by basic slicing always returns a view. Selection by advanced indexing always returns a copy. Selection by boolean mask is a form of advanced indexing. (The other form of advanced indexing is selection by integer array.)

但是,通过高级索引进行的分配会影响原始数组.

However, assignment by advanced indexing affects the original array.

所以

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

影响arr,因为它是一个赋值.相反,

affects arr because it is an assignment. In contrast,

mask_1_arr = arr[mask_1]

是通过布尔掩码选择的,因此mask_1_arrarr一部分的副本. 拥有副本后,夹具就到了. Python执行时

is selection by boolean mask, so mask_1_arr is a copy of part of arr. Once you have a copy, the jig is up. When Python executes

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

该分配会影响mask_1_arr,但是由于mask_1_arr是副本, 对arr没有影响.

the assignment affects mask_1_arr, but since mask_1_arr is a copy, it has no effect on arr.

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


在后台,arr[mask] = something导致Python调用 arr.__setitem__(mask, something). ndarray.__setitem__方法是 已实现以修改arr.毕竟,这是人们应该期待的自然现象 __setitem__要做.


Under the hood, arr[mask] = something causes Python to call arr.__setitem__(mask, something). The ndarray.__setitem__ method is implemented to modify arr. After all, that is the natural thing one should expect __setitem__ to do.

相反,作为表达式arr[indexer]导致Python调用 arr.__getitem__(indexer).当indexer是切片时, 元素允许NumPy返回视图(通过修改步幅和偏移量).当indexer 是任意布尔掩码或任意整数数组,通常 所选元素没有规律性,因此无法返回 看法.因此,必须返回副本.

In contrast, as an expression arr[indexer] causes Python to call arr.__getitem__(indexer). When indexer is a slice, the regularity of the elements allows NumPy to return a view (by modifying the strides and offset). When indexer is an arbitrary boolean mask or arbitrary array of integers, there is in general no regularity to the elements selected, so there is no way to return a view. Hence a copy must be returned.

这篇关于一个numpy数组的视图视图是一个副本吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆