不能直接套用统计学离群点检测方法,因传感器数据具强时序性、非平稳性、物理约束及工况差异;需结合运行状态分组+滚动窗口自适应计算阈值,并采用符合物理特性的修复策略。

直接用 IQR 或 z-score 做阈值截断,大概率会把真实突变信号当异常值删掉——传感器数据的“离群点”往往对应设备启停、负载切换或故障前兆,不是噪声。
为什么不能直接套用统计学离群点检测方法?
生产传感器数据有强时序性、非平稳性和物理约束。比如温度传感器在压缩机启动瞬间跳变 15℃ 是合理的,但用全局 z-score > 3 就会被标为异常;又比如振动幅值在低频段本底噪声大,固定 IQR 倍数会误杀。
- 传感器采样率不一致(有的 10Hz,有的 1s 一帧),导致滑动窗口长度难统一
- 同一类传感器在不同工况下正常范围差异大(空载 vs 满载电流)
- 多传感器耦合异常(如冷却水流量↓ + 出口温度↑ 同时发生才是真异常,单看都不超标)
用滚动窗口 + 工况标签做自适应阈值
核心是放弃“全量数据一个阈值”,改用带上下文的局部判断。先按运行状态(如 PLC 提供的 status_code 或聚类得到的工况标签)分组,再在每组内用滚动窗口算 rolling_iqr 或 rolling_std。
示例逻辑:
立即学习“Python免费学习笔记(深入)”;
df['iqr_window'] = df.groupby('operating_mode')['value'].transform(
lambda x: x.rolling(window=120, min_periods=30).quantile(0.75)
- x.rolling(window=120, min_periods=30).quantile(0.25)
)
df['upper_bound'] = df.groupby('operating_mode')['value'].transform(
lambda x: x.rolling(window=120, min_periods=30).quantile(0.75) + 1.5 * df['iqr_window']
)
df['is_outlier'] = df['value'] > df['upper_bound']
- 窗口大小选 120 是因为多数工业现场采样间隔为 0.5–2s,120 点 ≈ 1–4 分钟,足够覆盖稳态波动
-
min_periods=30防止启停阶段窗口内数据不足导致 NaN 连锁失效 - 必须用
groupby('operating_mode'),否则空载时的正常低值会被满载阈值误判
保留物理意义的“修复”而非粗暴删除
传感器数据缺失或异常后,插值要符合设备特性。线性插值对阶跃变化失真严重,而用前后均值会模糊瞬态响应。
- 对短时异常(
duration ),用 <code>pd.Series.interpolate(method='time'),它按实际时间戳加权,比method='linear'更准 - 对持续异常段(如传感器断连 30s),用上一个稳定周期的相同相位值替换(例如电机每转一圈采集 16 点,则用前一圈对应角度的值)
- 绝对不要用
fillna(method='ffill')跨工况填充——空载末尾值填到满载开头会引入系统性偏差
最易被忽略的是时间戳对齐:多个传感器走不同总线,时钟漂移可能达 ±200ms。不做亚秒级对齐就做多变量联合分析,相关性结论全是假阳性。


















