NumPy 速查表
最后更新
创建数组
数组在任意维度的网格中存放同一种类型的值。
| 操作 | 代码 |
|---|---|
| 导入 NumPy | import numpy as np |
| 从列表创建 | np.array([1, 2, 3]) |
| 用嵌套列表创建二维数组 | np.array([[1, 2, 3], [4, 5, 6]]) |
| 全 0、全 1、填充同一个值 | np.zeros((2, 3)), np.ones(4), np.full((2, 2), 7) |
| 按步长生成范围(不含终点) | np.arange(0, 10, 2) # [0 2 4 6 8] |
| n 个等间距的点(含终点) | np.linspace(0, 1, 5) # [0. 0.25 0.5 0.75 1.] |
| 单位矩阵 | np.eye(3) |
| 与另一个数组形状相同 | np.zeros_like(m), np.ones_like(m) |
| 指定元素类型 | np.array([1, 2, 3], dtype=np.float32) |
| 坐标网格 | xx, yy = np.meshgrid(np.arange(3), np.arange(2)) |
查看数组信息
| 操作 | 代码 |
|---|---|
| 形状:每个维度的大小 | m.shape # (3, 4) |
| 维度数 | m.ndim # 2 |
| 元素个数 | m.size # 12 |
| 元素类型 | m.dtype # int64 |
| 转换类型 | m.astype(np.float64) |
| 第一个维度的长度 | len(m) # 3 |
| 转回 Python 列表 | m.tolist() |
| 打印时少显示几位小数 | np.set_printoptions(precision=3, suppress=True) |
索引与切片
切片是视图,与原数组共享内存;布尔掩码和索引列表返回的是副本。
| 操作 | 代码 |
|---|---|
| 第一个和最后一个元素 | a[0], a[-1] |
| 切片 start:stop(不含 stop) | a[1:4] # [20 30 40] |
| 每隔一个取一个、反转 | a[::2], a[::-1] |
| 二维数组中的单个元素 | m[1, 2] # 6 |
| 取一行、取一列 | m[0], m[:, 1] |
| 取若干行和列组成的块 | m[:2, 1:3] |
| 满足条件的元素 | a[a > 25] # [30 40 50] |
| 组合多个条件 | a[(a > 15) & (a < 45)] |
| 按位置列表取值 | a[[0, 2, 4]] |
| 满足条件的位置 | np.flatnonzero(a > 25) # [2 3 4] |
| 逐元素二选一 | np.where(a > 25, a, 0) |
| 修改切片前先复制 | part = a[1:3].copy() |
| 用掩码赋值 | a[a > 40] = 0 |
数学运算与广播
运算符逐元素生效。广播会把标量、行或列扩展成与另一个数组相同的形状。
| 操作 | 代码 |
|---|---|
| 逐元素算术运算 | x + y, x - y, x * y, x / y, x ** 2 |
| 与标量运算 | x * 10 |
| 平方根、指数、对数 | np.sqrt(x), np.exp(x), np.log(x) |
| 绝对值、四舍五入 | np.abs(x - 5), np.round(x / 3, 2) |
| 把值限制在某个范围内 | np.clip(x, 2, 8) |
| 逐元素取最大值 | np.maximum(x, 3) |
| 点积 | x @ y # 37.0 |
| 每列减去均值(广播一行) | m - m.mean(axis=0) |
| 按行归一化(广播一列) | m / m.sum(axis=1, keepdims=True) |
| 安全地比较浮点数 | np.isclose(0.1 + 0.2, 0.3) # True, np.allclose(x, y) |
| 三角函数和 pi | np.sin(np.pi / 2) # 1.0 |
按轴聚合
axis=0 沿着行的方向向下计算,每列得到一个结果;axis=1 沿着列的方向横向计算,每行得到一个结果。
| 操作 | 代码 |
|---|---|
| 所有元素求和 | m.sum() # 21 |
| 每列一个结果 | m.sum(axis=0) # [5 7 9] |
| 每行一个结果 | m.sum(axis=1) # [ 6 15] |
| 均值和标准差 | m.mean(), m.std(), m.mean(axis=0) |
| 最小值、最大值 | m.min(), m.max(axis=1) |
| 最大值的位置 | m.argmax(), m.argmax(axis=1) |
| 中位数和百分位数 | np.median(m), np.percentile(m, [25, 50, 75]) |
| 累计求和 | np.cumsum(m, axis=1) |
| 所有元素的乘积 | m.prod() # 720 |
| 任意、全部、计数 | (m > 4).any(), (m > 0).all(), np.count_nonzero(m > 2) |
变形与合并
reshape 保留所有元素、只改变形状,所以元素总数必须保持不变。
| 操作 | 代码 |
|---|---|
| 改成新形状 | a.reshape(2, 3) |
| 让 NumPy 自动算出某一维的大小 | a.reshape(3, -1), a.reshape(-1, 1) |
| 展平成一维 | m.ravel(), m.flatten() |
| 转置 | m.T |
| 增加一个维度 | a[:, np.newaxis], np.expand_dims(a, axis=0) |
| 去掉大小为 1 的维度 | np.squeeze(np.ones((1, 3, 1))) |
| 沿已有的轴拼接 | np.concatenate([a, a]) |
| 按行或按列堆叠 | np.vstack([m, m]), np.hstack([m, m]) |
| 把一维数组作为列 | np.column_stack([a, a ** 2]) |
| 沿新轴堆叠 | np.stack([a, a], axis=0) # shape (2, 6) |
| 拆分成多块 | np.split(a, 3), np.array_split(a, 4) |
| 重复或平铺 | np.repeat([1, 2], 2) # [1 1 2 2], np.tile([1, 2], 2) # [1 2 1 2] |
排序、查找与去重
| 操作 | 代码 |
|---|---|
| 返回排序后的副本 | np.sort(a) |
| 从大到小 | np.sort(a)[::-1] |
| 排序后各元素的原位置 | np.argsort(a) |
| 最大的三个值 | np.sort(a)[-3:] |
| 去重后的值及出现次数 | values, counts = np.unique(a, return_counts=True) |
NumPy 2 新名称(unique_values 结果可能未排序) | np.unique_values(a), np.unique_counts(a) |
| 每个元素是否在列表中? | np.isin(a, [1, 9]) |
| 在有序数组中的插入位置 | np.searchsorted([1, 3, 5, 7], 4) # 2 |
| 集合运算 | np.intersect1d(a, [1, 2, 10]), np.union1d(a, [10]), np.setdiff1d(a, [1]) |
| 按某一列对行排序 | m[m[:, 1].argsort()] |
随机数
创建一个设定了种子的 Generator,所有随机数都从它生成,这样每次运行结果都一样。
| 操作 | 代码 |
|---|---|
| 设定种子的生成器 | rng = np.random.default_rng(42) |
| [0, 1) 内的浮点数 | rng.random(3) |
| 整数,不含上限 | rng.integers(1, 7, size=10) |
| 正态分布 | rng.normal(loc=0, scale=1, size=(2, 3)) |
| 某个范围内的均匀分布浮点数 | rng.uniform(5, 10, size=4) |
| 从列表中随机抽取 | rng.choice(["a", "b", "c"], size=5) |
| 不重复抽取 | rng.choice(10, size=3, replace=False) |
| 按权重抽取 | rng.choice(["H", "T"], size=10, p=[0.7, 0.3]) |
| 打乱后的副本、原地打乱 | rng.permutation(a), rng.shuffle(a) |
| 二项分布和泊松分布计数 | rng.binomial(10, 0.5, size=5), rng.poisson(3, size=5) |
线性代数
| 操作 | 代码 |
|---|---|
| 矩阵乘法 | A @ A |
| 求解 Ax = b | np.linalg.solve(A, b) # [0.8 1.4] |
| 逆矩阵和行列式 | np.linalg.inv(A), np.linalg.det(A) |
| 向量长度 | np.linalg.norm(b) |
| 特征值和特征向量 | values, vectors = np.linalg.eig(A) |
| 拟合一条直线 | slope, intercept = np.polyfit(x, y, 1) |
| 外积 | np.outer([1, 2], [3, 4]) |
| 对角线和迹 | np.diag(A), np.trace(A) |
缺失值与特殊值
np.nan 表示缺失的浮点数。任何与它进行的算术运算结果都是 nan,所以要用 nan 系列函数或掩码处理。
| 操作 | 代码 |
|---|---|
| 缺失值 | np.nan |
| 查找缺失值 | np.isnan(v), np.isnan(v).sum() |
| 删除缺失值 | v[~np.isnan(v)] |
| 替换缺失值和无穷大 | np.nan_to_num(v, nan=0.0, posinf=0.0) |
| 无穷大与有限值检查 | np.inf, np.isfinite(v) |
| 跳过 NaN 的统计函数 | np.nanmean(v[:3]) # 2.0, np.nanmax(v) |
保存与加载
| 操作 | 代码 |
|---|---|
| 单个数组,二进制文件 | np.save("data.npy", m), m = np.load("data.npy") |
| 一个文件保存多个数组 | np.savez("data.npz", x=x, y=y), np.load("data.npz")["x"] |
| 写入 CSV 文本 | np.savetxt("data.csv", m, delimiter=",", fmt="%d") |
| 读取 CSV 文本 | np.loadtxt("data.csv", delimiter=",") |
NumPy 2:旧名称与现在的写法
NumPy 2 删除了许多别名,所以从旧教程复制来的代码可能会报 AttributeError。
| 操作 | NumPy 2 | 旧写法 |
|---|---|---|
| 缺失值 | np.nan | np.NaN |
| 无穷大 | np.inf | np.Inf |
| 64 位浮点类型 | np.float64 | np.float_ |
| 曲线下面积 | np.trapezoid(y, x) | np.trapz(y, x) |
| 每个元素是否在另一个数组中? | np.isin(a, b) | np.in1d(a, b) |
| 按行堆叠 | np.vstack([a, a]) | np.row_stack([a, a]) |
| 乘积 | np.prod(a) | np.product(a) |
| 随机数 | rng = np.random.default_rng(0)
rng.random(3) | np.random.seed(0)
np.random.rand(3) |
数据科学代码离不开的 NumPy 调用,按任务分组:创建数组、查看数组信息、索引与切片、逐元素运算、按轴聚合、变形与合并、排序与查找、生成随机数,以及线性代数求解。每一行都是一段可以直接粘贴的短代码,再配一句话说明它的作用。
这里的内容全部基于 Coddy 运行的 NumPy 2 编写,最后一张表列出了 NumPy 2 删除的名称,旁边写明了现在该怎么写。大多数示例使用 a = np.array([3, 1, 4, 1, 5, 9, 2, 6]) 和 m = np.arange(12).reshape(3, 4)。还不熟悉 Python 本身?先看 Python 速查表,试试 Python 在线编辑器,再把 pandas、Matplotlib 和 scikit-learn 速查表放在手边一起用。
NumPy 速查表常见问题
这份 NumPy 速查表免费吗?
免费。这份 NumPy 速查表完全免费,无需注册。把它加入书签,或者在浏览器里打印成 PDF,需要查 reshape、按轴求和或随机抽样的写法时随时回来看。
这份速查表对应哪个 NumPy 版本?
np.NaN、np.float_、np.trapz 和 np.in1d 等别名,最后一张表把它们和现在的名称一一对应列出。NumPy 中的 axis=0 是什么意思?
axis=0 沿着行向下计算,所以 m.sum(axis=0) 为每一列返回一个总和;axis=1 沿着列横向计算,为每一行返回一个总和。不指定 axis 时,函数会使用所有元素。视图和副本有什么区别?
a[1:3] 这样的切片是视图:它与 a 共享内存,修改切片也会修改 a。像 a[a > 2] 或 a[[0, 2]] 这样的布尔掩码和索引列表返回的是副本。需要一个独立的数组时,调用 .copy()。为什么用 NumPy 数组而不是 Python 列表?
a * 2 会把每个元素翻倍,而 [1, 2] * 2 只是把列表重复一遍。pandas 和 scikit-learn 都是建立在 NumPy 数组之上的。应该用 np.random.seed 还是 default_rng?
rng = np.random.default_rng(seed),然后调用 rng 上的方法,比如 rng.normal() 或 rng.integers()。这是官方推荐的 API,随机数流更好,也没有隐藏的全局状态。np.random.seed 和 np.random.rand 仍然可用,但属于旧接口。