Python NumPy 进阶教程(中篇)
- 本篇(This intermediate tutorial)将进一步(deeper into)探讨——
- 广播机制(Broadcasting)、统计函数(statistical functions)、线性代数操作(linear algebra)、随机数 以及更多进阶技巧(advanced techniques)
1. 广播机制 (Broadcasting)
1.1 广播简介
NumPy 的广播机制允许在数组形状不完全相同的情况下进行运算
示例:
import numpy as np
音乐人 = np.array(["周杰伦", "林俊杰", "王力宏"]) #shape为(3,)
特点 = np.array([["爱唱歌"], ["很帅"]]) #shape为(2,1),末尾维度为1,可广播
句子 = 音乐人 + 特点
print(句子)
# 输出:
#[['周杰伦爱唱歌' '林俊杰爱唱歌' '王力宏爱唱歌']
# ['周杰伦很帅' '林俊杰很帅' '王力宏很帅']]
1.2 广播规则 (Rules)
- 只要在某些维度上大小为 1 或相同,就能自动“扩展”至匹配形状
- 若在某个维度上不满足上述条件,则运算会报错(the operation raises an error)
1.3 不能广播的例子
机构 = np.array(["医院", "学校"]) # shape为(2,)
地址 = np.array(["北京", "上海", "广州"]) # shape为(3,)
print(地址.ndim)
result = 机构 + 地址
print(result)
# 机构和地址的维度不一致,无法使用广播机制
2. 统计与聚合函数 (Statistical & Aggregate Functions)
NumPy 提供了丰富的统计函数,如求和、均值、标准差、最值等,通常对整数组或指定轴进行计算。
数字组 = np.array([[21, 31, 41], [12, 22, 32], [13, 23, 33]])
print("最大值:", np.max(数字组))
print("最小值:", np.min(数字组))
print("中位数:", np.median(数字组))
print("标准差:", np.std(数字组))
print("方差:", np.var(数字组))
print("累加:", np.cumsum(数字组))
print("累乘:", np.cumprod(数字组))
print("最大值的索引:", np.argmax(数字组))
print("和:", np.sum(数字组))
print("按行求和:", np.sum(数字组, axis=1))
print("按列求和:", np.sum(数字组, axis=0))
print("平均值:", np.mean(数字组))
print("按行求平均值:", np.mean(数字组, axis=1))
3. 线性代数操作
NumPy 提供了基本的线性代数功能,如矩阵乘法、求逆、特征值分解等。
3.1 矩阵乘法
长江 = np.array([[1, 2], [3, 4]])
黄河 = np.array([[5, 6], [7, 8]])
print("长江 * 黄河:", 长江 * 黄河) # 相同位置对应元素相乘
print("长江.dot(黄河):", 长江.dot(黄河)) # 矩阵乘法,或者使用np.dot(长江, 黄河),或者长江 @ 黄河
# 向量外积
长江 = np.array([10, 20, 30])
黄河 = np.array([7, 8])
print(np.outer(长江, 黄河)) # 长江的每个元素与黄河的每个元素相乘,得到一个3x2的矩阵
# 输出:
# [[ 70 80
# [140 160]
# [210 240]]
# 向量内积
长江 = np.array([10, 20, 30])
黄河 = np.array([1, 2, 3])
print(np.inner(长江, 黄河)) # 长江的每个元素与黄河的每个元素相乘,再求和,得到一个标量
# 输出:140
3.2 求逆与求解线性方程组
# 定义一个 2x2 矩阵
A = np.array([[1, 2], [3, 4]]) ##矩阵必须是方阵:只有方阵(即行数和列数相同)才有逆矩阵
# 检查矩阵是否可逆
if np.linalg.det(A) != 0: # 矩阵必须是非奇异的:矩阵的行列式必须不为零
# 求逆矩阵
A_inv = np.linalg.inv(A)
print("逆矩阵 A_inv:", A_inv)
else:
print("矩阵 A 不可逆")
# =======================================================================
# 定义系数矩阵 A 和常数向量 b
A = np.array([[3, 1], [1, 2]])
b = np.array([9, 8])
# 使用 np.linalg.solve 求解
x = np.linalg.solve(A, b)
print("解向量 x:", x)
4.三角函数
# 定义角度(以弧度为单位)
角度 = np.array([0, np.pi/6, np.pi/4, np.pi/3, np.pi/2])
# 正弦值
正弦值 = np.sin(角度)
print("正弦值:", 正弦值)
# 余弦值
余弦值 = np.cos(角度)
print("余弦值:", 余弦值)
# 正切值
正切值 = np.tan(角度)
print("正切值:", 正切值)
# ----------------------------------------------------------------------
# 弧度与角度的转换
# 定义角度(度数)
度数 = np.array([0, 30, 45, 60, 90])
# 转换为弧度
弧度 = np.radians(度数)
print("弧度:", 弧度)
# 转换回度数
转换回度数 = np.degrees(弧度)
print("度数:", 转换回度数)
# ---------------------------------------------------------------------------
# 三角函数支持逐元素操作,可以直接对数组进行计算
角度 = np.linspace(0, 2 * np.pi, 10)
# 计算正弦值
正弦值 = np.sin(角度)
print("角度(弧度):", 角度)
print("正弦值:", 正弦值)
5. 随机数与模拟 (Random Numbers & Simulation)
NumPy 内置的 random 子模块可生成各种分布的随机数,常用于模拟与数据采样。
import numpy as np
# 设置随机种子 (set seed for reproducibility)
np.random.seed(42)
# 如果再次运行这段代码,输出结果会完全相同。
# 用于确保随机数生成的可复现性,便于调试和验证代码
# 生成 0~1 范围内的随机浮点数
浮点数 = np.random.rand(3, 3)
print("随机浮点数:\n", 浮点数)
# 生成服从正态分布的随机数
正态 = np.random.randn(3, 3)
print("正态分布随机数:\n", 正态)
# 生成 0~10 范围内的随机整数
随机整数 = np.random.randint(0, 10, size=(2, 2))
print("随机整数:\n", 随机整数)
6. 字符串操作
动物 = np.array(["猫", "狗", "鸟", "猪", "猫", "狗", "猪"])
行为 = np.array(["吃", "跑", "飞", "睡", "叫", "跳", "打滚"])
# 拼接
描述 = np.char.add(动物, 行为)
# 替换
描述 = np.char.replace(描述, "猫", "大黄猫")
print(描述)
# ------------------------------------------------------------------------
a = np.array(['hello', 'WORLD', 'NumPy'])
# 转换为大写
print(np.char.upper(a)) # 输出: ['HELLO' 'WORLD' 'NUMPY']
# 转换为小写
print(np.char.lower(a)) # 输出: ['hello' 'world' 'numpy']
# 首字母大写
print(np.char.capitalize(a)) # 输出: ['Hello' 'World' 'Numpy']
# 分割字符串
b = np.char.split(a) # 输出: [list(['hello']) list(['WORLD']) list(['NumPy'])]
# 计算字符串长度
print(np.char.str_len(a)) # 输出: [5 5 5]
7. 小贴士与注意事项 (Tips & Caveats)
- np.linalg 与 scipy.linalg:当需要更多高级线性代数功能时,可使用 SciPy。
(For more advanced linear algebra, consider scipy.linalg.) - 随机数种子:使用 np.random.seed() 来保证实验结果可复现。
(Set a random seed for reproducible results.) - 运算效率:在数值计算中尽量使用向量化操作,避免 Python 层循环。
(Use vectorized operations instead of Python loops for better performance.)