Skip to content

NumPy Concatenate:使用 np.concatenate、vstack 和 hstack 连接数组

Updated on

合并数组是数值计算中最常见的操作之一。你将数据分割进行处理,然后需要重新组合。你从多个来源将特征加载到一个矩阵中。你堆叠多个模型的预测以进行集成。使用 Python 列表通过循环或 + 来合并数组会破坏性能并产生不必要的副本。

NumPy 提供了专门的数组连接函数,这些函数以 C 语言的速度运行,并让你精确控制沿哪个轴进行连接。本指南涵盖了 np.concatenate()np.vstack()np.hstack()np.stack() 及其使用场景。

📚

np.concatenate() -- 核心函数

np.concatenate() 沿现有轴连接一系列数组。

一维数组

import numpy as np
 
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.array([7, 8, 9])
 
result = np.concatenate([a, b, c])
print(result)  # [1 2 3 4 5 6 7 8 9]
print(result.shape)  # (9,)

沿行方向的二维数组(axis=0)

import numpy as np
 
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
 
# 垂直堆叠(添加行)
result = np.concatenate([a, b], axis=0)
print(result)
# [[1 2]
#  [3 4]
#  [5 6]
#  [7 8]]
print(result.shape)  # (4, 2)

沿列方向的二维数组(axis=1)

import numpy as np
 
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
 
# 水平堆叠(添加列)
result = np.concatenate([a, b], axis=1)
print(result)
# [[1 2 5 6]
#  [3 4 7 8]]
print(result.shape)  # (2, 4)

Shape 要求

所有数组除了连接轴外必须具有相同的形状。

import numpy as np
 
a = np.ones((3, 4))    # 3 行,4 列
b = np.zeros((2, 4))   # 2 行,4 列
 
# 正确:不同的行数,相同的列数,axis=0
result = np.concatenate([a, b], axis=0)
print(result.shape)  # (5, 4)
 
# 错误:不同的列数
c = np.ones((3, 5))
# np.concatenate([a, c], axis=0)  # ValueError: dimensions don't match

np.vstack() -- 垂直堆叠

np.vstack() 垂直堆叠数组(沿轴 0)。等同于 np.concatenate(arrays, axis=0),但也能处理一维数组,将其视为单独的行。

import numpy as np
 
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
 
# vstack 将一维数组视为行
result = np.vstack([a, b])
print(result)
# [[1 2 3]
#  [4 5 6]]
print(result.shape)  # (2, 3)
 
# 对于二维数组
c = np.array([[1, 2], [3, 4]])
d = np.array([[5, 6]])
result = np.vstack([c, d])
print(result)
# [[1 2]
#  [3 4]
#  [5 6]]

np.hstack() -- 水平堆叠

np.hstack() 水平堆叠数组(二维沿轴 1,一维沿轴 0)。

import numpy as np
 
# 一维数组:像 np.concatenate 一样连接
a = np.array([1, 2, 3])
b = np.array([4, 5])
result = np.hstack([a, b])
print(result)  # [1 2 3 4 5]
 
# 二维数组:添加列
c = np.array([[1], [2], [3]])
d = np.array([[4], [5], [6]])
result = np.hstack([c, d])
print(result)
# [[1 4]
#  [2 5]
#  [3 6]]

np.stack() -- 创建新轴

concatenate 不同,stack 沿轴连接数组,将维度数增加 1。

import numpy as np
 
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
 
# 沿新的轴 0 堆叠(默认)
result = np.stack([a, b])
print(result)
# [[1 2 3]
#  [4 5 6]]
print(result.shape)  # (2, 3)
 
# 沿新的轴 1 堆叠
result = np.stack([a, b], axis=1)
print(result)
# [[1 4]
#  [2 5]
#  [3 6]]
print(result.shape)  # (3, 2)

np.stack() 要求所有输入数组具有相同的形状。

函数比较

函数创建新轴?一维输入处理
np.concatenate现有(默认 0)原样连接
np.vstack0(垂直)将一维视为行
np.hstack1(水平)连接一维数组
np.stack新轴是(+1 维度)创建新维度
np.column_stack1将一维视为列
np.row_stack0与 vstack 相同

实用示例

为机器学习组合特征

import numpy as np
 
# 来自不同来源的特征数组
ages = np.array([25, 30, 35, 40])
incomes = np.array([50000, 60000, 75000, 90000])
scores = np.array([720, 680, 750, 800])
 
# 按列堆叠以创建特征矩阵
X = np.column_stack([ages, incomes, scores])
print(X)
# [[   25 50000   720]
#  [   30 60000   680]
#  [   35 75000   750]
#  [   40 90000   800]]
print(X.shape)  # (4, 3)

批处理结果

import numpy as np
 
# 分批处理数据,合并结果
results = []
for batch_start in range(0, 100, 25):
    batch = np.random.randn(25, 10)  # 25 个样本,10 个特征
    processed = batch * 2 + 1  # 一些处理
    results.append(processed)
 
# 垂直合并所有批次
all_results = np.vstack(results)
print(all_results.shape)  # (100, 10)

图像处理 -- 合并通道

import numpy as np
 
height, width = 100, 100
 
# 分离的颜色通道
red = np.random.randint(0, 256, (height, width))
green = np.random.randint(0, 256, (height, width))
blue = np.random.randint(0, 256, (height, width))
 
# 合并为 RGB 图像
rgb_image = np.stack([red, green, blue], axis=2)
print(rgb_image.shape)  # (100, 100, 3)

可视化合并数据

连接来自不同来源的数组后,PyGWalker (opens in a new tab) 让你在 Jupyter 中交互式地探索合并后的数据集:

import pandas as pd
import pygwalker as pyg
 
# 将连接后的数组转换为 DataFrame
df = pd.DataFrame(X, columns=['age', 'income', 'score'])
walker = pyg.walk(df)

常见问题

np.concatenate 和 np.stack 有什么区别?

np.concatenate 沿现有轴连接数组而不改变维度数。np.stack 沿新轴连接数组,增加一个维度。例如,用 concatenate 堆叠两个 (3,) 数组得到 (6,),而 stack 得到 (2, 3)。

np.concatenate 中的 axis 是什么意思?

axis 参数指定沿哪个维度连接。axis=0 沿行连接(添加更多行),axis=1 沿列连接(添加更多列)。对于二维数组,axis=0 是垂直堆叠,axis=1 是水平堆叠。

什么时候应该使用 vstack、hstack 还是 concatenate?

使用 vstack 添加行(垂直堆叠),hstack 添加列(水平堆叠),当需要指定任意轴时使用 concatenatevstackhstack 是便捷函数,比 concatenate 更直观地处理一维数组。

为什么连接数组时会出现 ValueError?

所有数组除了连接轴外必须具有相同的形状。如果沿 axis=0 连接,所有数组必须具有相同的列数。连接前使用 array.shape 检查形状。

如何连接不同维度的数组?

首先将数组重塑为兼容的维度。使用 np.expand_dims(array, axis) 添加一个维度,或使用 array.reshape(new_shape)。例如,要将一维数组与二维数组进行 vstack,重塑一维数组:array.reshape(1, -1)

总结

NumPy 提供了完整的数组连接工具包:np.concatenate() 用于沿任意轴的通用连接,np.vstack()/np.hstack() 用于直观的垂直/水平堆叠,np.stack() 用于需要创建新维度的场景。记住 concatenate 沿现有轴连接而 stack 创建新轴。仔细匹配维度,在常见的行/列操作中使用 vstack/hstack 以获得最易读的代码。

📚