Toccata in Nowhere.

Numpy 与 MATLAB 的 flatten / reshape 函数的差异及解决方法

2020.07.25

在将 MATLAB 的算法移植到 numpy 时,仔细观察便会发现一些同名函数存在差异。flatten 和 reshape函数即是一个例子。

结果对比

以下分别用 MATLAB 和 Python 实现同一个二维数组的创建、flattenreshape

Python

import numpy as np

a = np.zeros([2,2])
xx = 0
for ii in range(2):
	for jj in range(2):
			a[ii, jj] = xx
			xx += 1

print(a)

print(a.flatten())
b = a.flatten().reshape(2,2)

print(b)

输出

[[0. 1.]
 [2. 3.]]
[0. 1. 2. 3.]
[[0. 1.]
 [2. 3.]]

MATLAB

x = 0;
for i=1:2
    for j=1:2
        a(i,j) = x;
        x = x + 1;
    end
end
disp(a);
disp(a(:));
b = reshape(a(:),[2,2]);
disp(b);

输出

 0     1
 2     3

 0
 2
 1
 3

 0     1
 2     3

可以看到此时 numpyflatten() 函数的输出与MATLAB不同,但经过flatten()reshape() 之后的结果又还原回来。

差异与解决

numpy 默认使用 Row-major order (C order)

MATLAB 则使用的是 Column-major order (Fortran order)

造成了结果的不一致。

可以在使用numpy的flatten() / reshape()函数时进行 order的指定,例如:

a = a.flatten(order='F')
b = a.reshape(2,2,order='F')
print(a)
print(b)

输出

[0. 2. 1. 3.]
[[0. 1.]
 [2. 3.]]

延伸

使用 Row-major order (C order) 的有C/C++/Objective-C 与 Pascal等语言;

使用 Column-major order (Fortran order) 的有 Fortran, MATLAB, R, Julia等语言。

在矩阵操作时务必注意。


Reference

MATLAB 与python reshape 比较

Wikipedia: Row- and column-major order