NumPy 2.x 完全指南【十五】合并数组

1. 合并数组

合并数组是指将多个数组按照特定规则组合成一个新数组的操作。

函数/方法描述
concatenate(arrays, axis)沿现有轴连接数组序列。
concat(arrays, axis)沿现有轴连接数组序列。
stack(arrays)沿新轴堆叠数组序列(新增一个维度)。
vstack(tup)垂直堆叠数组(按行方向)。
hstack(tup)水平堆叠数组(按列方向)。
block(arrays)从嵌套的块列表组装高维数组。
dstack(tup)深度方向堆叠数组(沿第三轴)。
column_stack(tup)将一维数组按列堆叠为二维数组。

1.1 concatenate

numpy.concatenate():将相同维度​的多个数组沿指定轴连接(维度需匹配),返回新数组。

numpy.concat()concatenate 的别名函数,两者功能完全一致(为了与 Pandas 等库的 API 命名风格保持一致)。

函数定义:

def concatenate(arrays, axis=None, out=None, *, dtype=None, casting=None)

参数说明:

  • arrays:参与连接的多个数组。所有数组在非拼接轴维度必须具有相同形状(默认第一个轴)。
  • axis:拼接操作轴向。整数,可选,默认为 0 ,若设为 None ,所有数组将在拼接前展平。
  • out:指定输出容器。可选,形状需与未指定 out 参数时的返回结果严格匹配。
  • dtype:数据类型。可选(自 1.20.0 版本新增), 指定输出数组数据类型,不可与 out 参数同时使用。
  • casting:控制类型转换规则。可选 {'no', 'equiv', 'safe', 'same_kind', 'unsafe'} ,默认 ‘same_kind’ 。

注意事项:

  • 当输入包含掩码数组(MaskedArray)时,本函数不保留掩码信息,建议改用 ma.concatenate

示例 1 ,连接两个二维数组,axis=0 表示在 0 轴(行)上进行连接操作:

a = np.array([[1, 2],
              [3, 4]])
b = np.array([[5, 6]])
c = np.concatenate((a, b), axis=0)
print(c)
# [[1 2]
#  [3 4]
#  [5 6]]

示例 2 ,当在某个轴进行连接操作时,其他的轴的形状必须一致,比如,两个二维数组在行方向进行连接时,它们的列数必须相同,否则会抛出异常:

a = np.array([[1, 2, 3],
              [4, 5, 6]])
b = np.array([[7, 8]])
c = np.concatenate((a, b), axis=0)
# ValueError: all the input array dimensions except for the concatenation axis must match exactly, but along dimension 1,
# the array at index 0 has size 3 and the array at index 1 has size 2

示例 3 ,当 axis=None 表示将所有数组展平为一维数组后进行连接:

a = np.array([[1, 2, 3],
              [7, 8, 9]])
b = np.array([[1, 2]])
c = np.concatenate((a, b), axis=None)
print(c)  # [1 2 3 7 8 9 1 2]

示例 4 ,output 参数可以指定一个预先分配好的数组来存储结果,这样可以在处理大数据时避免额外的内存分配,提高效率:

a = np.array([[1, 2], [3, 4]])  # shape:(2,2)
b = np.array([[5, 6]])  # shape: (1,2)
# 预分配输出内存
output = np.empty((3, 2))  # 预分配 3 行 2 列数组
np.concatenate((a, b), axis=0, out=output)
print(output)

对于不同类型的数组进行连接时,默认自动进行数据类型提升。示例 5 ,int32float64 类型进行连接时结果数组的数据类型提升为 float64

int_arr = np.array([1, 2], dtype=np.int32)
float_arr = np.array([3.0, 4.0], dtype=np.float64)

result = np.concatenate([int_arr, float_arr], axis=0)
print(result.dtype)  # float64

可以使用 dtypecasting 参数强制指定输出数组的数据类型,注意事项:

  • out 参数的冲突,不能同时指定 dtypeout ,因为 out 已经预定义了数据类型。
  • casting 参数控制数据类型转换的严格程度:
    • no:完全禁止类型转换。
    • equiv:仅允许字节序变化。
    • safe:仅允许无损转换,例如 int32 → float64
    • same_kind:允许同类别转换,例如 float32 → float64
    • unsafe:允许任意转换(包括截断)。

示例 6 ,将浮点类型转整数类型(小数部分会被截断):

forced_int = np.concatenate(
    [int_arr, float_arr],
    axis=0,
    dtype=np.int32,
    casting='unsafe'
)
print(forced_int.dtype)  # int32
print(forced_int)  # [1 2 3 4]

1.2 stack

numpy.stack():沿新轴堆叠数组,生成比输入数组高一个维度的新数组。

函数定义:

def stack(arrays, axis=0, out=None, *, dtype=None, casting="same_kind")

参数说明:

  • arrays:参与堆叠的多个数组。所有数组必须形状相同。
  • axis:新轴在结果中的位置索引,默认为 0
  • out:指定输出容器。需与输出形状精确匹配。
  • dtype:数据类型。 指定输出数组数据类型,不可与 out 参数同时使用。
  • casting:控制类型转换规则。可选 {'no', 'equiv', 'safe', 'same_kind', 'unsafe'} ,默认 ‘same_kind’ 。

堆叠规则:新轴位置决定堆叠方向,其他维度保持原对齐

当使用 np.stack([a, b], axis=k) 时:

  • 新建轴的位置:在结果的第 k 个维度插入新轴。
  • 堆叠方向:沿着这个新轴的方向,将 ab 的数据排列。
  • 其他维度对齐:原始数组的各个维度的索引关系完全保留,仅在 k 轴位置扩展。

假设两个形状相同的三维数组 ab,形状均为 (D, H, W),当 axis=0 时,表示在最外层新建轴,结果数组的形状为 (m, d, h, w),其中 m 输入数组的数量,这里 m = 2

索引映射规则:

  • res_axis0[0, d, h, w] = a[d, h, w]
  • res_axis0[1, d, h, w] = b[d, h, w]

axis=1 时,结果数组的形状为 (d, m, h, w),索引映射规则:

  • res_axis1[d, 0, h, w] = a[d, h, w]
  • res_axis1[d, 1, h, w] = b[d, h, w]

axis= -1 时,表示在最后一个维度上插入新轴,即(d, h, w, m,)

示例 1 ,两个一维数组执行 stack 会堆叠为二维数组:

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

# 沿新轴 0 堆叠(默认)
stacked_axis0 = np.stack([a, b])
print(stacked_axis0.shape)
# 形状: (2, 3)
print(stacked_axis0)
# [[1 2 3]
#  [4 5 6]]

# 沿新轴 1 堆叠
stacked_axis1 = np.stack([a, b], axis=1)
print(stacked_axis1.shape)
# 形状: (3, 2)
print(stacked_axis1)
# [[1 4]
#  [2 5]
#  [3 6]]

示例 2 ,形状不一致时会报错:

a = np.array([1, 2, 3]) # shape (3,)
b = np.array([4, 5, 6, 7]) # shape (4,)
# ValueError: all input arrays must have the same shape
stacked_axis0 = np.stack([a, b])

示例 3 ,多个轴方向堆叠二维数组:

x = np.array([[1, 2],
              [3, 4]])  # (2,2)
y = np.array([[5, 6],
              [7, 8]])  # (2,2)

# 沿 axis= 0 堆叠
stacked_axis0 = np.stack([x, y], axis=0)
print(stacked_axis0.shape)
# (2, 2, 2)
print(stacked_axis0)
# [[[1 2]
#   [3 4]]
#
#  [[5 6]
#   [7 8]]]

# 沿 axis = 1 堆叠
stacked_axis1 = np.stack([x, y], axis=1)
print(stacked_axis1.shape)
# (2, 2, 2)
print(stacked_axis1)  C 0 , [1], 0 = C
# 当 `axis = 1` 时,索引的映射关系为:
# res_axis1[h, 0, w] = a[h, w]
# res_axis1[h, 1, w] = bh, w]
# 结果输出:
# [[[1 2]
#   [5 6]]
#
#  [[3 4]
#   [7 8]]]


# 沿 axis = 2 堆叠
stacked_axis2 = np.stack([x, y], axis=2)
print(stacked_axis2.shape)
# (2, 2, 2)
print(stacked_axis2)
# [[[1 5]
#   [2 6]]
#
#  [[3 7]
#   [4 8]]]


# 沿 axis = -1 堆叠( -1 表示最后一个轴,也就是 2 轴)
stacked_axis_2 = np.stack([x, y], axis=-1)
print(stacked_axis_2.shape)
# (2, 2, 2)
print(stacked_axis_2)
# [[[1 5]
#   [2 6]]
#
#  [[3 7]
#   [4 8]]]

在计算机视觉领域的实际应用时,批量图像数据堆叠时一个常见的操作,将多张图像(H×W×C)合并为一个批次(N×H×W×C),用于深度学习输入:

# 单张图像形状 (224, 224, 3)
image1 = np.random.randint(0, 255, (224, 224, 3))  # 随机生成图像1
image2 = np.random.randint(0, 255, (224, 224, 3))  # 随机生成图像2

# 沿批次轴(axis=0)堆叠
batch_images = np.stack([image1, image2], axis=0)
print(batch_images.shape)  # 输出: (2, 224, 224, 3)

1.3 vstack

numpy.vstack(): 垂直(按行)堆叠数组。即保持原有形状,直接沿第 0 轴进行堆叠,等效于 np.concatenate(..., axis=0)

函数定义:

def vstack(tup, *, dtype=None, casting="same_kind")

参数说明:

  • tup:输入数组。所有数组除第一个轴外其他轴形状需一致。
  • dtype:数据类型。 指定输出数组数据类型,。
  • casting:控制类型转换规则。可选 {'no', 'equiv', 'safe', 'same_kind', 'unsafe'} ,默认 ‘same_kind’ 。

示例 1 ,一维数组会被重塑为 (1, 3),确保可堆叠后沿第一个轴堆叠:

a = np.array([1, 2, 3])  # shape (3,)
b = np.array([4, 5, 6])  # shape (3,)
result = np.vstack((a, b))
# 输出:
# [[1 2 3]
#  [4 5 6]]
# shape (2, 3)

示例 2 ,对于二维数组,除第一个轴(行方向)外,其他维度(列数)必须相同,否则会报错:

a = np.array([[1, 2, 3],
              [4, 5, 6]])  # shape (2,3)
b = np.array([[6, 7, 8, 9],
              [10, 11, 12, 13]])  # shape (2,4)
result_2d = np.vstack((a, b))
# ValueError: all the input array dimensions except for the concatenation axis must match exactly, but along dimension 1, the array at index 0 has size 3 and the array at index 1 has size 4

示例 3 ,两个形状为 (2,3) 的二维数组:

a = np.array([[1, 2, 3],
              [4, 5, 6]])  # shape (2,3)
b = np.array([[7, 8, 9],
              [10, 11, 12]])  # shape (2,3)
# 沿垂直方向堆叠
result_2d = np.vstack((a, b))
print(result_2d)
#  [[ 1  2  3]
#  [ 4  5  6]
#  [ 7  8  9]
#  [10 11 12]]

示例 4 ,两个形状为 (2,3,4) 的三维数组:

c = np.arange(24).reshape(2, 3, 4)  # 0~23,shape (2,3,4)
d = np.arange(24, 48).reshape(2, 3, 4)  # 24~47,shape (2,3,4)

# 沿垂直方向堆叠
result_3d = np.vstack((c, d))
print(result_3d) # (4, 3, 4)
# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
#
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]
#
#  [[24 25 26 27]
#   [28 29 30 31]
#   [32 33 34 35]]
#
#  [[36 37 38 39]
#   [40 41 42 43]
#   [44 45 46 47]]]

1.4 hstack

numpy.hstack(): 水平(按列)堆叠数组。即保持原有形状,直接沿第 1 轴进行堆叠,等效于 np.concatenate(..., axis=1)

函数定义:

def hstack(tup, *, dtype=None, casting="same_kind")

垂直堆叠(沿第 0 轴,行方向)
参数说明:

  • tup:输入数组。所有数组除第二个轴外其他轴形状需一致。
  • dtype:数据类型。 指定输出数组数据类型,。
  • casting:控制类型转换规则。可选 {'no', 'equiv', 'safe', 'same_kind', 'unsafe'} ,默认 ‘same_kind’ 。

示例 1 ,一维数组直接沿第一个轴拼接,生成更长的一维数组:

a = np.array([1, 2, 3])  # 形状 (3,)
b = np.array([4, 5, 6])  # 形状 (3,)
result = np.hstack((a, b))
print(result)  # 输出: [1 2 3 4 5 6]

示例 2 ,对于二维数组,沿第二个轴(列方向)拼接,生成二维数组:

a = np.array([[1], [2], [3]])  # 形状 (3, 1)
b = np.array([[4], [5], [6]])  # 形状 (3, 1)
result = np.hstack((a, b))
print(result)
# 输出:
# [[1 4]
#  [2 5]
#  [3 6]]

1.5 dstack

numpy.dstack(): 将多个数组沿第三个轴(深度方向)堆叠,生成三维数组。

函数定义:

def dstack(tup)

参数说明:

  • tup:输入数组。

注意事项:

  • 一维数组 (N,) 自动转换为形状 (1, N, 1)
  • 二维数组 (M, N) 自动转换为形状 (M, N, 1)
  • 在第三个轴(深度方向)上合并数组,最终形状为 (M, N, K),其中 K 是堆叠的数组数量。
  • 适用于最多三维的数据,更高维操作建议使用 np.concatenatenp.stack

示例 1 ,堆叠一维数组:

a = np.array([1, 2, 3])  # 形状 (3,)
b = np.array([2, 3, 4])  # 形状 (3,)
result = np.dstack((a, b))
print(result.shape)  # 输出: (1, 3, 2)
print(result)
# [[[1 2]
#   [2 3]
#   [3 4]]]

示例 2 ,堆叠二维数组:

a = np.array([[1], [2], [3]])  # 形状 (3, 1)
b = np.array([[2], [3], [4]])  # 形状 (3, 1)
result = np.dstack((a, b))
print(result.shape)  # 输出: (3, 1, 2)
print(result)
# [[[1 2]]
#  [[2 3]]
#  [[3 4]]]

1.6 column_stack

numpy.column_stack(): 将多个一维数组作为列组合成一个二维数组,或沿列方向(第二个轴)拼接二维数组。功能与 hstack 类似,但针对一维数组自动转换为列向量进行了优化。

函数定义:

def column_stack(tup)

注意事项:

  • 每个形状为 (N,) 的一维数组会被重塑为 (N, 1) 的列向量。
  • 允许一维和二维数组组合,但所有数组的行数(第一维)必须一致。

示例 1 ,堆叠两个一维数组:

a = np.array([1, 2, 3])    # 形状 (3,)
b = np.array([4, 5, 6])    # 形状 (3,)
result = np.column_stack((a, b))
print("结果:\n", result)
print("形状:", result.shape)

示例 2 ,混合一维和二维数组:

c = np.array([[7, 8], [9, 10], [11, 12]])  # 形状 (3, 2)
d = np.array([13, 14, 15])                 # 形状 (3,)
result = np.column_stack((c, d))
print("结果:\n", result)
print("形状:", result.shape)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨 禹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值