
本文介绍如何将二维 numpy 数组 a(形状为 (n, m))与一维数组 b(长度为 n)按行一一配对,生成嵌套列表 c,其中每个元素为 [a[i], b[i]],并对比多种实现方式的性能与适用性。
本文介绍如何将二维 numpy 数组 a(形状为 (n, m))与一维数组 b(长度为 n)按行一一配对,生成嵌套列表 c,其中每个元素为 [a[i], b[i]],并对比多种实现方式的性能与适用性。
在 NumPy 数据处理中,常需将结构化数据(如样本特征矩阵)与其对应标签或权重向量进行配对。例如:
-
A是形状为(n, m)的二维数组,代表n个样本、每个含m维特征; -
B是长度为n的一维数组,代表每个样本的标量标签(如类别、得分、时间戳等); - 目标是构造列表
C,使得C[i] == [A[i].tolist(), B[i]],即每项为「特征行 + 标量」的二元嵌套列表。
✅ 推荐方法:list(map(list, zip(A, B)))
这是最简洁、可读性强且实际性能优异的纯 Python 方案:
import numpy as np
A = np.array([[1, 3, 6],
[2, 2, 5]])
B = np.array([1, 6])
C = list(map(list, zip(A, B)))
print(C)
# 输出: [[[1, 3, 6], 1], [[2, 2, 5], 6]]
原理说明:
-
zip(A, B)将A的每一行(np.ndarray视为可迭代对象,逐行迭代)与B对应元素配对,生成元组迭代器; -
map(list, ...)将每个(row_array, scalar)元组转为[row_list, scalar]列表; - 外层
list()收集全部结果为 Python 列表。
⚠️ 注意:
A[i]是np.ndarray,zip会自动解包其行;若需确保A[i]转为普通 Python 列表(而非数组),map(list, ...)已隐式完成该转换。
? 其他方案对比(不推荐但需了解)
| 方法 | 代码示例 | 说明 | 缺陷 |
|---|---|---|---|
| 列表推导式(更直观) | [ [a.tolist(), b] for a, b in zip(A, B) ] |
显式调用 tolist(),语义清晰 |
略微冗余,性能与 map(list, zip(...)) 基本持平 |
| NumPy 向量化拼接(❌错误方向) | np.column_stack([A, B[:, None]]) |
试图横向拼接 → 形状不兼容(A 是 2D,B 是 1D),且结果是扁平化数组,非嵌套结构 |
完全偏离目标格式,不可用 |
np.stack + np.expand_dims(❌过度复杂) |
np.stack([A, B[:, None]], axis=-1) |
生成高维张量,非所需嵌套列表结构 | 类型/形状均不符,需额外转换,得不偿失 |
✅ 最佳实践建议
-
优先使用
list(map(list, zip(A, B))):零依赖、无副作用、内存友好(惰性迭代)、在n 时速度极佳; - 若
A和B极大(百万级样本)且后续需继续 NumPy 运算,考虑不立即转为嵌套列表,改用结构化数组(np.dtype)或字典映射({i: (A[i], B[i]) for i in range(len(B))})以延迟序列化开销; - 避免
for循环手动构建(可读性差、Python 层面慢); - 所有方案均要求
len(A) == len(B),建议前置校验:assert len(A) == len(B), "Length mismatch between A and B"。
综上,list(map(list, zip(A, B))) 是兼顾简洁性、可读性与运行效率的最优解,适用于绝大多数数据配对场景。











