SciPy 与 MATLAB 数组操作对比:从基础到进阶的代码实例详解

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值