如何将含复合列名的Pandas宽表重塑为长表并保留时间戳索引
将Pandas宽格式DataFrame重塑为长格式
问题背景
给定如下宽格式DataFrame,列名以测量属性_被测对象的规则命名,需要将其转换为长格式,保留原时间戳索引,生成包含bacterium(被测对象)、min_area、size字段的目标结果:
原DataFrame代码
import pandas as pd df = pd.DataFrame( { "size_Ent": { pd.Timestamp("2021-01-01 00:00:00"): 600, pd.Timestamp("2021-01-02 00:00:00"): 930, }, "size_Baci": { pd.Timestamp("2021-01-01 00:00:00"): 700, pd.Timestamp("2021-01-02 00:00:00"): 460, }, "min_area_Ent": { pd.Timestamp("2021-01-01 00:00:00"): 1240, pd.Timestamp("2021-01-02 00:00:00"): 1503, }, "min_area_Baci": { pd.Timestamp("2021-01-01 00:00:00"): 1285, pd.Timestamp("2021-01-02 00:00:00"): 953, }, } )
原数据展示
size_Ent size_Baci min_area_Ent min_area_Baci 2021-01-01 600 700 1240 1285 2021-01-02 930 460 1503 953
期望结果
bacterium min_area size 2021-01-01 Baci 1285 700 2021-01-01 Ent 1240 600 2021-01-02 Baci 953 460 2021-01-02 Ent 1503 930
解决方案
方法1:使用pd.wide_to_long(推荐)
pd.wide_to_long是Pandas专为这类带分隔符的宽格式转长格式场景设计的工具,操作简洁高效:
# 将时间戳索引转为普通列,适配wide_to_long的参数要求 df_reset = df.reset_index().rename(columns={'index': 'date'}) # 执行格式转换 result = pd.wide_to_long( df_reset, stubnames=['size', 'min_area'], # 指定测量属性的前缀 i='date', # 作为标识行的列(原时间戳) j='bacterium', # 新生成的被测对象列名 sep='_', # 列名的分隔符 suffix='\\w+' # 匹配被测对象名称的正则规则 ).reset_index().set_index('date').sort_index(ascending=True, kind='mergesort') # 调整列顺序匹配期望结果 result = result[['bacterium', 'min_area', 'size']]
运行后即可得到目标格式的DataFrame。
方法2:使用melt+列名拆分
如果不想使用wide_to_long,也可以通过melt转置结合字符串拆分实现:
# 将宽格式转为长格式,保留时间戳索引 melted = df.melt(ignore_index=False, var_name='attr_bact', value_name='value') # 拆分合并的列名为测量属性和被测对象 melted[['attribute', 'bacterium']] = melted['attr_bact'].str.split('_', expand=True) # 重新透视回目标格式 result = melted.pivot_table( index=[melted.index, 'bacterium'], columns='attribute', values='value' ).reset_index(level=1).sort_index(ascending=True, kind='mergesort')
该方法同样能得到符合要求的结果,仅步骤相对繁琐。
内容的提问来源于stack exchange,提问作者Data_interested
相关产品推荐
相关产品推荐

