第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 核心 数组创建 np.array() np.zeros() / np.ones() np.linspace() np.random.rand() 数组操作 切片与索引 reshape / flatten vstack / hstack 广播机制 矩阵运算 np.dot() / @ 转置 .T 求逆 np.linalg.inv() 特征值分解 随机数生成 np.random.seed() 均匀/正态分布 随机整数/排列 线性代数 np.linalg.solve() np.linalg.eig() SVD分解 最小二乘法 统计函数 均值/中位数/方差 最大值/最小值 百分位数 相关系数 材料科学数据处理的核心工具

说实话,NumPy学好了,后面学Pandas、Scikit-learn都会轻松很多。它就像盖房子的地基——地基打牢了,上面盖什么都稳当。

最后分享一个经验:刚开始学NumPy时,别急着背所有函数。先掌握数组创建、切片、基本运算这三大块。遇到具体问题再查文档,用多了自然就记住了。我到现在还经常翻NumPy官方文档呢。


公众号:蓝海资料掘金营,微信deep3321