首页 › 技术知识 › 工程笔记 › 算法笔记 › Hampel 滤波器在数据清洗上的实战
算法笔记 气象 Hampel数据清洗离群点中位数

Hampel 滤波器在数据清洗上的实战

Hampel Filter for Data Cleaning

环境数据里的离群点(仪器故障、维护、雷击)会让趋势分析、统计平均全部失真。Hampel 滤波器基于中位数与 MAD,比均值标准差方法对异常值更鲁棒。

约 2021 字· 6 分钟阅读

为什么不用"均值±3σ"

传统离群点检测:|x - mean| > 3 × std 算异常。问题是:

  • 异常值本身就影响 mean 与 std
  • 多个异常值时,std 被拉大,3σ 阈值随之变大,小异常值漏检

Hampel 滤波器用中位数与MAD(中位数绝对偏差),对异常值免疫。

算法

对每个样本 x[i]:

  1. 取窗口 W(如前后各 5 个样本,共 11 个)
  2. 计算中位数 med
  3. 计算 MAD = median(|x[j] - med|),j 在窗口内
  4. 计算 σ ≈ 1.4826 × MAD(高斯分布等效)
  5. 若 |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、保留原始 + 标记 + 清洗三套,是经过实战的稳健配置。