正确补全时间序列需先用asfreq()或reindex()构造完整DatetimeIndex,再用interpolate(method='time')按真实时间差插值,并配合limit_area='inside'和limit参数控制插值范围。

缺失时间点直接用 resample() 会丢数据
很多人一上来就用 resample('D').mean() 或类似操作,结果发现原始缺失的日期根本没出现——resample() 只对已有数据分组聚合,不会主动补全新时间点。真正要“补全”,得先构造完整的时间索引,再对齐。
正确路径是:确保 DataFrame 有 DatetimeIndex → 用 asfreq() 或 reindex() 拉出完整时间轴 → 再插值。
- 优先用
asfreq('D')(比reindex()更简洁,自动填充NaN) - 如果原始索引不是
DatetimeIndex,必须先转:df.index = pd.to_datetime(df.index) -
asfreq()不会改变原始值,只补齐空档;后续插值才填数字
interpolate() 默认线性插值不适用于时间间隔不均
直接调 df.interpolate() 很容易踩坑:它默认按行号(整数位置)插值,不是按真实时间距离。比如 2023-01-01、2023-01-03、2023-01-10 缺了中间两天,线性插值会把 01-03 和 01-10 当作相邻行,等距分配,结果偏差大。
必须显式指定时间感知插值:
立即学习“Python免费学习笔记(深入)”;
- 用
df.interpolate(method='time')—— 它会把索引转成纳秒级整数,按真实时间差加权 - 或更明确地写
df.interpolate(method='index')(前提是索引是datetime64类型) - 避免用
method='linear',除非你确认索引是等间隔且已排序
高频数据补全要小心 limit_area 参数
传感器或日志类时间序列常有连续多天缺失,比如断采三天后恢复。若直接 interpolate(method='time'),可能把第 10 天的值一路插到第 1 天,完全失真。
这时必须限制插值作用范围:
-
df.interpolate(method='time', limit_area='inside'):只插中间的空段,两端不延展 -
df.interpolate(method='time', limit=2):最多连续插 2 个缺失值(即补 2 天) - 组合使用更稳妥:
limit_area='inside', limit=3,既防外推又控长度
注意:limit 是按缺失单元格数算的,不是按天数——如果一行有多个列,每个列单独计数。
非等频时间序列建议先 asfreq() 再插值,别用 resample().interpolate()
resample('H').interpolate() 看似方便,但本质是先聚合(默认取左闭区间均值)再插值,会模糊原始采样点。比如原始有 09:15 和 10:45 两条记录,resample('H') 会把它们都归到 09:00–10:00 和 10:00–11:00 两个桶里,再插值就脱离了真实时间戳。
正确做法始终是保真优先:
- 用
df.asfreq('15T')补齐 15 分钟粒度的索引(空位填NaN) - 再用
.interpolate(method='time')填值 - 如果原始频率不规则(如秒级+毫秒级混杂),先
sort_index()+drop_duplicates(keep='last')去重去乱
时间序列插值最易被忽略的,其实是索引是否严格单调且无重复——哪怕只差 1 纳秒,method='time' 也可能报 ValueError: Index cannot contain duplicate values。


















