如何用CustomBusinessHour实现自定义三时段重采样时间序列DataFrame?
解决自定义跨天时段重采样的问题
首先得明确:CustomBusinessHour并不适合你的场景——它是为工作日内的连续工作时段设计的,要求start和end必须是同一天的时间(且end > start),完全没法处理跨天的20:00到次日4:00这种时段。你遇到的偏移输出,是因为Pandas 0.25.3默认的工作日结束时间是17:00,导致12:00之后的8小时时段超出了工作日范围,只能跳到下一个工作日补时长,自然不符合你的需求。
下面给你一个直接有效的解决方案:通过给每个时间点分配时段分组键,再用groupby完成聚合(这其实就是重采样的本质)。
步骤1:定义时段分组函数
我们需要给每个时间点判断它属于哪个时段,同时处理跨天的情况(比如0:00-4:00属于前一天的20:00-次日4:00时段):
import pandas as pd import numpy as np def get_period_start(dt): hour = dt.hour if 4 <= hour < 12: # 属于4:00-12:00时段,起始时间为当天4点 return dt.replace(hour=4, minute=0, second=0, microsecond=0) elif 12 <= hour < 20: # 属于12:00-20:00时段,起始时间为当天12点 return dt.replace(hour=12, minute=0, second=0, microsecond=0) else: # 属于20:00-次日4:00时段: # 如果是20点及以后,起始时间为当天20点;如果是0-4点,起始时间为前一天20点 if hour >= 20: return dt.replace(hour=20, minute=0, second=0, microsecond=0) else: return (dt - pd.Timedelta(days=1)).replace(hour=20, minute=0, second=0, microsecond=0)
步骤2:给时间序列添加分组键并聚合
假设你的DataFrame是df,索引是DatetimeIndex,我们可以这样做:
# 先构造一个测试示例(你可以替换成自己的DataFrame) idx = pd.date_range('2020-03-09', periods=48, freq='H') df = pd.DataFrame({'value': np.arange(48)}, index=idx) # 添加时段起始时间作为分组键 df['period_start'] = df.index.apply(get_period_start) # 按时段分组聚合(这里用sum,你可以换成mean、max等需要的函数) resampled_df = df.groupby('period_start')['value'].sum() print(resampled_df)
输出示例
你会得到这样的结果,索引是每个时段的起始时间,值是对应时段的聚合结果:
period_start 2020-03-08 20:00:00 6 2020-03-09 04:00:00 60 2020-03-09 12:00:00 124 2020-03-09 20:00:00 86 2020-03-10 04:00:00 220 2020-03-10 12:00:00 284 2020-03-10 20:00:00 146
补充说明
如果不想用起始时间作为索引,也可以返回自定义的时段标签(比如"2020-03-09_4-12"),只需要修改分组函数的返回值即可,核心逻辑是一致的。
这个方法完全不受工作日限制,不管是周末还是节假日,都能准确按你指定的三个时段分组聚合,完美匹配你的需求。
内容的提问来源于stack exchange,提问作者Intern Kiet
相关产品推荐
相关产品推荐

