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

如何基于df2的自定义起止日期对df1分ID进行时间序列重采样

问题描述

我有两个pandas DataFrame:

  • df1包含多组以不同ID标识的时间序列数据,字段包括Index、Timestamp、Data、ID
  • df2存储了每个ID对应的时间序列处理的开始、结束日期,字段包括End Date、Start Date、ID、Name等

我此前已经实现了所有ID统一使用2010-01-01到2010-01-11作为时间范围,按1分钟频率重采样的逻辑,实现代码如下:

start = '2010-01-01'
end = '2010-01-11'

def f(x):
    r = pd.date_range(start=start, end = end, freq='1min')
    return x.reindex(r, method='ffill').bfill()


df_sub = (df1
        .set_index('Timestamp')
        .groupby('ID', sort=False)['Data']
        .apply(f)
        .rename_axis(['ID','Timestamp'])
        .reset_index()
        )

但上述方案所有ID使用相同的起止时间,我希望改为调用df2中每个ID对应的自定义起止日期进行重采样:例如ID 1的处理时间范围为2010-11-23到2010-12-03,ID 26的处理时间范围为2010-03-28到2010-04-07,最终输出包含ID、Timestamp、Data三个字段的重采样结果。

测试数据构造

df1构造代码

from pandas import Timestamp
import pandas as pd

df1 = pd.DataFrame({'Index': {(2, 1): 2,
  (2, 6): 8,
  (2, 37): 47,
  (2, 81): 92,
  (2, 88): 101,
  (2, 132): 146,
  (2, 139): 155,
  (2, 436): 453,
  (2, 545): 564,
  (2, 816): 835,
  (10, 172): 188,
  (10, 450): 469,
  (10, 565): 584,
  (10, 830): 849,
  (10, 1000): 1019,
  (10, 271312): 271331,
  (10, 271313): 271332,
  (10, 271314): 271333,
  (10, 271315): 271334,
  (10, 271316): 271335,
  (120, 1614): 1633,
  (120, 1665): 1684,
  (120, 1666): 1685,
  (120, 1733): 1752,
  (120, 1734): 1753,
  (120, 1835): 1854,
  (120, 1836): 1855,
  (120, 1957): 1976,
  (120, 1958): 1977,
  (120, 2091): 2110},
 'Timestamp': {(2, 1): Timestamp('2014-03-04 13:16:44.310000'),
  (2, 6): Timestamp('2014-03-04 13:17:01.777000'),
  (2, 37): Timestamp('2014-04-17 11:59:57.470000'),
  (2, 81): Timestamp('2014-04-17 12:01:08.973000'),
  (2, 88): Timestamp('2014-04-17 12:05:55.153000'),
  (2, 132): Timestamp('2014-04-17 12:08:58.933000'),
  (2, 139): Timestamp('2014-04-17 12:35:58.290000'),
  (2, 436): Timestamp('2014-04-17 12:41:42.147000'),
  (2, 545): Timestamp('2014-04-17 12:46:14.450000'),
  (2, 816): Timestamp('2014-04-17 13:05:53.077000'),
  (10, 172): Timestamp('2014-04-17 12:35:58.633000'),
  (10, 450): Timestamp('2014-04-17 12:41:42.067000'),
  (10, 565): Timestamp('2014-04-17 12:46:14.747000'),
  (10, 830): Timestamp('2014-04-17 13:05:53.153000'),
  (10, 1000): Timestamp('2014-04-17 13:10:20.127000'),
  (10, 271312): Timestamp('2014-05-13 14:59:44.627000'),
  (10, 271313): Timestamp('2014-05-13 14:59:44.780000'),
  (10, 271314): Timestamp('2014-05-13 14:59:45.600000'),
  (10, 271315): Timestamp('2014-05-13 14:59:45.757000'),
  (10, 271316): Timestamp('2014-05-13 14:59:46.687000'),
  (120, 1614): Timestamp('2014-04-17 15:39:52.673000'),
  (120, 1665): Timestamp('2014-04-17 15:46:41.260000'),
  (120, 1666): Timestamp('2014-04-17 15:46:41.417000'),
  (120, 1733): Timestamp('2014-04-17 16:07:54.657000'),
  (120, 1734): Timestamp('2014-04-17 16:07:54.817000'),
  (120, 1835): Timestamp('2014-04-17 16:23:59.943000'),
  (120, 1836): Timestamp('2014-04-17 16:24:00.103000'),
  (120, 1957): Timestamp('2014-04-17 16:53:00.543000'),
  (120, 1958): Timestamp('2014-04-17 16:53:00.703000'),
  (120, 2091): Timestamp('2014-04-17 17:29:21.163000')},
 'Data': {(2, 1): 30.0,
  (2, 6): 30.0,
  (2, 37): 25.0,
  (2, 81): 25.0,
  (2, 88): 25.0,
  (2, 132): 25.0,
  (2, 139): 25.0,
  (2, 436): 25.0,
  (2, 545): 25.0,
  (2, 816): 25.0,
  (10, 172): 25.0,
  (10, 450): 25.0,
  (10, 565): 25.0,
  (10, 830): 25.0,
  (10, 1000): 25.0,
  (10, 271312): 25.0,
  (10, 271313): 27.5,
  (10, 271314): 27.5,
  (10, 271315): 30.5,
  (10, 271316): 30.5,
  (120, 1614): 31.0,
  (120, 1665): 30.5,
  (120, 1666): 30.0,
  (120, 1733): 29.5,
  (120, 1734): 29.0,
  (120, 1835): 28.5,
  (120, 1836): 28.0,
  (120, 1957): 27.5,
  (120, 1958): 27.0,
  (120, 2091): 26.5},
 'ID': {(2, 1): 2,
  (2, 6): 2,
  (2, 37): 2,
  (2, 81): 2,
  (2, 88): 2,
  (2, 132): 2,
  (2, 139): 2,
  (2, 436): 2,
  (2, 545): 2,
  (2, 816): 2,
  (10, 172): 10,
  (10, 450): 10,
  (10, 565): 10,
  (10, 830): 10,
  (10, 1000): 10,
  (10, 271312): 10,
  (10, 271313): 10,
  (10, 271314): 10,
  (10, 271315): 10,
  (10, 271316): 10,
  (120, 1614): 120,
  (120, 1665): 120,
  (120, 1666): 120,
  (120, 1733): 120,
  (120, 1734): 120,
  (120, 1835): 120,
  (120, 1836): 120,
  (120, 1957): 120,
  (120, 1958): 120,
  (120, 2091): 120}
  })

df2构造代码

df2 = pd.DataFrame({'ID': {8: 10, 9: 2, 116: 120},
 'Start Date': {8: Timestamp('2014-04-20 00:00:00'),
  9: Timestamp('2014-03-04 00:00:00'),
  116: Timestamp('2014-04-17 00:00:00')},
 'End Date': {8: Timestamp('2014-04-30 00:00:00'),
  9: Timestamp('2014-03-14 00:00:00'),
  116: Timestamp('2014-04-27 00:00:00')},
 'comment': {8: 'TBA', 9: 'TBA', 116: 'TBA'},
 'Name': {8: 'NN95', 9: 'AA01', 116: 'BB10'}})
实现方案

首先将df2转换为ID到起止日期的映射表,方便分组时快速查询对应时间范围,再修改重采样函数,根据当前分组的ID获取自定义的起止时间生成时间序列即可:

# 构造ID到起止日期的映射字典
id_date_map = df2.set_index('ID')[['Start Date', 'End Date']].to_dict('index')

def resample_by_id(x):
    # x.name即为当前分组的ID值
    id_cfg = id_date_map[x.name]
    start = id_cfg['Start Date']
    end = id_cfg['End Date']
    # 生成对应时间范围的1分钟频率序列
    r = pd.date_range(start=start, end=end, freq='1min')
    return x.reindex(r, method='ffill').bfill()

df_result = (df1
        .set_index('Timestamp')
        .groupby('ID', sort=False)['Data']
        .apply(resample_by_id)
        .rename_axis(['ID','Timestamp'])
        .reset_index()
        )

最终输出的df_result就包含了ID、Timestamp、Data三个字段,每个ID都按照df2中指定的时间范围完成了1分钟频率的重采样。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 22:54:06