1. 缺失值误判为异常值:阈值清洗导致有效数据被删的排障

问题定位:固定阈值把合法极值判成异常

某环境监测数据集的 PM2.5 小时浓度列在清洗后行数骤减约 18%,被删记录集中在夜间与沙尘时段。原清洗脚本使用固定阈值规则:PM2.5 > 150 即判为异常并整行删除。问题在于该阈值把两类完全不同的情况混为一谈:一类是传感器故障产生的离群值(如 999、-1、0 等哨兵值),另一类是沙尘或重污染过程中真实出现的高浓度值(180~420 μg/m³)。前者应删除或标记,后者属于有效观测,删除会直接破坏污染过程分析和日均值统计。

排障的核心不是调阈值大小,而是先区分“缺失/无效”与“合法极值”两种语义,再让清洗规则按语义分别处理。下面用分布对比与业务边界核查两条线索交叉定位。

固定阈值清洗:合法极值被误删的定位与修正 原始 PM2.5 分布(示例) 浓度 μg/m³ 999 阈值 150 正常主体 合法极值 哨兵值 错误规则:一刀切删除 if PM2.5 > 150 → 删除整行 合法极值 180~420 被删 行数减少约 18%,过程断裂 修正规则:按语义分流 哨兵值/负值 → 标记缺失 合法极值 → 保留并标注 行数不变,统计口径一致 业务边界核查:区分“无效值”与“合法极值”的判断依据 ① 哨兵值特征 • 999 / -1 / -999 等固定码 • 与相邻时段突变、无过程 • 多站点同时出现同值 → 判为缺失,标记不删除 ② 合法极值特征 • 180~420 连续多小时爬升 • 与沙尘/静稳天气过程吻合 • 多站点空间相关性强 → 保留,必要时加质量标记 ③ 修正后验证 • 清洗前后行数差 = 哨兵值数 • 日均值与原表偏差 < 1% • 沙尘过程曲线连续可查 → 通过则规则修正完成

用分布对比锁定误删区间

先对原始列做分位数与直方图检查,而不是直接看最大值。示例数据(教学假设)中,PM2.5 的 P50≈42、P95≈118、P99≈210、最大值 999。若阈值取 150,则 P95 到 P99 之间的 180~210 区间会被整段删除,而这正是重污染过程的真实浓度。判断依据是:被删样本在时间上连续、在空间上多站点同步升高,且与气象沙尘过程对应,说明它们是有效观测而非随机噪声。

同时检查被删样本的取值形态:若大量记录恰好等于 999、-1、-999 等固定值,或与前后时刻出现无过渡的跳变,则属于哨兵值/无效值。两类样本混在同一阈值下被删除,是本次排障的关键发现。

修正规则:标记缺失而非删除

修正思路是把“删除”改为“标记”,并让阈值只作用于哨兵值识别,不再承担极值裁剪职责。以下为可直接运行的 Python 示例,使用 pandas 对示例数据执行修正前后对比。

import pandas as pd
import numpy as np

# 构造教学示例数据:正常值 + 合法极值 + 哨兵值
np.random.seed(7)
normal = np.random.normal(45, 20, 800).clip(1, 140)
legit_extreme = np.linspace(160, 420, 60)          # 沙尘过程合法极值
sentinel = np.array([999, -1, -999] * 10)          # 哨兵值
pm = np.concatenate([normal, legit_extreme, sentinel])
df = pd.DataFrame({"pm25": pm})

# 错误规则:固定阈值直接删除
wrong = df[df["pm25"] <= 150].copy()

# 修正规则:哨兵值标记为缺失,合法极值保留
SENTINEL = {999, -1, -999}
df["pm25_clean"] = df["pm25"].where(~df["pm25"].isin(SENTINEL))
df["qc_flag"] = np.where(df["pm25"].isin(SENTINEL), "missing", "valid")

print("原始行数:", len(df))
print("错误规则后行数:", len(wrong))
print("修正后行数:", len(df))
print("标记缺失数:", (df["qc_flag"] == "missing").sum())
print("保留的合法极值数:", ((df["pm25"] > 150) & (df["qc_flag"] == "valid")).sum())

预期输出(由上述示例数据直接推出):原始 890 行,错误规则后约 860 行(删掉 60 个合法极值中的大部分及哨兵值),修正后仍为 890 行,标记缺失 30 个,保留合法极值 60 个。行数不再因极值被误删而减少,缺失语义由 qc_flag 显式表达。

验证与通过条件

  • 行数守恒:清洗前后行数差应等于哨兵值/无效值数量,不应包含合法极值。
  • 统计口径一致:对 pm25_clean 求日均值时,缺失值自动跳过,日均值与原始有效观测的偏差应小于 1%(示例数据下可直接核对)。
  • 过程连续性:沙尘时段 180~420 的曲线在清洗后仍连续可查,不被截断。
  • 标记可追溯:qc_flag 能区分 missing 与 valid,后续聚合可按标记过滤,避免再次误删。
若业务确实需要剔除极端值,应使用基于分布的分位数规则(如按站点、按季节计算 P99.5)并保留原始值副本,而不是用全局固定阈值直接删除整行。
不要用“最大值是否超过阈值”作为唯一判据。合法极值与哨兵值在数值上可能都很大,必须结合时间连续性、空间相关性和固定码特征综合判断。