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

如何将单索引Pandas DataFrame重塑为适配时间序列的多级索引?

问题:将单索引DataFrame转换为时间序列多级索引结构

现有如下单索引Pandas DataFrame(形状为(22, 5)),包含id、V1至V4列:

import pandas as pd

sample_dframe = pd.DataFrame.from_dict(
    {
        "id": [123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 456, 456, 456, 456, 456, 456, 456, 456, 456, 456, 456, 456],
        "V1": [2552, 813, 496, 401, 4078, 952, 7279, 544, 450,548, 433,4696, 244,9735, 4263,642, 255,2813, 496,401, 4078952, 7279544],
        "V2": [3434, 133, 424, 491, 8217, 915, 7179, 5414, 450, 548, 433, 4696, 244, 9735, 4263, 642, 255, 2813, 496, 401, 4952, 4453],
        "V3": [382,161, 7237, 7503, 561, 6801, 1072, 9660, 62107, 6233, 5403, 3745, 8613, 6302, 557, 4256, 9874, 3013, 9352, 4522, 3232, 58830],
        "V4": [32628, 4471, 4781, 1497, 45104, 8657, 81074, 1091, 370835, 2058, 4447, 7376, 302237, 6833, 48348, 3545, 4263,642, 255,2813, 4088920, 6323521]
    }
)

需求:按id分组,每个id对应的V1至V4列各取5个时间步的数据,最终得到形状为(2, 4, 5)的多级索引DataFrame(对应2个唯一id值)。


解决方案

可以通过分组截取+索引重塑实现目标,具体代码如下:

# 1. 按id分组,每个分组仅保留前5行数据(对应5个时间步)
grouped = sample_dframe.groupby('id').head(5)

# 2. 为每个分组内的行生成时间步索引(从0到4)
grouped['time_step'] = grouped.groupby('id').cumcount()

# 3. 设置多级索引并重塑结构,让特征列和时间步成为列的层级
result = grouped.set_index(['id', 'time_step']).unstack('time_step')
# 调整列的层级顺序,让特征列(V1-V4)作为第一层级
result = result.swaplevel(axis=1).sort_index(axis=1)

# 查看结果:多级索引DataFrame,列层级为[特征列, 时间步]
print(result.shape)  # 输出 (2, 20),对应4个特征 × 5个时间步的展开列数

# 若需要转为(2,4,5)的三维数组格式
result_3d = result.values.reshape(2, 4, 5)
print(result_3d.shape)  # 输出 (2,4,5)

代码说明:

  • groupby('id').head(5):精准截取每个id对应的前5条数据,满足时间步数量要求。
  • cumcount():为每个分组内的行生成连续的时间步标识,避免原索引混乱。
  • set_index + unstack + swaplevel:将时间步转换为列的层级,并调整层级顺序,让特征列作为第一层级,更贴合时间序列的结构逻辑。
  • 最终的result是保留Pandas多级索引结构的DataFrame,若需要纯三维数组,通过reshape即可快速转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 00:05:46