Hampel 滤波器在数据清洗上的实战
环境数据里的离群点(仪器故障、维护、雷击)会让趋势分析、统计平均全部失真。Hampel 滤波器基于中位数与 MAD,比均值标准差方法对异常值更鲁棒。
为什么不用"均值±3σ"
传统离群点检测:|x - mean| > 3 × std 算异常。问题是:
- 异常值本身就影响 mean 与 std
- 多个异常值时,std 被拉大,3σ 阈值随之变大,小异常值漏检
Hampel 滤波器用中位数与MAD(中位数绝对偏差),对异常值免疫。
算法
对每个样本 x[i]:
- 取窗口 W(如前后各 5 个样本,共 11 个)
- 计算中位数 med
- 计算 MAD = median(|x[j] - med|),j 在窗口内
- 计算 σ ≈ 1.4826 × MAD(高斯分布等效)
- 若 |x[i] - med| > k × σ(k 通常取 3),则判为异常,用 med 替换
关键参数
窗口大小
- 窗口小:对突发异常敏感,但漏掉缓慢漂移
- 窗口大:对持续异常鲁棒,但响应慢
环境监测推荐窗口 11~21 个样本(半小时到 1 小时数据,5~10 min 采样)。
阈值 k
- k = 2:激进,剔除多,可能误剔正常极值
- k = 3:标准
- k = 5:保守,只剔极端异常
环境数据推荐 k = 3~4。
实战代码(Python)
```python import numpy as np from scipy.ndimage import median_filter
def hampel(data, window=11, n_sigma=3.0): """Hampel 滤波器:剔除离群点
data: 时间序列 window: 窗口大小(奇数) n_sigma: 阈值倍数 返回:清洗后数据 + 异常标记 """ half = window // 2 n = len(data) cleaned = data.copy() outliers = np.zeros(n, dtype=bool)
# 中位数滤波 med = median_filter(data, size=window, mode='nearest')
# MAD abs_dev = np.abs(data - med) mad = median_filter(abs_dev, size=window, mode='nearest') sigma = 1.4826 * mad
# 避免除零 sigma[sigma == 0] = np.nanmedian(sigma[sigma > 0]) if np.any(sigma > 0) else 1
# 检测异常 is_outlier = np.abs(data - med) > n_sigma * sigma cleaned[is_outlier] = med[is_outlier] outliers = is_outlier
return cleaned, outliers
模拟:温度数据 + 几个离群点
np.random.seed(42) n = 1000 true_data = 20 + 5 * np.sin(2 * np.pi * np.arange(n) / 24) # 日变化 noisy_data = true_data + np.random.randn(n) * 0.3
加离群点
noisy_data[100] = 35 # 雷击 noisy_data[200] = -5 # 传感器故障 noisy_data[[300, 301, 302]] = 30 # 维护
cleaned, outliers = hampel(noisy_data, window=21, n_sigma=3.0) print(f"检测到异常: {np.sum(outliers)} 个") print(f"清洗前 RMSE: {np.sqrt(np.mean((noisy_data - true_data)2)):.2f}") print(f"清洗后 RMSE: {np.sqrt(np.mean((cleaned - true_data)2)):.2f}") ```
常见错
错一:窗口太小
window = 5 时,连续 3 个异常点会被当作"正常"(中位数被污染)。正确做法:window > 2 × 异常段长度 + 1。
错二:对全数据统一参数
数据不同时段噪声特性不同(白天噪声大、夜间小)。可以分段调参,或用自适应窗口。
错三:剔除后不做记录
直接替换异常值,原始数据丢失,后续无法溯源。正确做法:保留原始数据 + 异常标记 + 清洗后数据三套,可追溯。
错四:用 Hampel 剔除趋势
Hampel 设计用于剔除"脉冲"异常,不擅长剔除趋势异常(如缓慢漂移)。缓慢漂移用"差分阈值"或"模型残差"检测更合适。
与其他方法比较
| 方法 | 优点 | 缺点 |
|---|---|---|
| 均值 ± 3σ | 简单 | 异常值影响统计量 |
| Hampel | 鲁棒 | 计算稍慢 |
| IQR | 类似 Hampel | 不直接给替换值 |
| DBSCAN | 可检测多簇异常 | 参数敏感、慢 |
| Isolation Forest | 适合高维 | 黑盒、慢 |
环境监测时间序列,Hampel 是性价比最高的选择。
结语
环境数据清洗不是"调一个函数",是算法 + 参数 + 元数据的组合。Hampel 滤波器基于中位数与 MAD,对异常值鲁棒,是时间序列清洗的首选。窗口 11~21、阈值 3~4、保留原始 + 标记 + 清洗三套,是经过实战的稳健配置。