1. 尾矿库浸润线监测数据异常识别与初判
案例任务与判据建立
某尾矿库在坝体 3 个断面布置了 9 支振弦式渗压计(测点编号如 P1-1 表示 1 号断面第 1 支),采集频率 1 次/小时,输出为测压管水位(单位 m,以坝基高程为基准)。本案例取其中 7 天(168 个采样点)的序列,任务是先做数据质量筛查,再对可疑段做渗流合理性初判,最终把异常归入“传感器故障”或“真实渗流响应”两类。
三类异常的定义与量化判据如下(阈值可按库区实际调整,此处为教学示例取值):
- 数据中断:连续缺失 ≥ 3 个采样点,或单点时间戳间隔 > 2 倍采集周期。
- 跳变:相邻两点差值 |Δh| > 0.30 m,且跳变后 3 点内未回落到原趋势带(±0.05 m)内。
- 漂移:以 24 点滑动中位数拟合斜率,|k| > 0.02 m/h 且持续 ≥ 12 点,同时与库水位变化方向不一致。
异常识别与初判逻辑
筛查不是单纯看数值大小,而是把数据形态与物理合理性交叉验证。核心交叉项有三个:跳变是否伴随信号质量指标(如振弦频率、激励响应)异常;漂移方向是否与库水位升降同向;中断恢复后首值是否与中断前趋势衔接。下图给出从原始序列到初判结论的判读路径与三类异常的典型形态。
关键判读要点
上图中最容易误判的是跳变与漂移。跳变若只出现在单点、且恢复后回到趋势带,多为瞬时干扰(如雷击、接线松动),可插值修复;若跳变后稳定停留在新水平,则要区分是传感器基准偏移还是渗流条件突变——此时看同断面邻点:邻点无同步变化,倾向传感器;邻点同步抬升,倾向真实渗流。
漂移的判别必须引入库水位。若测点水位缓慢上升而库水位同期下降,物理上不合理(除非有额外补给),优先怀疑传感器基准漂移或测管淤堵导致的“假水位”。反之,若漂移方向与库水位一致、幅度在合理响应范围内,则可能是正常渗流调整,不应草率判为故障。
可执行筛查脚本(Python)
下面给出可直接运行的筛查代码,输入为 CSV(列:ts, point_id, level),输出每个测点的异常标记与初判类别。阈值集中在 CFG 中,便于按库区调整。
import pandas as pd
import numpy as np
CFG = dict(gap_pts=3, jump=0.30, band=0.05, drift_k=0.02, drift_len=12)
def screen(df, cfg=CFG):
df = df.sort_values(["point_id", "ts"]).copy()
out = []
for pid, g in df.groupby("point_id"):
g = g.reset_index(drop=True)
h = g["level"].astype(float)
# 1) 中断:时间间隔 > 2 倍周期 或 连续缺失
dt = g["ts"].diff().dt.total_seconds() / 3600
gap = dt > 2
# 2) 跳变:相邻差超限且 3 点内未回落
d = h.diff().abs()
jump = pd.Series(False, index=g.index)
for i in np.where(d > cfg["jump"])[0]:
base = h.iloc[max(0, i-6):i].median()
nxt = h.iloc[i:i+4]
if len(nxt) and (nxt - base).abs().min() > cfg["band"]:
jump.iloc[i] = True
# 3) 漂移:24 点滑动中位数斜率
med = h.rolling(24, min_periods=12).median()
k = med.diff() / dt.replace(0, np.nan)
drift = (k.abs() > cfg["drift_k"]).rolling(cfg["drift_len"]).sum() >= cfg["drift_len"]
out.append(pd.DataFrame({
"point_id": pid, "ts": g["ts"], "level": h,
"gap": gap, "jump": jump, "drift": drift.fillna(False)
}))
return pd.concat(out, ignore_index=True)
# 初判:跳变/漂移且无邻点同步 → 疑传感器;有同步 → 疑真实响应
def verdict(res, sync_pts):
res["verdict"] = "正常"
res.loc[res["gap"], "verdict"] = "通信中断"
bad = res["jump"] | res["drift"]
res.loc[bad & ~res["point_id"].isin(sync_pts), "verdict"] = "疑传感器故障"
res.loc[bad & res["point_id"].isin(sync_pts), "verdict"] = "疑真实渗流响应"
return res
运行方式:res = screen(pd.read_csv("levels.csv", parse_dates=["ts"])),再调用 verdict(res, sync_pts={"P3-1","P3-3"})。验证方法:对已知注入的模拟异常段(如人为置空 5 点、叠加 0.4 m 阶跃、叠加 0.03 m/h 斜坡),检查 gap/jump/drift 三列是否在对应位置置 True,且正常段保持 False。
初判记录卡(可直接填写)
| 字段 | 填写内容 | 判断依据 |
|---|---|---|
| 测点编号 | 如 P2-1 | 断面-序号 |
| 异常时段 | 起止时间戳 | 筛查脚本输出 |
| 异常类型 | 中断 / 跳变 / 漂移 | 对应判据阈值 |
| 信号质量 | 频率、激励响应是否异常 | 原始信号核查 |
| 邻点同步性 | 同断面邻点是否同向变化 | 断面多点对比 |
| 库水位关系 | 同向 / 反向 / 无响应 | 库水位序列对照 |
| 初判结论 | 传感器故障 / 真实渗流 / 存疑 | 交叉验证结果 |
| 后续动作 | 剔除、加密观测、现场校验 | 结论对应处置 |
完成本案例后,应能对任一测点序列给出“异常类型 + 证据链 + 初判类别 + 处置建议”的完整记录,并明确哪些结论仍需现场校验确认。