4. 检测数据清洗基础
海底管道检测数据在进入分析之前,几乎不可能“开箱即用”。无论是漏磁(MFL)内检测、超声测厚、还是ROV外检测,原始数据都会因为传感器掉线、里程计漂移、多次检测拼接、人工录入等原因,出现缺失、重复和异常。清洗不是可选的“美化”步骤,而是决定后续壁厚评估、缺陷增长率和剩余寿命判断是否可信的前置工序。本节围绕管道检测中最常见的三类参数——壁厚、缺陷尺寸、位置——讲清楚清洗的判断依据和具体做法。
先明确数据对象与字段约定
假设我们拿到一份内检测缺陷列表,核心字段包括:defect_id(缺陷编号)、distance_m(距起点里程,单位米,沿管道轴向,起点为发球筒侧)、clock(时钟方位,1~12点,用于环向定位)、depth_pct(缺陷深度占壁厚百分比)、length_mm、width_mm、wall_thickness_mm(该处名义壁厚)、inspection_date。位置参照约定必须全文统一:里程沿介质流动方向递增,环向以管道正上方为12点、顺时针编号。清洗中的任何替换都不能破坏这套参照系。
缺失值:先分类,再决定填还是删
缺失值不能一律删除,也不能一律插补。对管道检测数据,建议按“缺失是否可推断”分三类处理:
- 可确定性推断:如某缺陷的
wall_thickness_mm缺失,但同一里程段的设计壁厚或相邻测点壁厚已知,可直接按管段规格补齐,并记录来源。 - 可统计推断:如少量
depth_pct缺失,且该缺陷长度、宽度完整,可按同类型缺陷(同方位区间、同尺寸量级)的中位数填补,但必须打上“插补”标记,后续统计时单独说明。 - 不可推断:如
distance_m或clock缺失,缺陷就无法定位到管体,这类记录应剔除并进入待复核清单,而不是随意填一个位置。
用 pandas 实现时,关键是“先标记、后处理”,保留可追溯性:
import pandas as pd
import numpy as np
df = pd.read_csv("mfl_defects.csv")
df["wt_missing"] = df["wall_thickness_mm"].isna()
df["depth_missing"] = df["depth_pct"].isna()
# 壁厚按同管段规格补齐(示例:按里程分段映射设计壁厚)
seg_wt = {0: 12.7, 5000: 11.1, 12000: 12.7}
def fill_wt(row):
if pd.notna(row["wall_thickness_mm"]):
return row["wall_thickness_mm"]
for start in sorted(seg_wt, reverse=True):
if row["distance_m"] >= start:
return seg_wt[start]
return np.nan
df["wall_thickness_mm"] = df.apply(fill_wt, axis=1)
# 深度缺失:按方位区间中位数插补,并标记
df["depth_pct"] = df.groupby(df["clock"].round())["depth_pct"] \
.transform(lambda s: s.fillna(s.median()))
df["depth_imputed"] = df["depth_missing"] & df["depth_pct"].notna()
# 位置缺失的记录剔除,进入复核清单
review = df[df["distance_m"].isna() | df["clock"].isna()]
df = df.dropna(subset=["distance_m", "clock"])
重复记录:按“物理同一缺陷”判重
重复记录常见于两次检测结果拼接、同一缺陷被相邻传感器重复报告。判重不能只看 defect_id,因为不同轮次编号会变。更可靠的做法是按物理位置聚类:里程差小于阈值(例如 0.3 m)、环向方位差小于 1 个钟点、且尺寸量级接近的记录,视为同一缺陷,保留信息最完整或检测时间最新的一条。阈值要结合检测器分辨率设定,不能拍脑袋。
df = df.sort_values("distance_m").reset_index(drop=True)
df["clock_num"] = df["clock"].astype(float)
dup_flag = (
df["distance_m"].diff().abs().lt(0.3) &
df["clock_num"].diff().abs().le(1.0)
)
# 标记后人工/规则复核,保留 depth_pct 非空且日期较新者
df["is_dup_candidate"] = dup_flag
异常值:用物理边界和统计规则双重把关
异常值识别要区分“物理不可能”和“统计离群”。物理边界是硬约束:depth_pct 必须在 0~100 之间;length_mm、width_mm 必须为正;clock 必须在 1~12;distance_m 不得超过管道总长。超出即判为录入或单位错误,例如把 12.5 mm 壁厚误录为 125,或把百分比写成小数 0.35 而非 35。
统计离群则用 IQR 或分位数规则,但要按管段、按缺陷类型分组计算,避免把真实的大缺陷误删。例如某管段 depth_pct 的 Q1=8、Q3=22,IQR=14,则上界为 22+1.5×14=43。超过 43% 的记录不直接删除,而是标记为“高深度待复核”,因为深缺陷恰恰是评估重点,误删代价极高。
替换与修正:留下可审计的痕迹
替换异常值时,应遵循“能回查则回查、不能回查则保守替换”的顺序。单位错误可按量纲换算修正;明显笔误可依据同缺陷其他字段反推;无法回查的,用同管段同类型缺陷的中位数替换,并新增 qc_flag 字段记录处理方式(如 unit_fix、median_fill、manual_review)。这样后续做缺陷增长率对比时,能清楚哪些点来自原始数据、哪些经过修正。
清洗后的自检:三个必须回答的问题
完成上述处理后,不要急着进入分析,先做三项自检。第一,位置完整性:是否所有保留记录的 distance_m 都落在 0 到管道总长之间,clock 是否都在 1~12。第二,数值合理性:depth_pct 的分布是否出现不合理的双峰(常见于百分比与小数混录),length_mm 是否出现数量级跳变。第三,可追溯性:每条被修改的记录是否都有 qc_flag,被剔除的记录是否都进入了复核清单。三项都通过,清洗结果才具备进入壁厚评估和缺陷增长率计算的基础。对管道检测而言,清洗的目标不是让数据“好看”,而是让每一个保留的缺陷都能被准确定位、合理量化,并经得起复核。