如何拼接不同形状的多维NumPy数组(填充缺失值)
拼接不同形状的多维数组并填充缺失值
问题描述
我有一个包含不同形状2D数组的列表lst,需要将它们拼接成形状为(len(lst), maxx, maxy)的3D数组。其中maxx是所有数组.shape[0]的最大值,maxy是所有数组.shape[1]的最大值。形状小于(maxx, maxy)的数组从左上角开始填充,缺失位置用指定值(如0或np.nan)补充。
示例
import numpy as np lst = [np.array([[1, 2], [3, 4]]), np.array([[1, 2, 3], [4, 5, 6]]), np.array([[1, 2], [3, 4], [5, 6]])] # maxx == 3,maxy == 3 result = np.array([[[1, 2, 0], [3, 4, 0], [0, 0, 0]], [[1, 2, 3], [4, 5, 6], [0, 0, 0]], [[1, 2, 0], [3, 4, 0], [5, 6, 0]]])
注意事项
np.concatenate要求所有输入数组形状完全匹配,无法直接用于此场景- 此问题是1D数组同类拼接填充问题的扩展
子问题:列数统一的特殊场景
可假设所有数组的.shape[1]等于maxy,示例如下:
lst = [np.array([[1, 2, 3], [4, 5, 6]]), np.array([[1, 2, 3]]), np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])]
附加难题:高维扩展
能否将方法扩展到更高维度?例如把3D数组拼接为4D数组,所有3D数组从同一角落开始填充,形状不足的部分用指定值补全。
解决方案
一、高效向量化实现(推荐处理大规模数据)
直接创建最终形状的数组,通过向量化切片填充,避免低效循环,适合数千个大数组的场景。
步骤如下:
- 计算所有数组的最大维度:
import numpy as np lst = [np.array([[1,2],[3,4]]), np.array([[1,2,3],[4,5,6]]), np.array([[1,2],[3,4],[5,6]])] max_dims = np.max([arr.shape for arr in lst], axis=0) maxx, maxy = max_dims result_shape = (len(lst), maxx, maxy)
- 初始化结果数组,填充指定默认值:
fill_value = 0 # 可替换为np.nan result = np.full(result_shape, fill_value, dtype=lst[0].dtype)
- 批量填充每个子数组:
for i, arr in enumerate(lst): x, y = arr.shape result[i, :x, :y] = arr
此方式的核心是利用numpy底层的向量化切片赋值,仅外层遍历列表,性能远高于逐元素操作。
二、Pandas方法(适合快速原型开发)
将每个2D数组转为DataFrame,自动补全行/列后拼接,代码简洁但性能略逊于纯numpy:
import pandas as pd fill_value = 0 # 每个数组转为DataFrame并补全到最大维度 dfs = [pd.DataFrame(arr).reindex(index=range(maxx), columns=range(maxy), fill_value=fill_value) for arr in lst] # 拼接为3D数组 result_pd = np.stack(dfs, axis=0)
注意:大规模数据场景下,DataFrame的额外开销会导致性能下降,优先选择纯numpy方案。
三、SciPy相关工具
SciPy中没有专门直接处理此类问题的函数。若填充值为0且数组稀疏,可借助scipy.sparse模块将稀疏数组转为稠密数组后拼接,但普通场景下必要性不大,纯numpy方案更高效。
四、高维扩展实现
上述向量化逻辑可无缝扩展到任意维度,核心步骤一致:
- 计算输入数组各维度的最大值
- 初始化对应形状的结果数组
- 遍历数组,用切片写入对应位置
以3D数组拼接为4D数组为例:
# 示例3D数组列表 lst_3d = [np.random.rand(2,3,4), np.random.rand(3,2,5), np.random.rand(1,1,1)] # 计算各维度最大值 max_dims_3d = np.max([arr.shape for arr in lst_3d], axis=0) # 结果形状:(数组数量, max_dim1, max_dim2, max_dim3) result_shape_4d = (len(lst_3d), *max_dims_3d) # 初始化结果数组 result_4d = np.full(result_shape_4d, fill_value=0, dtype=lst_3d[0].dtype) # 填充每个3D数组 for i, arr in enumerate(lst_3d): slices = tuple([i] + [slice(0, s) for s in arr.shape]) result_4d[slices] = arr
内容的提问来源于stack exchange,提问作者Vladimir Fokow
相关产品推荐
相关产品推荐

