如何根据趋势条件清理Series/DataFrame,将异常值替换为NaN?
处理时间序列中的异常值并替换为NaN
针对你提供的温度时间序列数据,这里有几种高效的异常值处理方法,比单纯基于前一行判断更合理且高效:
先构造示例数据
首先还原你的Series:
import pandas as pd import numpy as np data = { 'Time': ['2019-01-02 02:00:00', '2019-01-02 03:00:00', '2019-01-02 04:00:00', '2019-01-02 05:00:00', '2019-01-02 06:00:00'], 'Temperature': [14.95, 15.0, 37.0, 15.0, 15.5] } series = pd.Series(data['Temperature'], index=pd.to_datetime(data['Time']))
方法1:Z-score统计法
利用数据的整体分布判断异常,适合波动稳定的数据集,计算效率极高(O(n)):
# 计算每个数据点的Z-score z_scores = np.abs((series - series.mean()) / series.std()) # 设定阈值(通常取3,即超出3倍标准差视为异常) threshold = 3 # 替换异常值为NaN series_cleaned = series.where(z_scores < threshold, np.nan)
方法2:滑动窗口局部趋势法
基于局部窗口内的统计特征判断异常,更贴合时间序列的局部趋势:
# 以当前值为中心,取前后各1个数据点组成窗口,计算局部均值 window_mean = series.rolling(window=3, center=True).mean() # 计算当前值与局部均值的相对差异 diff_ratio = np.abs(series - window_mean) / window_mean # 设定差异阈值(比如超过50%视为异常) threshold = 0.5 series_cleaned = series.where(diff_ratio < threshold, np.nan)
方法3:前后值线性插值判断法
利用前后数据的线性趋势推导预期值,判断当前值是否偏离趋势:
# 获取前一行和后一行的值 prev_val = series.shift(1) next_val = series.shift(-1) # 计算当前时间点的线性插值预期值(因时间间隔均匀,权重取0.5) expected_val = prev_val + (next_val - prev_val) * 0.5 # 计算当前值与预期值的绝对差 diff = np.abs(series - expected_val) # 设定差值阈值(比如超过1度视为异常) threshold = 1.0 series_cleaned = series.where(diff < threshold, np.nan)
方法选择建议
- 如果数据整体波动小、分布稳定,优先用Z-score法,速度最快;
- 如果异常是局部偏离趋势,用滑动窗口法或线性插值法更准确,能更好贴合时间序列的连续性。
内容的提问来源于stack exchange,提问作者Simone Panico
相关产品推荐
相关产品推荐

