Python NumPy 进阶教程(中篇)

liftword23小时前技术文章2
  • 本篇(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)

  1. np.linalg 与 scipy.linalg:当需要更多高级线性代数功能时,可使用 SciPy。
    (For more advanced linear algebra, consider scipy.linalg.)
  2. 随机数种子:使用 np.random.seed() 来保证实验结果可复现。
    (Set a random seed for reproducible results.)
  3. 运算效率:在数值计算中尽量使用向量化操作,避免 Python 层循环。
    (Use vectorized operations instead of Python loops for better performance.)

相关文章

面试必考的「矩阵快速幂」考点汇总

设想这样一个场景,面试官给了你一道算法题,你很快确定这是一道递推问题,并给出了 O(n) 的解题方法,然而面试官却继续问:“还能继续优化吗?”这样类似的场景并不少见,因为算法不仅追求「正确」,还追求「...

11-Python 库将数百行代码浓缩为一行

#寻找热爱表达的你#在今天的文章中,我们选取了 11 个 Python 库,测试了它们在效率和优化方面的流行说法是否真实。这些库以将数百行代码简化为几行甚至一行而闻名! 它们不仅让你的项目更加流畅,...

傻傻分不清楚的点积与矩阵乘法 Part3

作者:Minkyung Kang译者:知源觅流原文链接:https://github.com/mkang32/python-basics/blob/master/numpy/dot_vs_multip...

傻傻分不清楚的点积与矩阵乘法 Part2

作者:Minkyung Kang译者:知源觅流原文链接:https://github.com/mkang32/python-basics/blob/master/numpy/dot_vs_multip...

如何用 Python 制作矩阵:详细指南

什么是矩阵?在深入研究之前,先了解一下什么是矩阵:它是按行和列排列的数字矩形数组。在Python中,我们通常使用嵌套列表来表示矩阵,其中每个内部列表代表一行。使用列表创建基本矩阵让从创建矩阵的最简单方...