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,2)
b: (2,5)
c: (5,2)

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

由于大量的单元测试,我能够围绕这些不一致的方式设计我的代码,但是理解正在发生的事情将会受到赞赏.

作为参考,我使用Python 2.7.3和Numpy 1.6.2通过MacPorts.

解决方法

从语法上讲,这看起来像是一种不一致,但从语义上讲,你在这里做了两件截然不同的事情.在您对a和b的定义中,您正在执行 advanced indexing,有时称为 fancy indexing,它返回数据的副本.在你的c定义中,你正在做 basic slicing,它返回一个数据视图.

为了区分它,有助于理解索引如何传递给python对象.这里有些例子:

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

如您所见,有许多不同的可能配置.首先,可以传递单个项目,或者可以传递项目元组.其次,元组可能包含切片对象,省略号对象,普通整数或numpy数组.

仅传递int,slice或Ellipsis对象或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相关文章