You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将含复合列名的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 02:05:23