平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“NumPy 中合并(或组合)多个数组的函数的做法实现方法”来说,它看着像小点,放到项目里常会牵出环境、配置、兼容性和维护成本。下面按实际采用顺序,把思路、关键写法和容易踩坑的地方讲清楚,便于大家直接对照操作。
从实现思路看,以下是对 NumPy 中用来合同时(或组合)多个数组的函数 的全面、系统、深入且结构清晰的详解。我们将涵盖所有主流函数(包括 concatenate、stack、vstack、hstack、dstack、column_stack、row_stack、block、r_/c_ 等),详细说明其:
- 功能原理
- 输入要求
- 输出形状
- 与其它函数的关系
- 典型应用场景
- 常用陷阱与注意事项
在这个场景下,同时辅以大量示例代码和对比表格,确保你彻底掌握 NumPy 数组合并的全貌。
一、核心概念:什么是“合并”?
实际处理时,在 NumPy 里,“合同时”通常指将两个或多个数组组合成一个更大的数组。根据是否引入新维度,可分为两类:
- 在这个场景下,沿已有轴拼接(Concatenation):不增加维度,只是延长某个方向。
- 如:把两个 (3,) 向量拼成 (6,) 向量。
- 从实现思路看,沿新轴堆叠(Stacking):新建一个新维度,将原数组作为“切片”放入。
- 如:把两个 (3,) 向量堆成 (2, 3) 矩阵。
理解这一区别是掌握所有合并函数的关键。
二、主要合并函数详解
1.np.concatenate
功能
沿已存在的轴连接数组序列。
语法
np.concatenate(arrays, axis=0, out=None)
要求
- 所有输入数组必须具有相同的维数(ndim)。
- 除 axis 维度外,其余维度的大小必须完全一致。
输出形状
与输入数组相同维度,仅 axis 方向长度相加。
示例
# 1D
a = np.array([1, 2]); b = np.array([3, 4])
np.concatenate([a, b]) # [1 2 3 4], shape=(4,)
# 2D, axis=0(行拼接)
A = np.array([[1, 2]]); B = np.array([[3, 4]])
np.concatenate([A, B], axis=0) # [[1 2], [3 4]], shape=(2,2)
# 2D, axis=1(列拼接)
C = np.array([[1], [2]]); D = np.array([[3], [4]])
np.concatenate([C, D], axis=1) # [[1 3], [2 4]], shape=(2,2)
注意
- 不兼容自动升维。若想拼接 1D 到 2D,需先 reshape。
- 结合项目来看,axis=None 会先展平所有数组再拼接(等价于 np.hstack + flatten)。
2.np.stack
功能
沿新新建的轴堆叠数组,强制所有输入形状完全相同。
语法
np.stack(arrays, axis=0, out=None)
要求
- 所有数组必须形状完全一致(包括维度数和各维大小)。
- axis 可为负值(如 axis=-1 表示最后一维)。
输出形状
原形状插入一个新维度:new_shape = old_shape[:axis] + (N,) + old_shape[axis:],其中 N 是数组个数。
示例
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
# 默认 axis=0
np.stack([a, b])
# [[1 2 3]
# [4 5 6]], shape=(2,3)
# axis=1
np.stack([a, b], axis=1)
# [[1 4]
# [2 5]
# [3 6]], shape=(3,2)
# 2D 示例
X = np.ones((2,3)); Y = np.zeros((2,3))
np.stack([X, Y], axis=2) # shape=(2,3,2)
与 concatenate 对比
| 特性 | concatenate | stack |
|---|---|---|
| 是否新增维度 | ||
| 输入形状要求 | 除 axis 外一致 | 完全一致 |
| 用途 | 扩展数据集 | 构造高维结构(batch、通道等) |
3.np.vstack(Vertical Stack)
功能
结合项目来看,垂直堆叠(按行方向拼接)。对 1D 数组特殊处理:自动升维为 (1, n)。
等价形式
- 对 ≥2D 数组:np.concatenate(..., axis=0)
- 对 1D 数组:先 reshape 为 (1, n) 再拼接
示例
# 1D → 自动升维
a = np.array([1, 2]); b = np.array([3, 4])
np.vstack([a, b])
# [[1 2]
# [3 4]], shape=(2,2)
# 2D
A = np.array([[1, 2]]); B = np.array([[3, 4]])
np.vstack([A, B]) # same as concatenate(axis=0)
注意
- 不适用来标量(0D)。
- 若混合 1D 和 2D,需确保列数匹配。
4.np.hstack(Horizontal Stack)
功能
水平堆叠(按列方向拼接)。
行为
- 对 1D:直接拼接成更长的 1D(等价于 concatenate)
- 对 ≥2D:concatenate(..., axis=1)
示例
# 1D
a = [1,2]; b = [3,4]
np.hstack([a,b]) # [1 2 3 4]
# 2D
A = [[1],[2]]; B = [[3],[4]]
np.hstack([A,B]) # [[1,3],[2,4]]
5.np.dstack(Depth Stack)
功能
沿**第 3 轴(深度)**堆叠,常用来图像通道合并。
等价
- 对 2D 数组:np.stack(..., axis=2)
- 对 1D 数组:先升维为 (1,1,n)?实际行为更复杂,建议避免混用。
示例
a = np.array([[1, 2]])
b = np.array([[3, 4]])
np.dstack([a, b])
# [[[1 3]
# [2 4]]], shape=(1,2,2)
理解这一步时,常用来将 R、G、B 三个 (H,W) 图像合成 (H,W,3) 彩色图。
6.np.column_stack
功能
将 1D 或 2D 数组按列组合成 2D 矩阵。
特殊规则
- 对 1D 数组:视为列向量(自动转为 (n,1))
- 对 2D 数组:直接按列拼接(同 hstack)
示例
x = np.array([1, 2, 3]) # (3,)
y = np.array([4, 5, 6]) # (3,)
np.column_stack([x, y])
# [[1 4]
# [2 5]
# [3 6]] ← 每个输入成为一列
# 与 stack(axis=1) 等价
np.stack([x, y], axis=1) # 相同结果
很适合将多个特征向量组合成设计矩阵(design matrix)。
7.np.row_stack
功能
等价于 np.vstack,仅为语义清晰提供别名。
np.row_stack == np.vstack # True
8.np.block
功能
实际处理时,最灵活的合同时函数,兼容嵌套列表构建分块矩阵(block matrix)。
特点
- 可混合不同形状的子数组(只要最后能对齐)
- 兼容任意嵌套层级
- 自动推断维度
示例
A = np.eye(2) * 2 # [[2,0],[0,2]]
B = np.ones((2,3)) # [[1,1,1],[1,1,1]]
C = np.zeros((3,2)) # [[0,0],[0,0],[0,0]]
D = np.eye(3) * 3 # 3x3
# 构建分块矩阵 [[A, B],
# [C, D]]
M = np.block([[A, B],
[C, D]])
print(M.shape) # (5, 5)
类似 MATLAB 的 [A B; C D] 语法。
注意
- 子块必须在非拼接维度上对齐(如 A 和 B 必须行数相同)。
- 比 concatenate 更高层,适合构造复杂结构。
9.np.r_和np.c_(便捷索引器)
功能
借助类似切片的语法更快拼接数组。
- np.r_:类似 vstack(按行)
- np.c_:类似 column_stack(按列)
示例
# r_: 拼接行(1D 变多行)
np.r_[1:4, 0, 0] # [1 2 3 0 0]
a = np.array([1,2]); b = np.array([3,4])
np.r_[a, b] # [1 2 3 4] (1D 拼接)
# c_: 拼接列
np.c_[a, b]
# [[1 3]
# [2 4]]
# 也可用于生成网格
x = np.array([1,2]); y = np.array([10,20])
np.c_[x, y, x+y]
# [[1 10 11]
# [2 20 22]]
实际处理时,底层调用 concatenate 或 column_stack,适合交互式采用。
三、函数关系与等价性总结
| 函数 | 等价表达式 | 适用场景 |
|---|---|---|
| vstack | concatenate(axis=0)(对 ≥2D) 1D 自动升维 | 更快上下拼接 |
| hstack | concatenate(axis=1)(对 ≥2D) 1D 直接拼接 | 更快左右拼接 |
| dstack | stack(axis=2)(对 2D) | 图像通道、深度堆叠 |
| column_stack | stack(axis=1)(对 1D) hstack(对 2D) | 特征列组合 |
| row_stack | vstack | 语义清晰 |
| r_ / c_ | 封装了 concatenate/column_stack | 快捷交互式拼接 |
| block | 多层 concatenate 组合 | 复杂分块矩阵 |
四、选择指南:何时用哪个?
| 场景 | 建议函数 |
|---|---|
| 合并两个样本列表(如训练集+验证集) | concatenate |
| 将多个向量组成矩阵的列 | column_stack 或 stack(axis=1) |
| 构造 batch 数据(如 10 张图像 → (10, H, W)) | stack |
| RGB 三通道合成彩色图像 | dstack 或 stack(axis=-1) |
| 更快上下拼接表格数据 | vstack |
| 更快左右拼接特征 | hstack |
| 构建分块矩阵(如线性代数中的增广矩阵) | block |
| 交互式更快拼接 | r_ / c_ |
五、常用错误与调试技巧
维度不匹配
- 报错:ValueError: all the input array dimensions except for the concatenation axis must match exactly
- 解决:检查 shape,必要时用 reshape 或 np.newaxis 调整。
axis 越界
- 1D 数组没有 axis=1
- 解决:先确认数组维度:arr.ndim
混淆 stack 与 concatenate
- 错误预期:以为 stack 会延长数组
- 正确理解:stack 是“打包”,concatenate 是“拉长”
混合 1D/2D 导致意外升维
- vstack([1D, 2D]) 可能出错
- 建议:统一输入维度后再操作
六、性能提示
- concatenate 通常比 stack 更高效(不新增维度)
- 频繁拼接大数组时,应预先分配内存(避免多次拷贝)
- 理解这一步时,对于大量小数组拼接,考虑用 list.append + 一次 concatenate
七、总结
NumPy 提供了丰富而灵活的数组合同时工具,核心在于理解:
- 是否新增维度(stack vs concatenate)
- 拼接方向(axis=0 行,axis=1 列,axis=2 深度)
- 输入形状约束
在这个场景下,掌握这些函数后,你能够高效地处理从轻松数据拼接到复杂张量构建的各种任务。
在这个场景下,总的来说,NumPy 合同时多数组适合结合实际项目边做边理解。先抓住核心思路,再逐步补上细节和边界处理,最后效果会更稳定,也更容易复用。

