NumPy 数值计算基础
标签: #Python #NumPy #数值计算 #ndarray #广播机制 #线性代数
学习周期:2 天 | 核心目标:掌握 NumPy 多维数组的创建、索引、运算及广播机制,为数据分析和机器学习打下基础
4.1 NumPy(数值计算)
NumPy(Numerical Python)是 Python 科学计算的核心库,提供了高性能的多维数组对象ndarray和丰富的数组运算函数。几乎所有数据分析和机器学习库(如 Pandas、Scikit-learn、TensorFlow)都基于 NumPy。
核心优势:高速度(底层 C 语言实现)、高内存效率、丰富的数值运算功能。
安装与导入
pip install numpyimport numpy as np4.1.1ndarray多维数组的创建与属性(shape, dtype)
1. 创建数组
从列表/元组创建
# 一维数组 arr1 = np.array([1, 2, 3, 4, 5]) # 二维数组(列表嵌套) arr2 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 指定数据类型 arr_float = np.array([1, 2, 3], dtype=np.float64) arr_int = np.array([1, 2, 3], dtype=np.int32)内置创建函数(常用)
| 函数 | 说明 | 示例 |
|---|---|---|
np.zeros(shape) | 全0数组 | np.zeros((2,3)) |
np.ones(shape) | 全1数组 | np.ones((3,2), dtype=np.int32) |
np.eye(N) | 单位矩阵(N×N) | np.eye(3) |
np.full(shape, value) | 填充指定值 | np.full((2,3), 7) |
np.arange(start, stop, step) | 等差数列(类似 range) | np.arange(0, 10, 2)→[0,2,4,6,8] |
np.linspace(start, stop, num) | 等间隔序列 | np.linspace(0, 1, 5)→[0.,0.25,0.5,0.75,1.] |
np.random.rand(d0,d1) | [0,1) 均匀分布 | np.random.rand(2,3) |
np.random.randn(d0,d1) | 标准正态分布 | np.random.randn(2,3) |
np.random.randint(low, high, size) | 随机整数 | np.random.randint(0, 10, (2,3)) |
2. 数组属性
arr = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float64) print(arr.shape) # (2, 3) → 2行3列 print(arr.ndim) # 2 → 维度数 print(arr.size) # 6 → 元素总数 print(arr.dtype) # float64 → 数据类型 print(arr.itemsize) # 8 → 每个元素字节数 # 改变形状(不改变原数组,返回新数组) arr_reshape = arr.reshape((3, 2))易错点:
np.array()中的元素类型必须一致,否则会自动向上转换(如 int + float → float)。reshape()新形状的元素总数必须与原数组相同。- 一维数组的
shape是(n,),注意末尾逗号。
4.1.2 索引、切片、布尔索引、花式索引
基础索引(按位置)
arr1 = np.arange(10) print(arr1[3]) # 3 print(arr1[-1]) # 9 arr2 = np.array([[1,2,3],[4,5,6],[7,8,9]]) print(arr2[0,0]) # 1 print(arr2[1,2]) # 6 print(arr2[2]) # [7,8,9](整行)切片(范围取值)
# 一维切片 arr1 = np.arange(10) print(arr1[2:5]) # [2,3,4] print(arr1[::2]) # [0,2,4,6,8] # 二维切片 arr2 = np.array([[1,2,3],[4,5,6],[7,8,9]]) print(arr2[:2, :2]) # [[1,2],[4,5]] print(arr2[:, 1]) # [2,5,8](第2列) print(arr2[1, :]) # [4,5,6](第2行) # ⚠️ 切片返回视图,修改会影响原数组 slice_view = arr2[:2, :2] slice_view[0,0] = 100 print(arr2[0,0]) # 变为100布尔索引(条件筛选)
arr = np.array([[1,2,3],[4,5,6],[7,8,9]]) mask = arr > 5 print(mask) # 布尔数组 print(arr[mask]) # [6,7,8,9] # 多条件(& 且,| 或,注意括号) print(arr[(arr > 3) & (arr < 8)]) # [4,5,6,7] print(arr[(arr == 2) | (arr == 8)]) # [2,8]花式索引(整数列表索引)
arr1 = np.arange(10) indices = [1,3,5,7] print(arr1[indices]) # [1,3,5,7] arr2 = np.array([[1,2,3],[4,5,6],[7,8,9]]) row = [0,2]; col = [1,2] print(arr2[row, col]) # [2,9](取(0,1)和(2,2)) print(arr2[[0,2], :]) # 取第1行和第3行的所有列索引方式对比
| 方式 | 返回类型 | 是否影响原数组 |
|---|---|---|
| 基础索引 | 标量或子数组 | 修改影响原数组 |
| 切片 | 视图(view) | 修改影响原数组 |
| 布尔索引 | 副本(copy) | 修改不影响原数组 |
| 花式索引 | 副本(copy) | 修改不影响原数组 |
4.1.3 广播机制(Broadcasting)
广播允许不同形状的数组进行算术运算,无需手动调整形状。
核心规则(从尾部维度对齐):
- 维度较少的数组在前面补1。
- 每个维度上,两个数组的形状要么相等,要么其中一个为1,要么缺失。
- 满足条件则可广播;否则报错
ValueError。
# 标量与数组 arr = np.array([1,2,3]) print(arr + 10) # [11,12,13] # 一维 + 二维 a = np.array([[1,2,3],[4,5,6]]) # (2,3) b = np.array([10,20,30]) # (3,) → 广播为 (1,3) → (2,3) print(a + b) # 每行加 b # 列向量广播 col = np.array([[1],[2],[3]]) # (3,1) row = np.array([10,20,30]) # (3,) → (1,3) print(col + row) # (3,3) # 不兼容示例 # a = np.ones((3,2)); b = np.ones((4,)) → ValueError4.1.4 通用函数(ufunc)
通用函数对数组逐元素高效运算,底层 C 实现,速度极快。
数学函数
arr = np.array([1,4,9,16]) print(np.sqrt(arr)) # [1.,2.,3.,4.] print(np.exp(arr)) # e^x print(np.log(arr)) # 自然对数 print(np.log10(arr)) # 以10为底 print(np.sin(arr)) # 正弦(弧度) print(np.cos(arr)) print(np.abs([-1,-2])) # [1,2] print(np.ceil(3.2)) # 4.0 print(np.floor(3.9)) # 3.0二元通用函数
a = np.array([1,2,3]) b = np.array([4,5,6]) print(np.add(a,b)) # [5,7,9] print(np.maximum(a,b)) # [4,5,6] print(np.minimum(a,b)) # [1,2,3] print(np.power(a,2)) # [1,4,9]比较函数
print(np.greater(a,b)) # [False,False,False] print(np.equal(a,b)) # [False,False,False]4.1.5 数组运算
元素级算术运算
a = np.array([[1,2],[3,4]]) b = np.array([[5,6],[7,8]]) print(a + b) # 加法 print(a - b) # 减法 print(a * b) # 逐元素乘法(不是矩阵乘法) print(a / b) # 除法 print(a ** 2) # 逐元素平方矩阵乘法
# 方式1:@ 运算符(推荐) print(a @ b) # 方式2:np.dot() print(np.dot(a, b)) # 方式3:np.matmul() print(np.matmul(a, b)) # 一维数组点积 x = np.array([1,2,3]) y = np.array([4,5,6]) print(np.dot(x, y)) # 1*4+2*5+3*6=32统计方法
arr = np.array([[1,2,3],[4,5,6],[7,8,9]]) print(arr.sum()) # 45(总和) print(arr.sum(axis=0)) # [12,15,18](按列求和) print(arr.sum(axis=1)) # [6,15,24](按行求和) print(arr.mean()) # 5.0 print(arr.mean(axis=0)) # [4.,5.,6.] print(arr.std()) # 标准差 print(arr.var()) # 方差 print(arr.max()) # 9 print(arr.min()) # 1 print(arr.argmax(axis=0)) # 每列最大值的行索引 [2,2,2] print(np.median(arr)) # 5.0(中位数) print(arr.cumsum()) # 累积和 [1,3,6,10,15,21,28,36,45]axis参数理解:
axis=0:沿着行方向(垂直),对每一列操作axis=1:沿着列方向(水平),对每一行操作
4.1.6 线性代数基础(np.linalg)
import numpy as np from numpy import linalg as LA A = np.array([[1, 2], [3, 4]]) B = np.array([[5, 6], [7, 8]]) # 矩阵乘法 C = A @ B # 转置 print(A.T) # [[1,3],[2,4]] # 逆矩阵(仅方阵) A_inv = LA.inv(A) print(A @ A_inv) # 近似单位矩阵 # 行列式 det = LA.det(A) # -2.0 # 迹(对角线之和) trace = np.trace(A) # 5 # 特征值和特征向量 eigenvalues, eigenvectors = LA.eig(A) # 解线性方程组 Ax = b A_eq = np.array([[3,1],[1,2]]) b_eq = np.array([9,8]) x = LA.solve(A_eq, b_eq) # [2.,3.] # 矩阵的秩 rank = LA.matrix_rank(A) # 2 # 最小二乘法(拟合) # x_lsq, residuals, rank, s = LA.lstsq(A, b, rcond=None)注意事项:
- 求逆和行列式仅适用于方阵,非方阵会报错。
- 若矩阵奇异(行列式为0),
inv()会抛出LinAlgError。 solve()要求系数矩阵满秩,否则用lstsq()。
📚 学习资料(Obsidian 可直接收藏)
官方文档
NumPy 官方快速入门
NumPy 中文文档
广播机制详解
线性代数指南中文教程
菜鸟教程 - NumPy
廖雪峰 - NumPy 基础视频推荐
莫烦 Python - NumPy 教程(B站)
🎯 学习建议(2 天计划)
- 第 1 天:掌握
ndarray创建、属性、基本索引和切片,重点练习布尔索引和花式索引,理解广播机制。 - 第 2 天:学习通用函数、数组运算(矩阵乘法、统计方法),了解
np.linalg常用线性代数函数。
✅ 核心要点总结
ndarray:同质多维数组,核心属性shape、dtype、ndim、size。- 创建方式:
np.array()、np.zeros()、np.ones()、np.arange()、np.linspace()、np.random.rand()等。 - 索引与切片:基本索引、切片(返回视图)、布尔索引(返回副本)、花式索引(返回副本)。
- 广播机制:形状兼容的数组可直接运算,自动扩展维度,规则清晰。
- 通用函数(ufunc):
np.sqrt()、np.exp()、np.sin()等,逐元素高效计算。 - 数组运算:元素级算术运算;矩阵乘法用
@或np.dot();统计方法可指定axis。 - 线性代数:
np.linalg提供逆、行列式、特征值、解方程组等。
练习题(自测)
- 创建一个 5×5 的随机整数矩阵(范围 0-100),计算其均值、标准差、最大值和最小值。
- 创建两个 3×3 矩阵
A和B,计算A + B、A - B、A @ B以及A的转置。 - 使用布尔索引将数组中所有大于 5 的元素替换为 0。
- 创建一个形状为 (4, 3) 的数组,通过广播将每一行都减去该行的平均值(实现行中心化)。
- 解线性方程组:
2x + y = 5 x - 3y = -1 - 生成 1000 个服从正态分布的随机数,计算其均值和标准差,并绘制直方图(可使用 Matplotlib,选做)。
建议在 Jupyter Notebook 中逐步练习,观察数组形状和广播行为。