3、数据质量评估:数据完整性检查、异常值检测(3σ原则、IQR方法)、缺失值模式分析、时间戳对齐问题
各位工程师朋友,咱们接着聊。上一章我们把数据从历史库里捞了出来,但说实话,捞出来的数据能不能直接用?我个人的经验是——千万别信。SCADA系统的数据,说白了就是现场传感器、PLC、RTU一层层传上来的,中间经过了多少噪声干扰、通信丢包、设备故障,你根本想象不到。
我记得有一次,一个水处理项目,现场报上来一个液位数据,连续三天都是0.00。操作员以为是水池空了,差点启动紧急补水。我一看,嗯,传感器线被老鼠咬断了。所以,数据质量评估是数据挖掘的第一步,也是最重要的一步。你想想看,垃圾数据进去,再牛的算法也白搭。
这一章,我们就来拆解数据质量评估的四个核心维度:完整性检查、异常值检测、缺失值模式分析、时间戳对齐。我会把我在项目中踩过的坑、总结的经验,都揉碎了讲给你听。
3.1 数据完整性检查
完整性检查,说白了就是看看数据有没有缺胳膊少腿。我习惯从两个维度入手:字段级完整性和记录级完整性。
字段级完整性,就是看每个字段有多少空值。比如一个温度测点,理论上应该每分钟一条数据,结果发现某一天有30%的时间戳是空的。嗯,这就有问题了。
我一般会先算一个空值率:
# 计算每个字段的空值率
import pandas as pd
def check_null_ratio(df):
null_ratio = df.isnull().sum() / len(df) * 100
return null_ratio.sort_values(ascending=False)
# 举个例子
null_info = check_null_ratio(scada_data)
print(null_info[null_info > 0]) # 只看有空值的字段
记录级完整性,则是看时间序列有没有断点。比如你期望每5分钟一条数据,结果从下午2点到3点之间一条都没有。这可能是通信中断,也可能是PLC死机了。
我的经验阈值:
- 空值率 < 1%:数据质量优秀,可以直接用
- 空值率 1% ~ 5%:需要关注,但通常可以插补
- 空值率 > 5%:必须排查原因,不能直接使用
小技巧:我习惯把空值率做成热力图,一眼就能看出哪些测点、哪些时间段问题最严重。颜色越深,问题越大。
3.2 异常值检测:3σ原则与IQR方法
异常值检测,这是数据质量评估的重头戏。SCADA数据里的异常值,说白了就是那些「离谱」的数据点。比如一个压力变送器,正常范围是0~10MPa,结果突然蹦出来一个100MPa。这要么是传感器坏了,要么是通信受到了干扰。
我常用的方法有两种:3σ原则和IQR方法。它们各有各的适用场景。
3σ原则
3σ原则基于正态分布假设。简单说,就是数据落在均值±3个标准差之外的概率只有0.3%。如果某个数据点落在这个范围之外,我就认为它是异常值。
def detect_outliers_3sigma(data_series):
mean = data_series.mean()
std = data_series.std()
lower_bound = mean - 3 * std
upper_bound = mean + 3 * std
outliers = data_series[(data_series < lower_bound) | (data_series > upper_bound)]
return outliers, lower_bound, upper_bound
# 举个例子
outliers, low, high = detect_outliers_3sigma(pressure_data)
print(f"检测到 {len(outliers)} 个异常值,范围: [{low:.2f}, {high:.2f}]")
注意:3σ原则对异常值本身很敏感。如果数据里已经有很多异常值,均值和标准差会被「带偏」,导致检测失效。我曾经在一个流量计数据上吃过这个亏——数据里有一堆尖峰,结果3σ把正常值也判成了异常。
IQR方法
IQR方法,也就是四分位距法,它不依赖正态分布假设,对异常值的鲁棒性更好。它的逻辑是:计算数据的Q1(25%分位数)和Q3(75%分位数),然后定义IQR = Q3 - Q1。通常认为,小于Q1 - 1.5×IQR或大于Q3 + 1.5×IQR的数据是异常值。
def detect_outliers_iqr(data_series):
Q1 = data_series.quantile(0.25)
Q3 = data_series.quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = data_series[(data_series < lower_bound) | (data_series > upper_bound)]
return outliers, lower_bound, upper_bound
# 举个例子
outliers_iqr, low_iqr, high_iqr = detect_outliers_iqr(pressure_data)
print(f"IQR方法检测到 {len(outliers_iqr)} 个异常值")
我的选择建议:
- 数据近似正态分布(比如温度、液位)→ 用3σ原则
- 数据分布偏斜严重(比如流量、压力尖峰)→ 用IQR方法
- 实在拿不准 → 两个都跑一遍,取交集或并集
3.3 缺失值模式分析
很多人一看到缺失值,就直接用均值填充或者前向填充。我告诉你,千万别这么干。缺失值不是凭空出现的,它背后往往有原因。你需要先搞清楚缺失值的模式。
统计学上把缺失值分为三种模式:
| 模式 | 含义 | SCADA场景举例 | 处理建议 |
|---|---|---|---|
| MCAR 完全随机缺失 |
缺失与否与数据本身无关 | 通信偶尔丢包,随机缺失 | 可以直接删除或简单插补 |
| MAR 随机缺失 |
缺失与否与其他变量有关 | 温度过高时,传感器保护性停机导致数据缺失 | 需要用其他变量建模预测 |
| MNAR 非随机缺失 |
缺失与否与缺失值本身有关 | 液位超过量程时,传感器输出满量程值(实际已失效) | 必须排查物理原因,不能简单插补 |
我习惯用缺失值热力图和缺失值关联分析来判断模式。比如,我发现A测点缺失的时候,B测点也经常缺失,那可能就是共因故障(比如同一个通信模块坏了)。
# 缺失值关联分析示例
def missing_correlation(df):
# 将数据转为是否缺失的布尔矩阵
missing_matrix = df.isnull().astype(int)
# 计算缺失模式之间的相关系数
corr = missing_matrix.corr()
return corr
# 如果两个测点的缺失相关系数 > 0.8,说明它们很可能共享同一个故障源
避坑指南:我曾经在一个风电项目里,发现所有风速大于25m/s时的数据都缺失了。一开始以为是随机缺失,后来才发现是风速计在强风下被吹坏了。这就是典型的MNAR——缺失值本身就和风速有关。如果当时用均值填充,那后续的发电量预测模型就全废了。
3.4 时间戳对齐问题
时间戳对齐,这是SCADA数据挖掘里最容易被忽视、但也是最坑人的问题。你想想看,一个工厂里可能有几十个PLC,每个PLC的时钟可能都不一样。有的快几秒,有的慢几分钟。如果不做对齐,你分析出来的结果就是「鸡同鸭讲」。
我遇到过最离谱的一次,是一个化工项目,DCS系统和PLC系统的时间差了整整8分钟。结果我做的物料平衡计算,怎么算都对不上。后来发现,DCS用的是北京时间,PLC用的是UTC时间,差了8小时。嗯,这锅得让工程师背。
时间戳对齐主要解决三个问题:
- 时间抖动(Jitter):数据到达时间不稳定,比如本该整点到的数据,有时候早2秒,有时候晚3秒
- 时间漂移(Drift):时钟逐渐偏离标准时间,比如一天慢1秒
- 时区/夏令时问题:不同系统使用不同时区,或者夏令时切换导致数据重复/缺失
我的对齐策略是这样的:
def align_timestamps(df, freq='5T', method='ffill'):
"""
时间戳对齐函数
freq: 目标频率,如'5T'表示5分钟
method: 填充方法,'ffill'前向填充,'bfill'后向填充,'interpolate'插值
"""
# 1. 确保时间戳是datetime类型
df.index = pd.to_datetime(df.index)
# 2. 创建标准时间轴
start = df.index.min().ceil(freq)
end = df.index.max().floor(freq)
standard_index = pd.date_range(start=start, end=end, freq=freq)
# 3. 重新索引并对齐
df_aligned = df.reindex(standard_index)
# 4. 填充缺失值
if method == 'ffill':
df_aligned = df_aligned.fillna(method='ffill')
elif method == 'interpolate':
df_aligned = df_aligned.interpolate()
return df_aligned
# 使用示例
aligned_data = align_timestamps(raw_data, freq='1T', method='interpolate')
特别提醒:时间戳对齐时,一定要保留原始时间戳作为备用。我见过有人直接覆盖了原始数据,结果发现对齐逻辑有bug,想回退都回退不了。我的习惯是,在数据框里加一列 original_timestamp,永远不删。
小结
数据质量评估,说白了就是给数据「体检」。完整性检查看有没有缺胳膊少腿,异常值检测看有没有离谱的数据点,缺失值模式分析看缺失背后的原因,时间戳对齐确保所有数据在同一个时间轴上说话。
这四步走完,你的数据才算真正「能用」。下一阶段,我们就可以开始做特征工程了。但那是后话,先把眼前的数据质量搞扎实。
记住一句话:数据质量决定了分析的天花板。算法再牛,也救不了烂数据。
公众号:蓝海资料掘金营,微信deep3321