resample必须在DatetimeIndex或PeriodIndex上调用,因它依赖时间索引结构分组;若date列非时间类型,需先转为datetime再设为索引;重采样后须接聚合操作(如mean、sum、ohlc等),并注意closed和label参数对时间对齐的影响。

resample 为什么必须在 DatetimeIndex 或 PeriodIndex 上调用
resample 不是普通 DataFrame 方法,它依赖时间索引的内在结构做分组切片。如果 date 列只是普通 object 或 int 类型,直接 df.resample('M') 会报 TypeError: Only valid with DatetimeIndex, TimedeltaIndex or PeriodIndex。
必须先确保索引是时间类型:
- 用
df.set_index('date').asfreq('D')转索引(若 date 已是 datetime 类型) - 若 date 是字符串,先
pd.to_datetime(df['date']),再set_index - 避免用
df.index = pd.DatetimeIndex(df['date'])后还保留原列——冗余且易混淆
如何选对 resample 的 agg 函数:mean / sum / first / last / ohlc
重采样本质是“按新频率分组 + 聚合”,resample 后必须跟聚合操作,否则只返回 Resampler 对象,不计算结果。
常见选择逻辑:
- 数值型指标(如温度、股价)常用
.mean()或.sum();但注意:流量类数据(如日请求量)应.sum(),均值反而失真 - 想取每段起始/结束值,用
.first()或.last(),比.iloc[0]安全(空组不报错) - K线场景直接用
.ohlc(),自动返回open/high/low/close四列,无需手动指定 - 不能混用不同逻辑,比如
.agg({'price': 'mean', 'volume': 'sum'})是合法的,但.agg(['mean', 'sum'])会对所有列都套两个函数
closed 和 label 参数怎么配才不偏移一天
默认 resample('M') 表示“月频”,但 Python 把每月最后一天作为分组边界,且 closed='right'(右闭),导致 2023-01-01 至 2023-01-31 的数据被归入 2023-02-01 的桶里——结果看起来整体右移一个月。
修复方式取决于业务定义:
- 要“自然月”结果落在当月最后一天(如财务月报),设
closed='right', label='right' - 要结果落在当月第一天(如月初计划),改用
closed='left', label='left' - 更稳妥的是显式指定
offset,比如resample('MS')(Month Start)天然对齐每月 1 号,不用调参数
验证方法:打印 result.index,看时间戳是否符合预期位置。
resample 遇到缺失日期怎么办:asfreq vs fillna
resample 默认只对**已有数据**分组,不会补全空周期。比如原始数据缺 2023-03-15,用 'D' 重采样后,那天依然不存在。
补全空日期得靠后续操作:
-
.asfreq('D'):强制生成每日索引,缺失处填NaN,适合后续插值或过滤 -
.reindex(pd.date_range(...), fill_value=0):指定范围并填固定值,适合计数类数据 - 别在
resample前用fillna——它对空组无效;要在resample().agg(...)之后链式调用.fillna(0)
高频转低频(如分钟→小时)一般不补,但低频转高频(日→小时)必须明确补全策略,否则时间轴断裂。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











