第4章:科学计算库NumPy——数组创建与操作、矩阵运算、随机数生成、线性代数与统计函数
NumPy,说白了就是Python科学计算的基石。我做了这么多年材料模拟,几乎每个项目都离不开它。你想想看,处理XRD数据、分析应力应变曲线、做有限元的前处理——哪样不得跟数组打交道?NumPy就是那个让你跟数组打交道的利器。
核心要点:NumPy的核心是ndarray对象,它比Python原生列表快几十倍。原因很简单——底层用C语言实现,内存连续存储,还支持向量化操作。
4.1 数组创建:从零开始搭积木
创建数组的方法很多,我习惯用这几种:
import numpy as np
# 从列表创建
arr1 = np.array([1, 2, 3, 4, 5])
# 全零数组——我经常用来初始化
zeros = np.zeros((3, 4))
# 全一数组
ones = np.ones((2, 3))
# 等差数列——做坐标轴时特别好用
x = np.linspace(0, 10, 100) # 0到10之间均匀取100个点
# 随机数组
rand_arr = np.random.rand(3, 3) # 0~1均匀分布
randn_arr = np.random.randn(1000) # 标准正态分布
我的小技巧:做材料性能预测时,我常用np.linspace生成温度或成分的扫描点。比如模拟不同温度下的杨氏模量,直接生成100个温度点,一次算完。
4.2 数组操作:切片、变形、拼接
数组操作是日常最频繁的工作。嗯,这里要注意几个坑:
arr = np.arange(12).reshape(3, 4)
# 切片——跟Python列表类似
sub = arr[1:3, 0:2] # 取第2~3行,第1~2列
# 变形——reshape不改变原数组
flat = arr.flatten() # 展平成一维
# 拼接——做数据增强时常用
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])
c = np.vstack((a, b)) # 垂直拼接
d = np.hstack((a, a)) # 水平拼接
我曾经踩过的坑:切片操作返回的是视图,不是副本!如果你修改了切片,原数组也会变。想要独立副本,记得用.copy()。有一次我调试了半天,发现数据莫名其妙变了,就是这原因。
4.3 矩阵运算:材料计算的硬核部分
矩阵运算在材料科学里太常见了。应力张量、应变张量、刚度矩阵——全是矩阵。NumPy让这些计算变得异常简单:
# 矩阵乘法
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
C = np.dot(A, B) # 或者 A @ B
# 转置
A_T = A.T
# 求逆——计算柔度矩阵时必用
A_inv = np.linalg.inv(A)
# 特征值——分析材料稳定性时用
eigenvalues, eigenvectors = np.linalg.eig(A)
实际案例:我在做复合材料弹性性能预测时,需要计算各向异性材料的刚度矩阵。用NumPy的矩阵运算,原本需要手算半小时的矩阵乘法,一行代码就搞定。而且不容易出错。
4.4 随机数生成:模拟与蒙特卡洛
随机数在材料模拟中用途很广。比如模拟晶粒生长、蒙特卡洛方法、随机缺陷分布等。
# 设置种子——保证结果可复现
np.random.seed(42)
# 均匀分布
uniform = np.random.uniform(0, 1, 1000)
# 正态分布——模拟测量误差
normal = np.random.normal(0, 0.1, 1000) # 均值0,标准差0.1
# 随机整数——随机选择样本
indices = np.random.randint(0, 100, 10)
# 随机排列——打乱数据顺序
shuffled = np.random.permutation(100)
我的习惯:每次做随机模拟前,一定先设种子。不然下次跑结果不一样,你都不知道是算法问题还是随机性导致的。设了种子,调试起来省心多了。
4.5 线性代数:不止是解方程
NumPy的线性代数模块np.linalg功能很全。我常用的有:
| 函数 | 用途 | 材料科学应用场景 |
|---|---|---|
| np.linalg.solve | 解线性方程组 | 有限元分析中的刚度方程 |
| np.linalg.eig | 特征值分解 | 晶体振动模式分析 |
| np.linalg.svd | 奇异值分解 | 材料数据降维 |
| np.linalg.norm | 计算范数 | 误差分析、残差计算 |
# 解线性方程组——比如求解节点位移
A = np.array([[3, 1], [1, 2]])
b = np.array([9, 8])
x = np.linalg.solve(A, b)
print(x) # [2. 3.]
# 最小二乘法——拟合材料参数
x_fit, residuals, rank, s = np.linalg.lstsq(A, b, rcond=None)
4.6 统计函数:数据说话的底气
做材料实验,数据出来了总得分析吧?NumPy的统计函数就是干这个的:
data = np.random.normal(100, 15, 1000) # 模拟1000个强度数据
mean = np.mean(data) # 均值——平均强度
std = np.std(data) # 标准差——数据离散程度
var = np.var(data) # 方差
min_val = np.min(data) # 最小值
max_val = np.max(data) # 最大值
median = np.median(data) # 中位数——抗异常值干扰
# 百分位数——做质量控制时常用
q25 = np.percentile(data, 25)
q75 = np.percentile(data, 75)
# 相关系数——分析成分与性能的关系
strength = np.random.normal(200, 20, 100)
hardness = strength * 0.8 + np.random.normal(0, 10, 100)
corr = np.corrcoef(strength, hardness)
print(f"相关系数矩阵:\n{corr}")
注意:统计函数默认计算整个数组的统计量。如果想按行或列计算,记得指定axis参数。比如np.mean(data, axis=0)计算每列的均值。我刚开始用的时候经常忘记,结果算出来的东西完全不对。
知识体系总览
下面这张图是我自己整理的NumPy知识结构,你可以照着这个路径学习:
说实话,NumPy学好了,后面学Pandas、Scikit-learn都会轻松很多。它就像盖房子的地基——地基打牢了,上面盖什么都稳当。
最后分享一个经验:刚开始学NumPy时,别急着背所有函数。先掌握数组创建、切片、基本运算这三大块。遇到具体问题再查文档,用多了自然就记住了。我到现在还经常翻NumPy官方文档呢。
公众号:蓝海资料掘金营,微信deep3321