跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

NumPy数组怎么拼接_np.concatenate()与vstack/hstack纵横向合并

np.concatenate()默认axis=0(垂直拼接),横向需显式指定axis=1;vstack/hstack行为特殊,尤其对1D数组;多次调用concatenate性能差,应一次性拼接或预分配。 拼接方向搞错:
np.concatenate()
默认按 axis=0 合并,不是“自动识别横竖” 很多人以为
np.concatenate()
会像
vstack
hstack
那样“智能判断方向”,其实它完全依赖
axis
参数。不显式指定
axis
,就按第 0 轴(行方向)合并,等价于
vstack
—— 即堆叠成更高数组,而不是更宽。 想横向拼(列方向),必须写
axis=1
,否则报
ValueError: all the input arrays must have same number of dimensions
或形状不匹配
vstack
底层就是
concatenate(..., axis=0)
hstack
在 2D 数组下等价于
concatenate(..., axis=1)
,但注意:
hstack
对 1D 数组行为特殊(会先转成列向量再水平拼) 如果数组维度不一致(比如一个 (3, 4),另一个 (3,)),
concatenate
直接报错;而
vstack
/
hstack
会尝试广播或隐式升维,反而容易掩盖问题 1D 数组拼接时
vstack
hstack
行为反直觉 对一维数组,
vstack([a, b])
会把每个
a
b
当作“一行”,结果是二维的;而
hstack([a, b])
是真正把元素首尾相连,返回一维数组 —— 这和名字的“v/h”直观感受相反。
a = np.array([1, 2]); b = np.array([3, 4])
vstack([a, b]) → array([[1, 2], [3, 4]])
(2×2)
hstack([a, b]) → array([1, 2, 3, 4])
(1D,长度 4) 这时用
concatenate([a, b])
才等价于
hstack
;想等价
vstack
,得先
reshape(-1, 1)
或改用
axis=0
+ 显式二维输入 性能与内存:多次
concatenate
比预分配后赋值慢得多
np.concatenate()
每次都新建数组、拷贝数据。循环里反复调用,时间复杂度是 O(n²),尤其拼大数组时延迟明显。 避免:
res = arr0; for a in arr_list: res = np.concatenate([res, a])
推荐:先收集所有数组到列表,一次拼完 ——
np.concatenate(arr_list)
若拼接逻辑复杂(如条件过滤后拼),考虑预分配目标数组(用
np.empty
np.zeros
),再用切片赋值,比反复
concatenate
快一个数量级以上
vstack
/
hstack
内部也是调
concatenate
,所以同样有这问题,别以为换函数就自动优化 常见错误:形状不兼容却没立刻报错 最典型的坑是拼接时某维长度不一致但其他维碰巧对得上,导致运行时不报错、结果错得隐蔽。比如两个数组都是 2D,但一个 (5, 3),另一个 (5, 4),用
axis=1
拼会崩;但如果一个是 (5, 3),另一个是 (5, 1),
concatenate
不报错,但你可能根本没意识到发生了广播式拼接(实际不会广播,这里指人为误判)—— 真正危险的是维度数不同还硬拼。 错误示例:
np.concatenate([np.ones((3, 4)), np.ones((3,))], axis=1)
→ 报错,因为 (3,) 不能直接在 axis=1 拼到 (3, 4) 上 但
np.concatenate([np.ones((3, 4)), np.ones((3, 1))], axis=1)
成功,结果是 (3, 5),容易漏看末尾多了一列全 1 建议拼之前加检查:
all(a.shape[1:] == arr_list[0].shape[1:] for a in arr_list)
(对 axis=0);或用
np.broadcast_arrays
预探路 事情说清了就结束

相关文章