Matlab与Python/Numpy高维矩阵线性索引顺序的区别

这里我将在介绍索引顺序之前介绍一下创建矩阵,因为这里也是利用的线性索引,有助于理解后面的索引顺序。

创建矩阵

同样是创建从1到60的3×4×5的三维矩阵,可以从下面这个简单的例子中一窥两者的区别,大家可以体会一下。为了方便观察,三维图只展示了落在三个平面上的数字,但应该已经足够理解了。

Numpy:

import numpy as np
a=np.arange(1,61).reshape(3,4,5)

Matlab与Python/Numpy高维矩阵线性索引顺序的区别

我们可以看到,Numpy是按照z-y-x的顺序填充元素的,想象比作把元素向矩阵容器里塞,每个z轴是一根管子,那就是在塞满a[0,0,:]后,接着去塞a[0,1,:],到第二维被塞满后才去塞a[1,0,:]。

Matlab:

b=reshape(1:60,[3,4,5])

Matlab与Python/Numpy高维矩阵线性索引顺序的区别

Matlab的填充方式则恰恰相反,在将最低维“塞满”后,才开始向高维叠加。

布尔索引

接下来展示两者进行布尔索引的时候的不同,为了保持一致性,均使用之前由Matlab创建的矩阵来索引,Python中的矩阵由Matlab中读取而来:

save('test.mat',b)
from scipy.io import loadmat
b = loadmat('test.mat')['b']

Numpy:

b[b%5==0]

Matlab与Python/Numpy高维矩阵线性索引顺序的区别

对比前面的三维图可以看出,Numpy索引元素的顺序依然是按照其创建矩阵时的顺序来列出索引的。

此外如果将Numpy的整个矩阵打印到终端,还可以看到,越内侧的方括号维数越高,下面是b[0,:,:],即上面第二张图的y-z面:

Matlab与Python/Numpy高维矩阵线性索引顺序的区别

Matlab:

b(rem(b,5)==0)  % 列出可以被5整除的元素的线性索引

Matlab与Python/Numpy高维矩阵线性索引顺序的区别

由于是拿Matlab创建的矩阵索引,所以顺序和创建时的大小顺序一致。

总结

Matlab创建和索引矩阵时是以最低维开始,逐步向高维叠加,符合人类直觉。而Numpy则相反,是从最高维开始索引。