如何通用地将Pandas中多组关联列合并为单列?
Pandas多列重组为对象列表列的简洁通用实现
需求背景
现有如下结构的Pandas DataFrame:
n objects id x y Vx Vy id.1 x.1 ... Vx.40 Vy.40 ... 0 41 1 2 3 4 5 17 3 ... 5 6 ... 1 21 1 2 3 4 5 17 3 ... 0 0 ... 2 36 1 2 3 4 5 17 3 ... 0 0 ...
需要把每组id、x、y、Vx、Vy(包括带序号后缀的id.1、x.1等列)合并成单个列表列,最终得到这样的结构:
n objects object_0 object_1 object_40 ... 0 41 [1,2,3,4,5] [17,3,...] ... [...5,6] ... 1 21 [1,2,3,4,5] [17,3,...] ... [...0,0] ... 2 36 [1,2,3,4,5] [17,3,...] ... [...0,0] ...
原实现代码虽然能运行,但不够简洁通用,这里提供两种更优雅的实现方式:
方法一:列名拆分+分组聚合
通过拆分列名提取对象索引和属性名,再按对象索引分组聚合:
import pandas as pd # 排除不需要重组的固定列 non_obj_cols = ['n', 'objects'] obj_cols = df.columns.drop(non_obj_cols) # 拆分列名,获取属性名和对象索引;给无后缀的列补索引0 col_split = obj_cols.str.split('.', expand=True) col_split.columns = ['attr', 'obj_idx'] col_split['obj_idx'] = col_split['obj_idx'].fillna('0') # 遍历每个对象索引,合并对应属性列为列表 for idx in col_split['obj_idx'].unique(): # 筛选当前对象对应的属性列名 attrs = col_split[col_split['obj_idx'] == idx]['attr'].tolist() current_cols = [f"{a}.{idx}" if idx != '0' else a for a in attrs] # 生成新列并删除原列 df[f'object_{idx}'] = df[current_cols].values.tolist() df.drop(current_cols, axis=1, inplace=True)
方法二:melt+pivot_table重塑结构
通过转置DataFrame结构,再分组聚合得到目标格式:
import pandas as pd # 将宽表转长表,保留固定列 melted_df = df.melt(id_vars=['n', 'objects'], var_name='col_name', value_name='value') # 拆分列名,补全object_0的索引 melted_df[['attr', 'obj_idx']] = melted_df['col_name'].str.split('.', expand=True) melted_df['obj_idx'] = melted_df['obj_idx'].fillna('0') # 分组聚合:按n、objects、obj_idx把值拼成列表,再转宽表 result = melted_df.groupby(['n', 'objects', 'obj_idx'])['value'].agg(list).unstack() # 重命名列 result.columns = [f'object_{idx}' for idx in result.columns] # 重置索引恢复原结构 result = result.reset_index()
优势对比
- 通用性拉满:不需要提前知道属性名、对象数量,自动适配不同列名和结构
- 代码更简洁:利用Pandas原生函数,避免循环硬编码,逻辑更清晰
- 鲁棒性更强:自动处理无后缀的
object_0列,无需额外判断
内容的提问来源于stack exchange,提问作者Bozhidar Dimitrov
相关产品推荐
相关产品推荐

