python - Numpy 多维数组索引交换轴顺序

标签 python numpy

我正在处理多维 Numpy 数组。当使用其他索引数组访问这些数组时,我注意到一些不一致的行为。例如:

import numpy as np
start = np.zeros((7,5,3))
a     = start[:,:,np.arange(2)]
b     = start[0,:,np.arange(2)]
c     = start[0,:,:2]
print 'a:', a.shape
print 'b:', b.shape
print 'c:', c.shape

在这个例子中,我得到了结果:

a: (7, 5, 2)
b: (2, 5)
c: (5, 2)

这让我很困惑。为什么“b”和“c”的尺寸不同?为什么“b”交换轴顺序,而不是“a”?

由于大量的单元测试,我已经能够围绕这些不一致设计我的代码,但理解正在发生的事情将不胜感激。

作为引用,我通过 MacPorts 使用 Python 2.7.3 和 Numpy 1.6.2。

最佳答案

从句法上看,这看起来不一致,但从语义上讲,您在这里做的是两件截然不同的事情。在您对 ab 的定义中,您正在执行 advanced indexing ,有时称为 fancy indexing ,它返回数据的副本。在你对 c 的定义中,你在做 basic slicing ,返回数据 View 。

要区分它们,有助于理解索引是如何传递给 python 对象的。以下是一些示例:

>>> class ShowIndex(object):
...     def __getitem__(self, index):
...         print index
... 
>>> ShowIndex()[:,:]
(slice(None, None, None), slice(None, None, None))
>>> ShowIndex()[...,:]
(Ellipsis, slice(None, None, None))
>>> ShowIndex()[0:5:2,::-1]
(slice(0, 5, 2), slice(None, None, -1))
>>> ShowIndex()[0:5:2,np.arange(3)]
(slice(0, 5, 2), array([0, 1, 2]))
>>> ShowIndex()[0:5:2]
slice(0, 5, 2)
>>> ShowIndex()[5, 5]
(5, 5)
>>> ShowIndex()[5]
5
>>> ShowIndex()[np.arange(3)]
[0 1 2]

如您所见,有许多不同的可能配置。首先,可以传递单个项目,也可以传递项目元组。其次,元组可能包含 slice 对象、Ellipsis 对象、普通整数或 numpy 数组。

当您传递 对象(如intsliceEllipsis 对象)时,基本切片被激活,或者None(与 numpy.newaxis 相同)。这些可以单独传递或以元组形式传递。以下是文档中关于如何激活基本切片的内容:

Basic slicing occurs when obj is a slice object (constructed by start:stop:step notation inside of brackets), an integer, or a tuple of slice objects and integers. Ellipsis and newaxis objects can be interspersed with these as well. In order to remain backward compatible with a common usage in Numeric, basic slicing is also initiated if the selection object is any sequence (such as a list) containing slice objects, the Ellipsis object, or the newaxis object, but no integer arrays or other embedded sequences.

当您传递 numpy 数组、仅包含整数或包含任何类型的子序列的非元组序列,或者包含数组或子序列的元组时,将激活高级索引。

有关高级索引和基本切片的不同之处的详细信息,请参阅文档(链接到上面)。但在这种特殊情况下,我很清楚发生了什么。使用部分索引时,它与以下行为有关:

The rule for partial indexing is that the shape of the result (or the interpreted shape of the object to be used in setting) is the shape of x with the indexed subspace replaced with the broadcasted indexing subspace. If the index subspaces are right next to each other, then the broadcasted indexing space directly replaces all of the indexed subspaces in x. If the indexing subspaces are separated (by slice objects), then the broadcasted indexing space is first, followed by the sliced subspace of x.

在使用高级索引的 a 定义中,您有效地将序列 [0, 1] 作为元组的第三项传入,并且由于没有广播发生(因为没有其他序列),一切都按预期发生。

b 的定义中,同样使用高级索引,您有效地传递了 两个 序列,[0],第一个项目(被转换成一个intp数组),和[0, 1],第三项。这两项一起广播,结果与第三项的形状相同。然而,由于广播已经发生,我们面临一个问题:我们将广播的形状插入到新形状元组中的什么位置?正如文档所说,

there is no unambiguous place to drop in the indexing subspace, thus it is tacked-on to the beginning.

因此,广播产生的 2 被移动到形状元组的开头,产生明显的转置。

关于python - Numpy 多维数组索引交换轴顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11942747/

相关文章:

python - 检查两个 numpy 数组之间是否相等

python - 加权平均,其中一个权重是无限的

python - 如何从有序字典中选择最佳对?

Python 正则表达式插入符号在多行模式下不起作用?

python - "Fork and Join"具有无服务器函数(例如 AWS Lambda)/Python

python - 在新的 subprocess.Popen 对象列表上使用 poll()

python - 使用OpenCV-Python,如何有效地同时使用Python列表和Numpy数组?

python - 在 Beam 中读取和写入序列化的 protobuf

python - Django - 根据用户组显示/隐藏基本 html 中的 url?

Python:查找索引