NumPy 函数速查表 - NumPy 常用命令与数组操作大全

这套速查面向常用 Python 处理数组的开发者,无论做数据分析、几何计算还是给模型做输入预处理都会用到:从 np.array/np.zeros 建数组,到索引起始值切片取数据、reshape 变换形状、sum/mean 做统计,再到 a @ b 做矩阵乘。与纯 API 手册不同,条目按"建数组→取值→变形→算账→存盘"的实战链路组织。读完应能想到每个阶段用哪个函数,并避开广播和视图/副本最容易踩的那几个坑。

编程语言·共 40 条命令·最后更新 2026-07-21
numpypython数据分析数组

典型使用场景

面向做数据清洗、统计计算与数值实验的工程师,尤其是从 pandas 或 R 迁过来需要先建立「ndarray 语义」的人。NumPy 的性能来自向量化,代价是形状与广播规则比 Python 列表严格得多。本表覆盖四组:数组创建(array / zeros / arange / linspace / 随机数)、索引与切片(布尔掩码、 Fancy indexing、多维切片)、形状变换(reshape / flatten / T / concatenate / split)、以及数学统计与广播和存取盘(sum / mean / std / dot / unique / save / loadtxt)。最该先掌握的两条规则是:reshape 返回视图而 flatten 返回副本(就地改会互相影响),以及形状不兼容时广播会报错或静默产生意外结果。

数组创建 9

np.array([1, 2, 3])
从列表创建数组
np.zeros((3, 4))
创建 3×4 全 0 数组
np.ones((2, 3))
创建 2×3 全 1 数组
np.arange(0, 10, 2)
等差数组 [0, 2, 4, 6, 8]
np.linspace(0, 1, 5)
0 到 1 等分 5 个点
np.eye(3)
3×3 单位矩阵
np.random.rand(3, 3)
3×3 均匀分布随机数
np.random.randn(3, 3)
3×3 标准正态分布
np.random.randint(0, 10, (2, 3))
2×3 随机整数

索引与切片 6

a[0]
取首个元素,结果是一个标量;取多行多列才是子数组
a[1:3]
切片取第 2、3 个元素,返回的是视图(view),修改它会影响原数组
a[a > 5]
布尔索引,保留满足条件 a > 5 的元素,常用于按阈值筛选/掩码取值
a[[0, 2, 4]]
花式索引,用整数数组按位置取指定行,返回的是副本而非视图
a[1:3, 2:4]
二维切片:取行 1-2、列 2-3 相交的子块
np.where(a > 5, a, 0)
条件替换:满足 a > 5 保留原值,否则置 0,批量做"大于阈值才计入"很常用

形状变换 8

a.shape
查看数组各维度长度,如 (3, 4) 表示 3 行 4 列
a.reshape(2, 3)
变换为 2×3 形状,元素总数必须一致;reshape 通常返回视图
a.flatten()
展平为一维数组,返回的是副本,改它不影响原数组
a.T
转置交换维度:二维即行列互换,一维数组转置前后不变
np.concatenate([a, b], axis=0)
沿指定轴拼接数组,除拼接轴外其余维度必须一致,用 axis 控制是拼行还是拼列
np.vstack([a, b])
垂直方向堆叠(上下拼接),要求列数一致
np.hstack([a, b])
水平方向堆叠(左右拼接),要求行数一致
np.split(a, 3)
沿默认轴把数组等分为 3 个子数组,若不能整除会抛错

数学与统计 10

a.sum()
对全部元素求和,传 axis 可沿指定轴求和(如按行/按列)
a.mean()
计算所有元素的算术平均值,同样支持 axis 参数做分轴均值
a.std()
计算标准差,衡量数据相对均值的离散程度,axis 可选
a.min() / a.max()
返回数组中的最小值 / 最大值
a.argmin() / a.argmax()
返回最小值 / 最大值出现的位置索引,配合扁平化常用于定位最值所在下标
a.cumsum()
累积和:第 i 位是前 i+1 个元素之和,常画累积分布图用
np.dot(a, b)
矩阵点积:按内积规则两两相乘再累加,适合向量/矩阵卷积基础运算
a @ b
矩阵乘法(Python 3.5+ 的 @ 运算符),等同 np.matmul,做线性代数和矩阵变换用
np.sort(a)
对数组排序并返回排序后的新数组;要原地排序可先调 a.sort()
np.unique(a)
去重并返回升序排列的独有元素,加 return_counts=True 可得各元素出现次数

广播与保存 7

a + 1
广播:每个元素加 1
a * 2
广播:每个元素乘 2
a + b(形状兼容即可)
广播运算
np.save("data.npy", a)
保存为 npy 文件
np.load("data.npy")
加载 npy 文件
np.savetxt("data.csv", a, delimiter=",")
保存为 CSV
np.loadtxt("data.csv", delimiter=",")
从 CSV 加载

参数矩阵

参数作用示例
np.array([1, 2, 3])从列表创建数组;dtype 决定元素类型,缺省按值推断np.array([1, 2, 3])
np.zeros((3, 4))按形状创建全零数组;注意参数是元组,写成 (3, 4) 而不是 3, 4np.zeros((3, 4))
np.ones((2, 3))按形状创建全 1 数组,常用作掩码或权重初值np.ones((2, 3))
np.arange(0, 10, 2)等差数列,不含终点;步长为浮点时会因精度产生意外的结束值np.arange(0, 10, 2)
np.linspace(0, 1, 5)在闭区间内均分 5 个点(含两端),画函数曲线时不会漏端点np.linspace(0, 1, 5)
np.eye(3)生成 3x3 单位矩阵,线性代数运算的基础件np.eye(3)
np.random.rand(3, 3)生成 [0, 1) 均匀分布的随机数矩阵np.random.rand(3, 3)
np.random.randn(3, 3)生成标准正态分布随机数矩阵;与 rand 的区别是分布不同而非取值范围np.random.randn(3, 3)
np.random.randint(0, 10, (2, 3))生成指定形状的随机整数,左闭右开np.random.randint(0, 10, (2, 3))
a[0]按维度取下标,返回的仍可能是数组而非标量,取决于维度a[0]
a[1:3]切片视图,不复制数据;改动切片会改到原数组a[1:3]
a[a > 5]布尔掩码筛选,返回副本,是过滤数据最直接的写法a[a > 5]
a[[0, 2, 4]]Fancy indexing 用索引数组取任意元素,返回副本a[[0, 2, 4]]
a[1:3, 2:4]多维切片,先切第一个维度再切第二个a[1:3, 2:4]
np.where(a > 5, a, 0)三参数形式按条件逐元素取值,是向量化条件赋值的核心np.where(a > 5, a, 0)
a.shape查看形状;比用 len 判断多维数组是否可靠得多a.shape
a.reshape(2, 3)返回视图,不复制数据;改视图元素会影响原数组,无法原地改形状a.reshape(2, 3)
a.flatten()返回一维副本,与 reshape 的最大差别就在是否复制a.flatten()
a.T转置视图,交换行列;一次矩阵乘法写错方向常源于此a.T
np.concatenate([a, b], axis=0)沿指定轴拼接,数组形状除拼接轴外必须完全一致np.concatenate([a, b], axis=0)
np.vstack / np.hstack按行/列堆叠,是 concatenate 在两个轴上的简写np.vstack([a, b])
np.split(a, 3)把数组切成 3 份;返回列表,各份按原顺序排列np.split(a, 3)
a.sum() / a.mean()默认对所有元素聚合;指定 axis 可沿某一维折叠并保持其它维a.sum()
a.std()标准差,默认总体口径;做数据归一化时最常用a.std()
a.argmin() / a.argmax()返回极值所在的扁平索引;二维数组要配合 unravel_index 才有意义a.argmin() / a.argmax()
a.cumsum()累积和,做累计分布、差分、滚动统计的基础a.cumsum()
np.dot(a, b) / a @ b点积与矩阵乘法,两种等价写法;形状必须满足矩阵乘法规则np.dot(a, b)
np.sort(a)返回排序后的副本,不改变原数组;就地排序用 a.sort()np.sort(a)
np.unique(a)去重并升序排序,是统计取值分布最省事的一行np.unique(a)
a + 1 / a * 2广播运算,标量自动扩展到每个元素,无需写循环a + 1
a + b(形状兼容即可)广播要求从右对齐且逐维兼容(一为 1 或相等),否则报 broadcast 错误a + b(形状兼容即可)
np.save("data.npy", a)保存为 .npy 二进制格式,保留 dtype 与形状,读取无损且快np.save("data.npy", a)
np.load("data.npy")读回 .npy;返回的是数组而不是路径(与 np.load 的其它用法易混)np.load("data.npy")
np.savetxt(..., delimiter=",")导出为纯文本 CSV,可读但丢失 dtype 信息,且大文件慢np.savetxt("data.csv", a, delimiter=",")
np.loadtxt("data.csv", delimiter=",")读回 CSV;指定 dtype 能避免整数被读成 floatnp.loadtxt("data.csv", delimiter=",")

易错点与避坑指南

现象改了 reshape 结果的元素,原数组也跟着变了。

原因reshape 在数组连续时返回视图,只有必要时才复制。

处置需要独立副本时先 copy() 或改用 flatten();要确认是否共享可看 base 属性。

现象两个数组相加报 operands could not be broadcast。

原因形状在某一维既不相等也不为 1;广播是逐维从右对齐匹配的。

处置先统一维度(a.reshape(-1, 1))或用 np.broadcast_to 显式扩展;别急着加循环。

现象结果形状变成 (N, 1) 而不是预期的 (N,),索引时行为诡异。

原因标量与数组运算、或 a[:, None] 切片引入的新维度导致轴没有消除。

处置用 a.shape 核对每一维;需要降到一维时用 a.ravel() 或 a.flatten()。

现象np.arange 生成的长度比预期多一个或少一个。

原因arange 不含终点,且浮点步长会累积误差,末值可能越过终点。

处置需要确定的点数改用 np.linspace(0, 1, 5),它按点数反推步长。

现象np.zeros(3, 4) 报 TypeError。

原因这是函数调用不是元组字面量,Python 会当成三个实参。

处置写成 np.zeros((3, 4)),用逗号传元组时必须带括号。

现象取 a[0] 得到一整行而不是一个数。

原因a 是二维数组,取第一维下标返回的是一行。

处置明确降维:a[0, 0] 或 a[0][0],或先 a.ravel() 再索引。

现象随机结果每次运行都不一样,无法复现实验。

原因直接使用全局随机状态,没有设置种子。

处置在脚本开头固定种子再生成,并记录版本号;对比实验时这步不能省。

现象np.load 返回的是 MemMap 而不是数组,改动意外写回了磁盘。

原因np.load 对 .npy 默认使用 mmap 模式共享内存映射。

处置需要普通数组时加 mmap_mode=None(默认即为普通读取时检查返回值类型)。

排障路径

  1. 1先看清每个数组的形状与类型

    print([(x.shape, x.dtype) for x in arrs])

    形状与 dtype 是九成广播与索引问题的根因。

  2. 2检查是否共享底层内存

    print(arr.reshape(-1).base)

    base 非 None 说明是视图,改动会互相影响。

  3. 3复现广播错误的具体维度

    print(np.broadcast(a, b))

    广播失败时会在这里直接暴露不兼容的轴。

  4. 4确认归一化后的取值范围

    print((a - a.mean()) / a.std())

    标准差为 0 的列会产生 NaN,需要先剔除。

  5. 5核对读回文件的形状与 dtype

    print(np.load("data.npy").shape)

    与保存前对比,确认没有被压缩或转换。

  6. 6确认 NumPy 版本

    python -c "import numpy; print(numpy.__version__)"

    跨版本行为差异(尤其是随机数与默认 dtype)是环境问题高发区。

命令示例

视图 vs 副本:切片与花式索引的差别

a = np.arange(12).reshape(3, 4) # 切片返回视图,改它会影响原数组 a[1:3, 2:4] = -1 # 花式索引返回副本,改它不影响原数组 b = a[[0, 2]] b[0, 0] = 99 # flatten 永远是副本 c = a.flatten() c[0] = 100

同一份数据用不同取法拿到的东西,身份完全不同:对切片赋值会静默改到原数组的共享内存,对花式索引或 flatten 的结果赋值则只改副本。要「读」就随便切,要「改之前先复制」就显式 a.copy()。

布尔索引 + np.where 做阈值筛选

a = np.arange(10) hot = a[a > 5] # 只保留大于 5 的元素 clamped = np.where(a > 5, a, 0) # 大于 5 保留,否则置 0 b = np.array([[1, 9], [7, 3]]) rows = b[b[:, 0] > 5] # 按条件挑行 count = int((a > 5).sum()) # 统计超阈值的个数

掩码求值的前提是数组是一维或掩码与被选维度长度一致;对二维数组写 a[a > 5] 会先把整块摊平成一维,再取符合条件的元素,形状悄悄变了。二维场景要挑行或挑列,就得先取某一列再比较。

广播:形状不同的数组逐元素运算

a = np.arange(6).reshape(2, 3) b = np.array([10, 20, 30]) # 形状 (3,) c = a + b # (2,3) + (3,) → (2,3),按列广播 d = a * 2 # 维度为 1 时也能广播 a = np.arange(3).reshape(3, 1) b = np.arange(3).reshape(1, 3) e = a + b # (3,1) + (1,3) → (3,3)

广播只沿长度为 1 的维度扩展,能免掉大量 tile/repeat。当两边同维但长度都不为 1 且不相等时报 shape 错;而当长度恰好都为 1 时又不会报错,广播出的结果形状可能与直觉相反,先打印 .shape 确认。

reshape 前先算清元素总数

a = np.arange(12) # 12 个元素 a.reshape(3, 4) # 12 = 3×4 b = a.reshape(-1, 1) # -1 表示该维度自动推断 c = a.reshape(2, -1) # 另一维自动算成 6 # 元素总数不一致会直接抛错 # a.reshape(5, 5)

reshape 不搬数据、只改形状描述,所以元素总数必须对得上,否则直接抛 ValueError。用 -1 让 NumPy 自己推一维,比手算除法更不容易错;真正需要改变内存布局时才用 reshape,单纯摊平用 flatten。

线性代数与去重计数

a = np.array([[1, 0], [0, 1]]) b = np.array([[2, 3], [4, 5]]) np.dot(a, b) a @ b # 去重并统计出现次数 vals, counts = np.unique([1, 1, 2, 3, 3, 3], return_counts=True)

点积与 @ 在一维向量上结果相同,在二维矩阵上分别是内积规则与标准矩阵乘法,别混用。unique 会自动排序,需要保持原顺序时得自己排 argsort;return_counts=True 是找频次分布最快的办法,不用再套 collections.Counter。

常见坑与注意事项

  • 整数数组做除法(a / b)默认得到浮点结果,这是与旧版本行为不同的地方,直接按整数截断的假设会让均值、比例类计算悄悄变错。
  • a[i] 取单个元素返回的是标量而不是长度为 1 的数组,取单个元素后再用二维索引会直接越界报错;需要保持形状时用 a[i:i+1]。
  • 切片返回视图,对它赋值会静默改掉原数组共享的那块内存;循环里逐块写入又没意识到这一点时,原数据被污染却毫无报错。
  • shape 不兼容的广播在某一维恰好都为 1 时不会报错,而是按广播规则静默扩展,结果形状与预期相反且难以察觉;做运算前先核对两边 .shape。
  • np.where 返回的是新数组,对它赋值不会改到原数据;想原地修改必须显式写回 a[:] = np.where(...),漏掉赋值就是一次静默的数据丢失。
  • 数组过大时 np.save / savetxt 与 np.load / loadtxt 都会把整个文件读进内存,几十 MB 就会耗尽内存;np.load 可配合 mmap_mode 惰性读取,纯 CSV 文本格式则不含 dtype 信息,loadtxt 需自己指定。

提示

  • NumPy 数组是同构的,所有元素类型必须一致,混类型会自动提升。
  • 广播规则:两个维度从后往前比较,相等或其中一个为 1 才能广播。
  • a * b 是元素级乘法,矩阵乘法用 a @ b 或 np.dot(a, b)。

常见问题

切片拿到的数据改了原数组也跟着变,怎么避免?

关键是分清视图和副本。切片 a[1:3] 和 reshape 通常返回视图,改它就是改原数组;布尔索引 a[a > 5]、花式索引 a[[0, 2, 4]] 返回副本;flatten() 明确返回副本,改它不影响原数组;np.sort(a) 也返回排序后的新数组,想原地排序要调 a.sort()。所以只是要读,用切片零成本;要安全地修改,先显式拷贝,例如 np.array(a[1:3]) 或用 np.copy 之类方式拿到独立数据再改。

a * b 和 a @ b 计算结果一样吗?

完全不一样。a * b 是逐元素相乘,两个形状兼容的数组会按广播规则展开后一一相乘;a @ b 是矩阵乘法(等价于 np.matmul),按行乘列再求和,要求内维度吻合。一维向量与同长向量相乘时,(a * b) 得到的是逐元素积,而 a @ b 得到的是内积这个标量。要做线性代数、矩阵变换就必须用 @ 或 np.dot(a, b);只做逐元素缩放则用 a * 2 这类广播写法。

数组形状对不上又不想改原数据,拼接和变换怎么选?

改形状用 reshape(2, 3),元素总数必须一致,通常返回视图;a.T 转置交换维度,二维即行列互换,一维数组转置前后不变;a.flatten() 展平成一维并返回副本。要合并多个数组则看方向:np.concatenate([a, b], axis=0) 最通用,沿指定轴拼接,除拼接轴外其余维度必须一致,axis=0 是拼行、axis=1 是拼列;np.vstack 上下拼要求列数一致,np.hstack 左右拼要求行数一致。拆开则用 np.split(a, 3) 沿默认轴等分,不能整除会抛错。

怎么按阈值筛选数据,或者把不满足条件的值替换掉?

两条路径。布尔索引直接取子集:a[a > 5] 保留满足 a > 5 的元素,常用于阈值筛选和掩码取值,取列同理写 a[a[:, 0] > 5]]。要做条件替换而不是筛选,用 np.where(a > 5, a, 0):三参数形式下满足条件取中间那个值,否则取最后一个参数,因此能实现「大于阈值才计入、否则置零」。np.where 还能只传两个参数当作条件判断,返回满足条件的元素索引。

随机数据和等差序列该用哪个函数生成?

要规则序列就用确定性的函数:np.arange(0, 10, 2) 生成 [0, 2, 4, 6, 8] 这类等差数列,步长直接给第三个参数;np.linspace(0, 1, 5) 表示在 0 到 1 之间取 5 个等分点(含首尾)。要随机数用 np 系列:np.random.rand(3, 3) 是 0 到 1 的均匀分布,np.random.randn(3, 3) 是标准正态分布,np.random.randint(0, 10, (2, 3)) 生成 0 到 10 之间的 2×3 随机整数。结构性占位数组则用 np.zeros((3, 4))、np.ones((2, 3)) 和 np.eye(3)。

官方参考来源

下方为命令对应的官方权威文档,供你核对最新用法与深入查阅。

由 巧匠 维护

公开更新于 2026年7月21日,内容持续校对官方文档。

联系我们

命令或描述有误?提交反馈、商务合作或产品建议都可发送邮件给我们。

联系我们