时间序列清洗需先用pd.to_datetime(..., errors='coerce')转datetime并处理混合类型,再用interpolate(method='time')插值,接着用rolling('7d').quantile识别异常值,最后验证缺失值、统计量及可视化。

用 pd.to_datetime 强制解析时间列,但要小心返回 NaT
时间序列清洗的第一步往往是把时间列转成 datetime64 类型。直接用 pd.to_datetime(df['time'], errors='coerce') 最稳妥——它会把无法解析的字符串(比如 '2023-99-01' 或空格)转成 NaT,而不是报错中断。别用 errors='raise',除非你明确想定位脏数据位置;也别省略 errors 参数,默认值是 'raise',容易在生产环境突然崩掉。
注意:如果原始列含混合类型(比如部分是字符串、部分是整数时间戳),先统一转成字符串再解析更安全:pd.to_datetime(df['time'].astype(str), errors='coerce')。否则整数可能被误当作纳秒时间戳,导致诡异的年份(如 1970 年)。
用 interpolate 填补缺失值,但得选对方法和方向
时间序列的缺失值不能简单用均值或中位数填充,interpolate 更合理。默认线性插值(method='linear')只按行索引等距计算,但真实时间序列索引往往不等距。所以必须先确保索引是 DatetimeIndex,再用 method='time' 或 method='index':
-
method='time':按实际时间间隔加权(推荐,尤其当采样不规律时) -
method='index':按索引位置等距插值(适合已重采样为固定频率的序列) - 避免用
method='pad'或method='bfill'填充长时间缺口,容易掩盖趋势断裂
示例:df.set_index('time').interpolate(method='time').reset_index()。注意:插值前最好先 sort_index(),否则结果不可靠。
用 rolling + quantile 识别异常值,比固定阈值更鲁棒
对时间序列,用全局均值±3倍标准差找异常值很容易误杀——比如某天设备刚重启,读数普遍偏高。改用滚动窗口统计更合理。例如取 7 天滚动窗口的上下四分位数,把超出 [Q1 - 1.5×IQR, Q3 + 1.5×IQR] 的点标为异常:
q1 = df['value'].rolling('7D').quantile(0.25)
q3 = df['value'].rolling('7D').quantile(0.75)
iqr = q3 - q1
outliers = (df['value'] q3 + 1.5 * iqr)
关键点:
- 窗口用字符串(如
'7D')而非整数,才能对不规则时间索引正确对齐 - 滚动计算前必须确保索引是
DatetimeIndex且已排序 -
min_periods=3可设为较小值,避免开头大量NaN
处理完记得检查 isna().sum() 和 describe() 的分布变化
填补和剔除操作容易引入新问题:插值可能让方差变小,异常值过滤可能删掉真实突变。每次操作后必须验证:
- 运行
df['value'].isna().sum()确认缺失没意外增加 - 对比处理前后
df['value'].describe(),看std、min、max是否突变过大 - 画图:用
df.plot(x='time', y='value', style='.')快速扫一眼是否出现“直线段”(插值痕迹)或“断崖”(异常剔除过度)
最易被忽略的是时间索引的连续性——resample('1H').mean() 会自动补全缺失时间点并填 NaN,但如果你后续做差分或建模,这些隐式插入的 NaN 可能引发连锁错误。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











