Numpy 3D数组在单步索引和两步索引时转换

use*_*814 6 python indexing numpy

import numpy as np
x = np.random.randn(2, 3, 4)
mask = np.array([1, 0, 1, 0], dtype=np.bool)
y = x[0, :, mask]
z = x[0, :, :][:, mask]
print(y)
print(z)
print(y.T)
Run Code Online (Sandbox Code Playgroud)

为什么分两步完成上述操作会导致一步到位?

hpa*_*ulj 5

这与列表索引的行为相同:

In [87]: x=np.arange(2*3*4).reshape(2,3,4)
In [88]: x[0,:,[0,2]]
Out[88]: 
array([[ 0,  4,  8],
       [ 2,  6, 10]])
In [89]: x[0,:,:][:,[0,2]]
Out[89]: 
array([[ 0,  2],
       [ 4,  6],
       [ 8, 10]])
Run Code Online (Sandbox Code Playgroud)

在第二种情况下,x[0,:,:]返回一个(3,4)数组,下一个索引选择2列.

在第一种情况下,它首先选择第一个和最后一个维度,然后附加切片(中间维度).的0[0,2]产生一个2尺寸,并且3从中间被附加,赋予(2,3)形状.

这是混合基本和高级索引的情况.

http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#combining-advanced-and-basic-indexing

在第一种情况下,高级索引操作产生的维度首先出现在结果数组中,然后是子空间维度.

这不是一个容易理解或解释的案例.基本上对最终维度应该是什么有一些模糊性.它试图用一个例子来说明,x[:,ind_1,:,ind_2]其中ind_1ind_2是3d(或者一起广播到那里).

早期解释这一点的尝试是:

numpy order数组切片索引如何?

结合多维numpy数组的切片和广播索引

===========================

解决这个问题的方法是用数组替换切片 - 列向量

In [221]: x[0,np.array([0,1,2])[:,None],[0,2]]
Out[221]: 
array([[ 0,  2],
       [ 4,  6],
       [ 8, 10]])
In [222]: np.ix_([0],[0,1,2],[0,2])
Out[222]: 
(array([[[0]]]), array([[[0],
         [1],
         [2]]]), array([[[0, 2]]]))
In [223]: x[np.ix_([0],[0,1,2],[0,2])]
Out[223]: 
array([[[ 0,  2],
        [ 4,  6],
        [ 8, 10]]])
Run Code Online (Sandbox Code Playgroud)

虽然最后一个案例是3d,(1,3,2). ix_不喜欢标量0.另一种使用方式ix_:

In [224]: i,j=np.ix_([0,1,2],[0,2])
In [225]: x[0,i,j]
Out[225]: 
array([[ 0,  2],
       [ 4,  6],
       [ 8, 10]])
Run Code Online (Sandbox Code Playgroud)

这是一种获得相同数字的方法,但是在(2,1,3)数组中:

In [232]: i,j=np.ix_([0,2],[0])
In [233]: x[j,:,i]
Out[233]: 
array([[[ 0,  4,  8]],

       [[ 2,  6, 10]]])
Run Code Online (Sandbox Code Playgroud)