fillna()对时序缺失数据常失效,因默认不识别时间顺序;须先确保索引为排序后的DatetimeIndex,再用asfreq()对齐频率,配合interpolate(method='time')或ffill等填充才准确。

为什么 fillna() 对时序缺失数据经常失效
因为 fillna() 默认按列逐值填充,不理解时间顺序,也不会考虑前后时间点的业务逻辑。比如用 method='ffill' 填充,遇到连续多天缺失,就只是把上一个非空值机械复制过去,无法反映趋势或周期性。更关键的是:如果索引不是 DatetimeIndex,ffill/bfill 仍会按行号而非时间先后执行,结果完全错位。
必须先确保索引是 DatetimeIndex 并已排序
这是所有时序填充操作的前提。Pandas 的时间感知方法(如 asfreq()、resample())只在正确的时间索引下才可靠。
- 检查索引类型:
type(df.index)应返回pandas.core.indexes.datetimes.DatetimeIndex - 如果不是,用
df.index = pd.to_datetime(df.index)转换(注意传入列名或指定errors='coerce'处理非法日期) - 强制升序并去重:
df = df.sort_index().drop_duplicates(),否则asfreq()可能报ValueError: cannot reindex from a duplicate axis
用 asfreq() + fillna() 组合实现等频对齐填充
asfreq() 是时序填充的核心入口——它先把数据“拉”到目标频率(如每日),再暴露缺失位置,此时再填才真正基于时间间隔。
- 先调用
df.asfreq('D')将数据转为日频,自动插入NaN占位缺失日期 - 再用
fillna(method='ffill', limit=7)向前填充最多7天(避免跨月/跨季污染) - 若需插值,改用
interpolate(method='time'),它会按真实时间差加权,比method='linear'更准 - 注意:
interpolate(method='time')要求索引为DatetimeIndex且无重复值,否则静默退化为线性插值
df_daily = df.asfreq('D')
df_filled = df_daily.interpolate(method='time').fillna(method='ffill', limit=7)
处理周期性数据(如每小时温度)要慎用线性插值
温度、电量等有明显日周期的数据,直接 interpolate(method='time') 会在凌晨和正午之间画一条直线,物理意义错误。这时应优先考虑:
立即学习“Python免费学习笔记(深入)”;
- 用
resample('H').mean()重采样后填充,利用原始粒度信息 - 对齐到固定周期后,用
groupby(df.index.hour).transform('mean')填充均值(适合稳定周期模式) - 避免用
method='polynomial'或高阶插值——时序噪声会让拟合结果剧烈震荡
真正难的不是语法,而是判断缺失是随机丢失(可用插值),还是系统性断采(该标记为异常而非填充)。


















