如何使用Pandas将多年度宽格式DataFrame转换为长格式?
问题描述
现有如下结构的DataFrame:
{ 'year1_ID': ['Id1', 'Id2'], 'year1_Name':['Name1', 'Name2'], 'year1_Info': ['Info1','Info2'], 'year1_AddInfo':['AddInfo1','AddInfo2'], 'year2_ID': ['Id3', 'Id4'], 'year2_Name':['Name3', 'Name4'], 'year2_Info': ['Info3','Info4'], 'year2_AddInfo':['AddInfo3','AddInfo4'], 'year3_ID': ['Id5', 'Id6'], 'year3_Name':['Name5', 'Name6'], 'year3_Info': ['Info5','Info6'], 'year3_AddInfo':['AddInfo5','AddInfo6'] }
表格形式如下:
year1_ID year1_Name year1_Info year1_AddInfo year2_ID year2_Name year2_Info year2_AddInfo year3_ID year3_Name year3_Info year3_AddInfo Id1 Name1 Info1 AddInfo1 Id3 Name3 Info3 AddInfo3 Id5 Name5 Info5 AddInfo5 Id2 Name2 Info2 AddInfo2 Id4 Name4 Info4 AddInfo4 Id6 Name6 Info6 AddInfo6
其中ID、Name、Info、AddInfo是跨年度重复的属性,需要将其转换为如下长表格式:
Year ID Name Info AddInfo year1 Id1 Name1 Info1 AddInfo1 year1 Id2 Name2 Info2 AddInfo2 year2 Id3 Name3 Info3 AddInfo3 year2 Id4 Name4 Info4 AddInfo4 year3 Id5 Name5 Info5 AddInfo5 year3 Id6 Name6 Info6 AddInfo6
尝试过pd.melt()和pd.stack()未得到预期结果,寻求正确实现方案。
解决方案
使用Pandas的pd.wide_to_long()方法可以直接处理这种带前缀的宽表转长表需求,这是专门为这类场景设计的工具,比melt或stack更简洁高效。
代码实现
import pandas as pd # 构造示例DataFrame(替换为你的实际数据) df = pd.DataFrame({ 'year1_ID': ['Id1', 'Id2'], 'year1_Name':['Name1', 'Name2'], 'year1_Info': ['Info1','Info2'], 'year1_AddInfo':['AddInfo1','AddInfo2'], 'year2_ID': ['Id3', 'Id4'], 'year2_Name':['Name3', 'Name4'], 'year2_Info': ['Info3','Info4'], 'year2_AddInfo':['AddInfo3','AddInfo4'], 'year3_ID': ['Id5', 'Id6'], 'year3_Name':['Name5', 'Name6'], 'year3_Info': ['Info5','Info6'], 'year3_AddInfo':['AddInfo5','AddInfo6'] }) # 执行宽表转长表 result = pd.wide_to_long( df, stubnames=['ID', 'Name', 'Info', 'AddInfo'], # 指定重复的属性名 i=df.index, # 以原始行索引作为分组标识,确保每行数据对应转换 j='Year', # 提取出的年份列名 sep='_', # 列名中前缀与属性的分隔符 suffix='.*' # 匹配年份部分的正则,这里匹配任意字符 ).reset_index(drop=True) # 调整列顺序,让Year列排在首位 result = result[['Year', 'ID', 'Name', 'Info', 'AddInfo']] print(result)
代码说明
stubnames:指定所有列中重复的属性名称(即去掉年份前缀后的部分)。i:设置分组依据,这里用原始DataFrame的行索引,保证每一行的多年度数据能正确拆分。j:定义提取出的年份列的名称。sep:指定列名中年份与属性的分隔符(这里是下划线_)。suffix:用正则匹配年份部分,.*表示匹配任意字符,适配不同格式的年份命名。
运行后即可得到目标格式的长表。
内容的提问来源于stack exchange,提问作者user11666514
相关产品推荐
相关产品推荐

