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

如何用Python的Pandas包将时间序列数据从宽格式转长格式?

宽格式时间序列转长格式并生成Time变量

我有一组宽格式的时间序列数据,需要转换为长格式来做数据分析和数据集合并。数据中A_0代表指标A在时间0的取值,A_15代表时间15的取值,以此类推。

原始数据代码:

import pandas as pd

df_wide = pd.DataFrame({'Subject': ['AA', 'BB', 'CC', 'DD'],
               'A_0': [1, 2, 3, 4],
               'A_15': [2, 3, 4, 5],
               'A_30': [3, 4, 5, 6],
               'B_0': [1, 2, 3, 4],
               'B_15': [2, 3, 4, 5],
               'B_30': [3, 4, 5, 6],
               'C_0': [1, 2, 3, 4],
               'C_15': [2, 3, 4, 5],
               'C_30': [3, 4, 5, 6]
              }
             )

原始数据展示:

Subject  A_0  A_15  A_30  B_0  B_15  B_30  C_0  C_15  C_30
0      AA    1     2     3    1     2     3    1     2     3
1      BB    2     3     4    2     3     4    2     3     4
2      CC    3     4     5    3     4     5    3     4     5
3      DD    4     5     6    4     5     6    4     5     6

期望转换后的长格式(带Time变量):
目标数据代码:

df_long = pd.DataFrame({'Subject': ['AA', 'AA', 'AA', 'BB', 'BB', 'BB', 'CC', 'CC', 'CC', 'DD', 'DD', 'DD'],
                    'Time': [0, 15, 30, 0, 15, 30, 0, 15, 30, 0, 15, 30],
                    'A': [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6],
                    'B': [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6],
                    'C': [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6],       
                    })

目标数据展示:

Subject  Time  A  B  C
0       AA     0  1  1  1
1       AA    15  2  2  2
2       AA    30  3  3  3
3       BB     0  2  2  2
4       BB    15  3  3  3
5       BB    30  4  4  4
6       CC     0  3  3  3
7       CC    15  4  4  4
8       CC    30  5  5  5
9       DD     0  4  4  4
10      DD    15  5  5  5
11      DD    30  6  6  6

我试过pivot和melt但没搞明白怎么生成Time变量,求帮助。


解决方案

可以通过**melt+列拆分+pivot**三步完成转换,逻辑清晰易理解:

步骤1:用melt将宽格式转为中间长格式

先把所有指标列(A_0、B_15这类)转为行,保留Subject作为标识列:

# melt转换,id_vars是保留的列,value_vars是要转成行的列
df_melt = df_wide.melt(id_vars='Subject', var_name='Metric_Time', value_name='Value')

转换后df_melt的结构:

Subject Metric_Time  Value
0       AA         A_0      1
1       BB         A_0      2
2       CC         A_0      3
3       DD         A_0      4
4       AA        A_15      2
...

步骤2:拆分Metric_Time列为Metric和Time

把Metric_Time列按下划线_拆分,得到指标名(A/B/C)和时间值(0/15/30):

# 拆分列,expand=True表示拆成两列
df_melt[['Metric', 'Time']] = df_melt['Metric_Time'].str.split('_', expand=True)
# 把Time转为数值类型
df_melt['Time'] = df_melt['Time'].astype(int)

拆分后df_melt新增了Metric和Time列:

Subject Metric_Time  Value Metric  Time
0       AA         A_0      1      A     0
1       BB         A_0      2      A     0
2       CC         A_0      3      A     0
3       DD         A_0      4      A     0
4       AA        A_15      2      A    15
...

步骤3:用pivot转回宽格式(按Subject和Time分组)

现在把Metric列转成列名,Value作为对应值,得到最终的长格式:

df_long = df_melt.pivot(index=['Subject', 'Time'], columns='Metric', values='Value').reset_index()
# 去掉列名的索引名称
df_long.columns.name = None

最终输出的df_long就和你期望的格式完全一致了。

一步到位的简化代码

如果想把步骤合并成一行,可以这样写:

df_long = (df_wide.melt(id_vars='Subject', var_name='Metric_Time', value_name='Value')
           .assign(**{'Metric': lambda x: x['Metric_Time'].str.split('_').str[0],
                      'Time': lambda x: x['Metric_Time'].str.split('_').str[1].astype(int)})
           .pivot(index=['Subject', 'Time'], columns='Metric', values='Value')
           .reset_index()
           .rename_axis(None, axis=1))

内容的提问来源于stack exchange,提问作者CB_datarookie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 17:35:17