如何重组时间序列DataFrame:提取指定行并构建间隔列结构
问题描述
现有如下时间序列DataFrame:
| min | Volume every minute |
|---|---|
| 1 | 0.2 |
| 2 | 0.3 |
| ... | ... |
| 252001 | 0.9 |
需要将其重组为新DataFrame,要求:
min列保留每第1441个值(即1、1441、2881…252001)- 生成三类列:
1_1、1_2…1_1440:以每组起始值(1、1441等)为起点,每分钟提取1440条数据3_1、3_2…3_1440:以每组起始值为起点,每3分钟提取1440条数据5_1、5_2…5_1440:以每组起始值为起点,每5分钟提取1440条数据
预期结构示例:
| min | 1_1 | ... | 1_1440 | 3_1 | ... | 3_1440 |
|---|---|---|---|---|---|---|
| 1 | 0.2 | ... | 0.8 | 0.2 | ... | 0.6 |
| 1441 | 0.5 | ... | 2880min对应值 | 0.5 | ... | 5458min对应值 |
| ... | ... | ... | ... | ... | ... | ... |
| 252001 | 0.9 | NaN | NaN | NaN | ... | NaN |
解决方案
核心思路是先给原始数据分组(每组对应新DataFrame的一行),然后对不同频率的数据进行重排,最后合并所有结果。
步骤1:给原始数据添加分组标识
计算每条数据所属的分组,分组起始点为1、1441、2881…,每组包含后续1440条数据(最后一组可能不足):
import pandas as pd # 假设原始DataFrame名为df df['group_id'] = (df['min'] - 1) // 1441
group_id为0对应起始min=1的组,1对应起始min=1441的组,以此类推。
步骤2:处理不同频率的数据
针对1分钟、3分钟、5分钟三种频率,分别提取每组内的数据并转成宽格式:
处理1分钟频率
直接按分组提取每组内的Volume every minute,生成1_1到1_1440的列:
# 生成组内的位置标识(1到1440) df['pos_1min'] = df.groupby('group_id').cumcount() + 1 # 只保留位置<=1440的行,避免最后一组超出范围 df_1min = df[df['pos_1min'] <= 1440] # 转成宽格式并添加前缀'1_' wide_1min = df_1min.pivot(index='group_id', columns='pos_1min', values='Volume every minute').add_prefix('1_')
处理3分钟频率
按每组起始点,每3分钟取一条数据,生成对应列:
# 计算每组内的相对min值,筛选每3分钟的点 df['rel_min'] = df['min'] - df.groupby('group_id')['min'].transform('first') df_3min = df[df['rel_min'] % 3 == 0] # 生成组内位置标识(1到1440) df_3min['pos_3min'] = df_3min.groupby('group_id').cumcount() + 1 df_3min = df_3min[df_3min['pos_3min'] <= 1440] # 转成宽格式并添加前缀'3_' wide_3min = df_3min.pivot(index='group_id', columns='pos_3min', values='Volume every minute').add_prefix('3_')
处理5分钟频率
逻辑与3分钟一致,调整筛选条件:
df_5min = df[df['rel_min'] % 5 == 0] df_5min['pos_5min'] = df_5min.groupby('group_id').cumcount() + 1 df_5min = df_5min[df_5min['pos_5min'] <= 1440] wide_5min = df_5min.pivot(index='group_id', columns='pos_5min', values='Volume every minute').add_prefix('5_')
步骤3:合并结果并添加min列
将三个宽格式DataFrame合并,补充对应的起始min值:
# 合并所有宽表 result = pd.concat([wide_1min, wide_3min, wide_5min], axis=1) # 添加起始min列:每个group_id对应的起始min为1 + group_id*1441 result['min'] = 1 + result.index * 1441 # 将min列移至最前面 result = result[['min'] + [col for col in result.columns if col != 'min']]
补充说明
- 最后一组(对应min=252001)如果数据不足1440条,对应列会自动填充
NaN,符合预期结构。 - 如果原始数据的min列存在缺失值,需要先补全连续序列:
df = df.set_index('min').reindex(range(1, 252002)).reset_index(),避免分组逻辑出错。
内容的提问来源于stack exchange,提问作者prem
相关产品推荐
相关产品推荐

