1. 引言:SciPy 与 MATLAB 的数组世界
在科学计算和数据分析领域,数组(Array)是最核心的数据结构之一。MATLAB 以其强大的矩阵运算能力而闻名,而 Python 的 SciPy 生态系统(特别是 NumPy 库)则提供了与之媲美甚至更灵活的多维数组操作能力。本文将深入对比 SciPy(NumPy)与 MATLAB 在数组创建、索引、运算、线性代数、随机数生成等方面的异同,并通过丰富的代码实例展示如何将常见的 MATLAB 数组操作迁移到 Python 环境中。
2. 环境准备与基础导入
在开始之前,请确保已安装必要的 Python 库:
# 安装命令(如未安装)
# pip install numpy scipy matplotlib
在 Python 中,我们通常这样导入相关模块:
import numpy as np
import scipy as sp
import scipy.linalg as la # 线性代数模块
import scipy.stats as stats # 统计模块
对应的 MATLAB 环境则内置了所有核心功能,无需额外安装。
3. 数组创建与初始化
3.1 创建零数组、单位数组和全一数组
MATLAB:
% 创建 3x4 的零矩阵
A_zeros = zeros(3, 4);
% 创建 5x5 的单位矩阵
I = eye(5);
% 创建 2x3 的全一矩阵
A_ones = ones(2, 3);
% 创建 2x2x2 的三维全一数组
A_3d = ones(2, 2, 2);
SciPy/NumPy:
# 创建 3x4 的零数组
A_zeros = np.zeros((3, 4))
创建 5x5 的单位矩阵
I = np.eye(5)
创建 2x3 的全一数组
A_ones = np.ones((2, 3))
创建 2x2x2 的三维全一数组
A_3d = np.ones((2, 2, 2))
关键区别: NumPy 使用元组 (rows, cols) 指定形状,而 MATLAB 使用逗号分隔参数。
3.2 创建等差数列数组(linspace)和随机数组
MATLAB:
% 从 0 到 10,生成 5 个等间距点
x = linspace(0, 10, 5);
% 创建 3x3 的随机矩阵(均匀分布,0~1)
R_rand = rand(3, 3);
% 创建 2x4 的正态分布随机矩阵(均值为 0,标准差为 1)
R_randn = randn(2, 4);
SciPy/NumPy:
# 从 0 到 10,生成 5 个等间距点
x = np.linspace(0, 10, 5)
创建 3x3 的随机数组(均匀分布,0~1)
R_rand = np.random.rand(3, 3)
创建 2x4 的正态分布随机数组(均值为 0,标准差为 1)
R_randn = np.random.randn(2, 4)
4. 数组索引与切片
4.1 基础索引(从 0 开始 vs 从 1 开始)
MATLAB(索引从 1 开始):
A = [1, 2, 3; 4, 5, 6; 7, 8, 9];
first_element = A(1, 1); % 结果为 1
last_element = A(3, 3); % 结果为 9
SciPy/NumPy(索引从 0 开始):
A = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
first_element = A[0, 0] # 结果为 1
last_element = A[2, 2] # 结果为 9
4.2 切片操作
MATLAB:
A = magic(5); % 创建一个 5x5 的魔方阵
% 获取第 2 到第 4 行,第 1 到第 3 列
subA = A(2:4, 1:3);
% 获取所有行,第 3 列
col3 = A(:, 3);
% 获取第 2 行,所有列
row2 = A(2, :);
% 使用步长:获取第 1, 3, 5 行
odd_rows = A(1:2:5, :);
SciPy/NumPy:
A = np.array([[17, 24, 1, 8, 15],
[23, 5, 7, 14, 16],
[4, 6, 13, 20, 22],
[10, 12, 19, 21, 3],
[11, 18, 25, 2, 9]]) # 一个 5x5 魔方阵
获取第 2 到第 4 行(索引 1:4),第 1 到第 3 列(索引 0:3)
subA = A[1:4, 0:3]
获取所有行,第 3 列(索引 2)
col3 = A[:, 2]
获取第 2 行(索引 1),所有列
row2 = A[1, :]
使用步长:获取第 1, 3, 5 行(索引 0:5:2)
odd_rows = A[0:5:2, :]
关键区别: MATLAB 的切片包含结束索引,而 NumPy 的切片不包含结束索引(即 start:stop 表示 [start, stop))。
5. 数组运算与线性代数
5.1 元素级运算与矩阵乘法
MATLAB:
A = [1, 2; 3, 4];
B = [5, 6; 7, 8];
% 元素级加法
C_elementwise_add = A + B;
% 元素级乘法(逐元素相乘)
C_elementwise_mul = A .* B;
% 矩阵乘法
C_matrix_mul = A * B;
% 矩阵转置
A_transpose = A';
% 矩阵求逆
A_inv = inv(A);
SciPy/NumPy:
A = np.array([[1, 2],
[3, 4]])
B = np.array([[5, 6],
[7, 8]])
元素级加法
C_elementwise_add = A + B
元素级乘法(逐元素相乘)
C_elementwise_mul = A * B # 注意:NumPy 中 * 是元素级乘法
矩阵乘法
C_matrix_mul = A @ B # Python 3.5+ 推荐用法
或使用 np.dot(A, B)
矩阵转置
A_transpose = A.T
矩阵求逆
A_inv = np.linalg.inv(A)
5.2 解线性方程组
MATLAB:
A = [3, 2; 1, 4];
b = [5; 6];
x = A \ b; % 使用反斜杠求解 Ax = b
SciPy:
A = np.array([[3, 2],
[1, 4]])
b = np.array([5, 6])
x = np.linalg.solve(A, b) # 求解 Ax = b
5.3 特征值与特征向量
MATLAB:
A = [4, 1; 2, 3];
[V, D] = eig(A); % V 是特征向量矩阵,D 是对角特征值矩阵
SciPy:
A = np.array([[4, 1],
[2, 3]])
D, V = np.linalg.eig(A) # 注意:NumPy 返回的顺序是特征值数组 D 和特征向量矩阵 V
# D 是特征值数组,V 的列是对应的特征向量
6. 随机数生成与统计
6.1 常见分布
MATLAB:
% 生成 10 个均匀分布随机数(0~1)
unif = rand(10, 1);
% 生成 5x5 正态分布矩阵(均值 0,标准差 1)
norm = randn(5, 5);
% 生成 100 个泊松分布随机数(λ=3)
poiss = poissrnd(3, 100, 1);
SciPy:
import numpy as np
from scipy import stats
生成 10 个均匀分布随机数(0~1)
unif = np.random.rand(10)
生成 5x5 正态分布数组(均值 0,标准差 1)
norm = np.random.randn(5, 5)
生成 100 个泊松分布随机数(λ=3)
poiss = stats.poisson.rvs(3, size=100)
6.2 统计计算
MATLAB:
data = randn(100, 1);
mean_val = mean(data);
std_val = std(data);
median_val = median(data);
SciPy/NumPy:
data = np.random.randn(100)
mean_val = np.mean(data)
std_val = np.std(data)
median_val = np.median(data)
7. 数组形状操作与广播
7.1 改变数组形状
MATLAB:
A = 1:12; % 1x12 行向量
B = reshape(A, 3, 4); % 重塑为 3x4 矩阵
C = reshape(A, 2, 3, 2); % 重塑为 2x3x2 三维数组
SciPy/NumPy:
A = np.arange(1, 13) # 1 到 12 的数组
B = A.reshape(3, 4) # 重塑为 3x4 矩阵
C = A.reshape(2, 3, 2) # 重塑为 2x3x2 三维数组
7.2 广播(Broadcasting)机制
广播是 NumPy 中强大的特性,允许不同形状的数组进行算术运算。MATLAB 通过 bsxfun 函数实现类似功能(R2016b 后部分操作自动支持广播)。
NumPy 广播示例:
# 创建一个 3x4 矩阵
matrix = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
创建一个长度为 4 的行向量
row_vector = np.array([10, 20, 30, 40])
广播:矩阵的每一行都加上这个行向量
result = matrix + row_vector
print(result)
输出:
[[11 22 33 44]
[15 26 37 48]
[19 30 41 52]]
8. 文件 I/O:保存与加载数组
8.1 MATLAB 文件(.mat)的读写
MATLAB 保存:
A = rand(5, 5);
B = magic(3);
save('data.mat', 'A', 'B');
SciPy 读取 .mat 文件:
from scipy import io
读取 .mat 文件
mat_data = io.loadmat('data.mat')
A = mat_data['A']
B = mat_data['B']
保存到 .mat 文件
io.savemat('new_data.mat', {'A': A, 'B': B})
8.2 NumPy 原生格式(.npy, .npz)
import numpy as np
保存单个数组到 .npy 文件
arr = np.random.rand(10, 10)
np.save('array.npy', arr)
loaded_arr = np.load('array.npy')
保存多个数组到 .npz 文件(压缩格式)
arr1 = np.ones((5, 5))
arr2 = np.zeros((3, 3))
np.savez('arrays.npz', matrix1=arr1, matrix2=arr2)
data = np.load('arrays.npz')
loaded_arr1 = data['matrix1']
loaded_arr2 = data['matrix2']
9. 性能对比与实用技巧
9.1 向量化操作
无论是 MATLAB 还是 NumPy,向量化操作都比循环快得多:
MATLAB 向量化示例:
% 低效的循环
n = 1000000;
result = zeros(n, 1);
for i = 1:n
result(i) = sin(i/1000);
end
% 高效的向量化
x = 1:n;
result = sin(x/1000);
NumPy 向量化示例:
import numpy as np
低效的循环
n = 1000000
result = np.zeros(n)
for i in range(n):
result[i] = np.sin(i/1000)
高效的向量化
x = np.arange(1, n+1)
result = np.sin(x/1000)
9.2 内存布局与视图
NumPy 数组有 C_CONTIGUOUS(行优先)和 F_CONTIGUOUS(列优先)两种内存布局,后者与 MATLAB 兼容:
import numpy as np
创建 Fortran 顺序(列优先)数组,与 MATLAB 内存布局一致
A_fortran = np.array([[1, 2, 3],
[4, 5, 6]], order='F')
print(A_fortran.flags)
输出:C_CONTIGUOUS : False, F_CONTIGUOUS : True
10. 总结与迁移建议
SciPy/NumPy 与 MATLAB 在数组操作上有着高度的相似性,但也存在一些重要区别:
- 索引: MATLAB 从 1 开始,NumPy 从 0 开始
- 切片: MATLAB 包含结束索引,NumPy 不包含结束索引
- 矩阵乘法: MATLAB 使用
*,NumPy 使用@或np.dot - 元素级乘法: MATL

1001

被折叠的 条评论
为什么被折叠?



