2. PHM数据清洗与异常值处理实战

任务说明

本案例针对工业传感器时序数据,完成缺失值、噪声与异常点的清洗,输出可直接用于训练的数据集。核心处理链:滑动窗口均值滤波 → 3σ 准则标记异常 → 线性插值修复缺失与异常。输入为带缺失(NaN)和尖峰噪声的单通道传感器序列,输出为等长、无缺失、无异常点的干净序列。

环境与依赖

  • Python 3.8+,依赖 numpy、pandas(pip install numpy pandas)。
  • 无需其他框架,脚本可直接运行。

处理流程

原始序列 含NaN/尖峰 滑动窗口滤波 窗口=5 均值 3σ 异常检测 标记越界点 线性插值修复 输出干净数据集

完整实现

import numpy as np
import pandas as pd

def clean_sensor(series, window=5, sigma=3.0):
    """滑动窗口滤波 + 3σ异常标记 + 线性插值修复"""
    s = pd.Series(series, dtype="float64")

    # 1. 滑动窗口均值滤波(min_periods=1 保证边界与NaN不丢点)
    smoothed = s.rolling(window=window, center=True, min_periods=1).mean()

    # 2. 3σ 准则:基于滤波后序列的均值/标准差标记异常
    mu, std = smoothed.mean(), smoothed.std(ddof=0)
    lower, upper = mu - sigma * std, mu + sigma * std
    mask = (smoothed < lower) | (smoothed > upper)

    # 3. 将原始缺失值与异常点统一置为NaN,再线性插值
    cleaned = s.copy()
    cleaned[mask] = np.nan
    cleaned = cleaned.interpolate(method="linear", limit_direction="both")

    return cleaned, mask, (lower, upper)

if __name__ == "__main__":
    # 构造含缺失与尖峰的示例数据
    raw = [10.0, 10.2, np.nan, 10.1, 10.3, 50.0, 10.2, 10.1,
           np.nan, 10.4, 10.2, 10.3, -30.0, 10.1, 10.2]
    cleaned, mask, bounds = clean_sensor(raw, window=5, sigma=3.0)

    print("异常点索引:", list(np.where(mask)[0]))
    print("3σ区间:", tuple(round(b, 3) for b in bounds))
    print("清洗后是否含NaN:", cleaned.isna().any())
    print("清洗后序列:")
    print(cleaned.round(3).tolist())

运行与验证

直接执行 python clean_sensor.py。判定通过条件:

  • 清洗后是否含NaN 输出 False,说明缺失与异常点均被修复;
  • 异常点索引 应包含尖峰位置(示例中索引 5 与 12);
  • 清洗后序列长度与输入一致,且数值落在 3σ 区间内,无 50.0、-30.0 等离群值。

若需接入真实数据,将 raw 替换为传感器 CSV 的某一列即可,例如 pd.read_csv("sensor.csv")["value"]。

关键点

  • center=True 使滤波窗口居中,避免相位偏移;min_periods=1 保证首尾与NaN位置不产生空洞。
  • 3σ 阈值基于滤波后序列计算,可抑制单个尖峰对均值/方差的污染。
  • limit_direction="both" 确保序列首尾的缺失也能被插值填充,输出等长无缺失数据。