如何让Pandas的resample函数在非24小时可整除的时间区间下与日期对齐?
如何让Pandas的resample函数在非24小时可整除的时间区间下与日期对齐?
我完全懂你遇到的困扰——用5小时这种没法整除24的区间重采样时,一开始还好好的,结果到第二天时段就跑偏了,完全不是你想要的固定整点窗口。其实这是因为Pandas默认的resample是连续滚动的时间窗口,24除以5没法得到整数,所以窗口会从起始时间一直累加,到第二天自然就偏移了;而像2h、4h这种能整除24的区间,刚好能把一天分成整数个窗口,所以每天都能对齐到整点。
想要实现你要的固定时段(00-05、05-10、10-15、15-20、20-次日00),咱们可以换个思路——给数据打时段标签,按固定时段分组聚合,而不是依赖默认的连续滚动窗口。下面给你两种实用的方法:
方法一:自定义时段分组(推荐,完全匹配需求)
这种方法直接根据数据的小时数,把每条数据归到对应的每日固定时段里,20点之后的数据直接关联到次日的时段标签,确保每天的窗口都对齐。
import pandas as pd # 假设你的原始数据是read,且索引是datetime类型 read['date'] = read.index.date read['hour'] = read.index.hour # 定义函数:给每条数据分配时段和对应的基准日期 def get_period_info(row): if 0 <= row['hour'] < 5: return (row['date'], '00:00-05:00') elif 5 <= row['hour'] < 10: return (row['date'], '05:00-10:00') elif 10 <= row['hour'] < 15: return (row['date'], '10:00-15:00') elif 15 <= row['hour'] < 20: return (row['date'], '15:00-20:00') else: # 20:00到次日00:00的时间段 return (row['date'] + pd.Timedelta(days=1), '20:00-00:00') # 生成分组键 read['period_key'] = read.apply(get_period_info, axis=1) # 按分组键聚合,用你需要的聚合规则 agg_rules = {'Open': 'first', 'High': 'max', 'Low': 'min', 'Close': 'last'} df = read.groupby('period_key').agg(agg_rules) # 调整索引格式,让结果更清晰 df.index = pd.MultiIndex.from_tuples(df.index, names=['Date', 'Period']) print(df)
这样处理后,你会得到完全对齐的每日时段:当天20点到次日0点的数据会被归到次日的20:00-00:00时段(如果你想把它归到当天的最后一个时段,只需要把函数里的日期改成row['date']就行)。
方法二:生成固定时段边界后重采样
如果你更习惯用resample的思路,可以先手动生成所有需要的固定时段边界,再把数据映射到对应的窗口里:
import pandas as pd # 确保原始数据索引是datetime类型,且无时区(避免时区干扰) read = read.tz_localize(None) # 生成所有每日时段的起始边界 start_date = read.index.min().floor('D') end_date = read.index.max().ceil('D') daily_dates = pd.date_range(start=start_date, end=end_date, freq='D') period_starts = [] for date in daily_dates: # 每天添加5个固定起始点 period_starts.extend([ date, date + pd.Timedelta(hours=5), date + pd.Timedelta(hours=10), date + pd.Timedelta(hours=15), date + pd.Timedelta(hours=20) ]) # 去重并排序边界 period_starts = sorted(list(set(period_starts))) # 把数据切割到对应的时段窗口 read['period_label'] = pd.cut( read.index, bins=period_starts, labels=[s.strftime('%Y-%m-%d %H:%M') for s in period_starts[:-1]] ) # 按时段标签聚合 agg_rules = {'Open': 'first', 'High': 'max', 'Low': 'min', 'Close': 'last'} df = read.groupby('period_label').agg(agg_rules) # 把标签转回datetime索引 df.index = pd.to_datetime(df.index) print(df)
这个方法会提前创建好所有你需要的固定时段窗口,再把数据“装”进去聚合,结果同样能完美对齐你要的每日时段。
总结一下:当重采样区间无法整除24小时时,默认的连续滚动窗口必然会偏移,所以咱们需要主动定义每日固定的时段边界,通过分组聚合来实现对齐需求,而不是依赖resample的默认行为。
备注:内容来源于stack exchange,提问作者x_crypto
相关产品推荐
相关产品推荐

