什么时候获取numpy数组的子矩阵返回视图但不复制? [英] When does getting submatrix of an numpy array returns view but not copy?
问题描述
我正在尝试获取一个numpy二维数组的子矩阵,并对其进行修改.有时我会得到一个副本,对其进行的修改不会影响原始数组:
I'm trying to get a submatrix of a numpy 2D array, and modify it. Sometimes I get a copy, which modification to it does not affect the original array:
In [650]: d=np.random.rand(5,5)
In [651]: may_share_memory(d, d[[0,1],:][:,[2,3]])
Out[651]: False
In [652]: d[[0,1],:][:,[2,3]]=2
In [653]: d
Out[653]:
array([[ 0.0648922 , 0.41408311, 0.88024646, 0.22471181, 0.81811439],
[ 0.32154096, 0.88349028, 0.30755883, 0.55301128, 0.61138144],
[ 0.18398833, 0.40208368, 0.69888324, 0.93197147, 0.43538379],
[ 0.55633382, 0.80531999, 0.71486132, 0.4186339 , 0.76487239],
[ 0.81193408, 0.4951559 , 0.97713937, 0.33904998, 0.27660239]])
虽然有时may_share_memory
还返回 False :
In [662]: d[np.ix_([0,1],[2,3])]=1
In [663]: d
Out[663]:
array([[ 0.0648922 , 0.41408311, 1. , 1. , 0.81811439],
[ 0.32154096, 0.88349028, 1. , 1. , 0.61138144],
[ 0.18398833, 0.40208368, 0.69888324, 0.93197147, 0.43538379],
[ 0.55633382, 0.80531999, 0.71486132, 0.4186339 , 0.76487239],
[ 0.81193408, 0.4951559 , 0.97713937, 0.33904998, 0.27660239]])
In [664]: may_share_memory(d, d[np.ix_([0,1],[2,3])])
Out[664]: False
更奇怪的是,如果将视图"分配给变量,它将变成副本"(同样,修改不会影响原始数组):
What more strange is, if assign that 'view' to a variable, it becomes a 'copy' (again, modification does not affect the original array):
In [658]: d2=d[np.ix_([0,1],[2,3])]
In [659]: may_share_memory(d,d2)
Out[659]: False
In [660]: d2+=1
In [661]: d
Out[661]:
array([[ 0.0648922 , 0.41408311, 0.88024646, 0.22471181, 0.81811439],
[ 0.32154096, 0.88349028, 0.30755883, 0.55301128, 0.61138144],
[ 0.18398833, 0.40208368, 0.69888324, 0.93197147, 0.43538379],
[ 0.55633382, 0.80531999, 0.71486132, 0.4186339 , 0.76487239],
[ 0.81193408, 0.4951559 , 0.97713937, 0.33904998, 0.27660239]])
推荐答案
您看到的是.
另外,为了清楚起见,d[np.ix_([0,1],[2,3])] = 1
不是视图,而是分配.有关这方面的更多解释,请参见@EelcoHoogendoorn的答案.您感到困惑的根源似乎是Eelco谈到的__setitem__
vs __getitem__
,但是我想我要添加一些具体的数字说明.
Also, for clarity, d[np.ix_([0,1],[2,3])] = 1
is not a view, it's an assignment. See @EelcoHoogendoorn's answer for more explanation in that regard. The root of your confusion seems to be with __setitem__
vs __getitem__
, which Eelco addresses, but I thought I'd add a few numpy-specific clarifications.
每当您使用一系列坐标进行索引(np.ix_
返回索引数组)时,它都是花哨的"索引,并且将始终返回副本.
Any time you index with a sequence of coordinates (np.ix_
returns an array of indicies), it's "fancy" indexing and will always return a copy.
您可以使用切片进行的所有操作始终返回视图.
Anything you can do with slicing with always return a view.
例如:
In [1]: import numpy as np
In [2]: x = np.arange(10)
In [3]: y = x[3:5]
In [4]: z = x[[3, 4]]
In [5]: z[0] = 100
In [5]: x
Out[5]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [6]: y[0] = 100
In [7]: x
Out[7]: array([ 0, 1, 2, 100, 4, 5, 6, 7, 8, 9])
这样做的原因是numpy数组在内存中必须是半连续的(更确切地说,必须能够通过偏移量,步幅和形状来描述它们).
The reason for this is that numpy arrays have to be semi-contiguous in memory (more precisely, they have to be able to be described by an offset, strides, and shape).
任何类型的切片都可以用这种方式描述(甚至像x[:, 3:100:5, None]
这样的东西).
Any type of slicing can be described this way (even something like x[:, 3:100:5, None]
).
任意坐标序列(例如x[[1, 4, 5, 100]]
)不能是.
An arbitrary sequence of coordinates (e.g. x[[1, 4, 5, 100]]
) cannot be.
因此,如果使用切片,则numpy始终返回一个视图,如果使用花式索引"(也就是使用一系列索引或布尔掩码),则numpy始终返回一个副本.
Therefore, numpy always returns a view if slicing is used and a copy if "fancy indexing" (a.k.a. using a sequence of indicies or a boolean mask) is used.
赋值(例如x[blah] = y
)将总是就地修改numpy数组.
Assignments (e.g. x[blah] = y
), however, will always modify a numpy array in-place.
这篇关于什么时候获取numpy数组的子矩阵返回视图但不复制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!