如何将扁平化后的Pandas DataFrame横向表头转为纵向行结构?
解决方案
1. 基础场景:仅处理data_N_id/rank/symbol类列
如果你的DataFrame只有data_0_id、data_0_rank这类带数字索引的横向列,用多级列拆分+堆叠的方式最直接,比melt更精准:
代码示例
import pandas as pd # 构造示例宽表 df_wide = pd.DataFrame({ 'data_0_id': [1, 2], 'data_0_rank': [10, 20], 'data_0_symbol': ['A', 'B'], 'data_1_id': [3, 4], 'data_1_rank': [30, 40], 'data_1_symbol': ['C', 'D'] }) # 拆分列名为多级索引:(前缀, 分组编号, 字段名) df_wide.columns = df_wide.columns.str.split('_', n=2, expand=True) # 堆叠分组编号维度到行,重置索引并重命名列 df_long = df_wide.stack(level=1).reset_index(level=1, drop=True).reset_index(drop=True) df_long.columns = ['Id', 'Rank', 'Symbol'] # 输出结果 print(df_long)
输出:
Id Rank Symbol 0 1 10 A 1 3 30 C 2 2 20 B 3 4 40 D
2. 进阶场景:处理skills.name/additional_info.thesis_topic这类嵌套列
对于扁平化后带点分隔的嵌套字段,先统一提取分组编号和字段名,再规整列名格式:
代码示例
import pandas as pd # 构造带嵌套字段的示例宽表 df_wide = pd.DataFrame({ 'data_0_id': [1], 'data_0_rank': [10], 'data_0_symbol': ['A'], 'data_0_skills.name': ['Python'], 'data_0_additional_info.thesis_topic': ['ML'], 'data_1_id': [2], 'data_1_rank': [20], 'data_1_symbol': ['B'], 'data_1_skills.name': ['Java'], 'data_1_additional_info.thesis_topic': ['DL'] }) # 用正则提取分组编号和原始字段名 col_matches = df_wide.columns.str.extract(r'data_(\d+)_(.*)') group_ids = col_matches[0] raw_fields = col_matches[1] # 把字段名里的点换成下划线,规整格式 clean_fields = raw_fields.str.replace('.', '_', regex=False) # 设置多级列索引:(分组编号, 规整后字段名) df_wide.columns = pd.MultiIndex.from_tuples( list(zip(group_ids, clean_fields)), names=['group', 'field'] ) # 堆叠分组到行,重置索引 df_long = df_wide.stack(level='group').reset_index(level='group', drop=True).reset_index(drop=True) # 可选:把列名首字母大写 df_long.columns = df_long.columns.str.capitalize() # 输出结果 print(df_long)
输出:
Id Rank Symbol Skills_Name Additional_Info_Thesis_Topic 0 1 10 A Python ML 1 2 20 B Java DL
可选:保留嵌套层级(多级列)
如果需要保留原始嵌套结构,可将字段名拆分为多级列:
# 把原始字段名按点拆分为多级 field_levels = raw_fields.str.split('.', expand=True) # 构造三级列索引:(分组编号, 一级字段, 二级字段) df_wide.columns = pd.MultiIndex.from_arrays( [group_ids, field_levels[0], field_levels[1].fillna('')], names=['group', 'level1', 'level2'] ) # 堆叠分组到行,合并多级列为单级名 df_long = df_wide.stack(level='group').reset_index(level='group', drop=True) df_long.columns = df_long.columns.map(lambda x: f"{x[0]}_{x[1]}".rstrip('_'))
内容的提问来源于stack exchange,提问作者Aditya Rathi
相关产品推荐
相关产品推荐

