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 ,int32
和 float64
类型进行连接时结果数组的数据类型提升为 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
可以使用 dtype
和 casting
参数强制指定输出数组的数据类型,注意事项:
- 与
out
参数的冲突,不能同时指定dtype
和out
,因为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
个维度插入新轴。 - 堆叠方向:沿着这个新轴的方向,将
a
和b
的数据排列。 - 其他维度对齐:原始数组的各个维度的索引关系完全保留,仅在
k
轴位置扩展。
假设两个形状相同的三维数组 a
和 b
,形状均为 (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.concatenate
或np.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)