Numpy:通过切片查看vs复制

Cae*_*ium 11 python numpy slice

当我正在进行切片时,发生了意想不到的事情,这似乎是第一个被查看但第二个是复制.

第一

第一片行,然后是片段.这似乎是一种观点.

>>> a = np.arange(12).reshape(3, 4)   
>>> a[0:3:2, :][:, [0, 2]] = 100
>>> a
array([[100,   1, 100,   3],
       [  4,   5,   6,   7],
       [100,   9, 100,  11]])
Run Code Online (Sandbox Code Playgroud)

第二

但是,如果我第一次切片,然后切片行,它似乎是一个副本:

>>> a[:, [0, 2]][0:3:2, :] = 0
>>> a
array([[100,   1, 100,   3],
       [  4,   5,   6,   7],
       [100,   9, 100,  11]])
Run Code Online (Sandbox Code Playgroud)

我很困惑,因为这两种方法最终会导致看似位置改变,但为什么第二种方法实际上不会改变数字?

Mal*_*ore 15

John Zwinck 接受的答案实际上是错误的(我只是以艰难的方式想通了这一点!)。问题中的问题是将“左值索引”与 numpy 的花哨索引结合起来。以下文档准确地解释了这种情况

https://scipy-cookbook.readthedocs.io/items/ViewsVsCopies.html

在“但是花哨的索引有时确实会返回视图,不是吗?”

  • 摘要(而不仅仅是链接)会有所帮助。 (3认同)

Joh*_*nck 12

重要的是你是按行还是按列切片.按行切片可以返回视图,因为它是原始数组的连续段.按列切片必须返回副本,因为它不是连续的段.例如:

A1 A2 A3
B1 B2 B3
C1 C2 C3
Run Code Online (Sandbox Code Playgroud)

默认情况下,它以这种方式存储在内存中:

A1 A2 A3 B1 B2 B3 C1 C2 C3
Run Code Online (Sandbox Code Playgroud)

所以如果你想选择每一行,那就是:

[A1 A2 A3] B1 B2 B3 [C1 C2 C3]
Run Code Online (Sandbox Code Playgroud)

这可以描述为{start: 0, size: 3, stride: 6}.

但是如果你想选择每一个第二列:

[A1] A2 [A3 B1] B2 [B3 C1] C2 [C3]
Run Code Online (Sandbox Code Playgroud)

并且无法使用单个开始,大小和步幅来描述.所以没有办法构建这样的视图.

如果您希望能够查看每个第二列而不是每隔一行,则可以使用列主要的Fortran命令构建数组:

np.array(a, order='F')
Run Code Online (Sandbox Code Playgroud)

然后它将被存储为:

A1 B1 C1 A2 B2 C2 A3 B3 C3
Run Code Online (Sandbox Code Playgroud)

  • 这个解释是不正确的。您可以通过尝试首先使用“ a [:, 0:3:2] [0:3:2,:] = 0”来选择列来轻松地进行检查,这将起作用。真正重要的是您要进行基本索引还是高级索引(有关示例和更多说明,请参见:https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html)。在这种情况下,通过“ [:,[0,2]]”选择列是高级索引,因此将返回一个副本。 (3认同)
  • 我知道您的答案不是一般教程。不过还是错的。让我更详细地解释:导致OP问题的2个因素a)视图与副本,以及b)索引操作的顺序(请参阅此答案:/sf/ask/3241585931/)。您说“重要的是要按行还是按列切片”,bc行返回视图,而列返回副本。这不是真的bc a)并不重要,并且b)如果您使用基本索引,则行和列均返回视图。如上评论所示,对于视图vs.副本而言,重要的是基本索引还是高级索引。 (2认同)