pandas DatetimeIndex下滚动idxmax计算与最大值标记方法
问题原因
偏移本质是rolling参数用法错误:
- 传整数
window=60时,pandas按60行观测值划分窗口,必须凑够60行数据才会返回计算结果,前59行全部返回空值,视觉上就会出现整段曲线延迟60分钟的效果。 - 整数窗口完全不识别DatetimeIndex的时间语义,哪怕数据是固定1分钟采样,一旦存在缺行、时间点不连续的情况,窗口实际覆盖的时间跨度会完全不符合预期。
修正方案
直接给rolling传入时间偏移字符串作为窗口参数,pandas会自动适配DatetimeIndex按时间跨度划分窗口,不需要新增数值索引列,不需要手写循环遍历滑窗做计算,底层是C优化实现,大数据量下性能和整数窗口完全一致。
修正后的可运行代码:
import numpy as np import pandas as pd import matplotlib.pyplot as plt np.random.seed(0) dtidx = pd.date_range(start='6/1/2022', end='6/2/2022', freq='min') df = pd.DataFrame( np.cumsum(np.random.randn(len(dtidx))), index=dtidx, columns=['value'] ) ax = df.plot(figsize=(20, 4), label='原始序列') # 核心修改:窗口用时间偏移'60min'替代整数60 window = '60min' roll_max = df.rolling(window).max() roll_max.plot(ax=ax, label='60分钟滑动窗口最大值') # 计算每个窗口最大值对应的时间点 roll_max_time = df.rolling(window).apply(lambda x: x.idxmax()) # 标记最大值点,每小时标一个避免点过密影响观感 for ts in roll_max_time.dropna().iloc[::60, 0]: ax.scatter(ts, df.loc[ts, 'value'], c='red', s=60, zorder=6) ax.legend() plt.show()
补充说明
- 时间窗口默认采用
closed='right'规则,窗口区间为(当前时间-60分钟, 当前时间],从第一个时间点开始就有计算结果,不会出现整数窗口前59个空值导致的偏移问题。 - 如果需要调整窗口对齐方式,可修改
closed(控制窗口端点是否包含)、center(设置为True时窗口以当前时间点为中心)参数适配需求。 - 该写法对非固定采样频率、存在缺失时间点的DatetimeIndex数据集同样有效,窗口时间跨度始终准确。
内容的提问来源于stack exchange,提问作者Saeed
相关产品推荐
相关产品推荐

