第三讲:数据采集与预处理——SCADA、CMS与气象数据的“洗剪吹”
各位同行,大家好。今天咱们聊聊数据采集与预处理。说实话,这一章看着基础,但我在现场见过太多“数据没洗干净,后面分析全白干”的案例。你想想看,风机故障诊断就像医生看病,你拿到的CT片子都是花的,那诊断结果能准吗?
我个人习惯把数据预处理比作“洗菜切菜”。菜不洗干净,炒出来的菜再香也带着土腥味。咱们风场的数据也一样,SCADA、CMS、气象数据,这三样东西来源不同、格式不同、质量参差不齐,必须得好好拾掇拾掇。
核心观点:数据预处理不是“体力活”,而是决定故障诊断成败的“关键工序”。80%的根因分析错误,根源都在数据预处理阶段。
一、SCADA数据:风机的“体检报告”
SCADA系统,说白了就是风机的“黑匣子”。它每10分钟甚至1秒记录一次数据,包括风速、转速、功率、温度、电压、电流等等。我见过最夸张的一个风场,单台风机一天就能产生几十万条记录。
但这里有个坑——SCADA数据经常“缺胳膊少腿”。为什么?通信中断、传感器故障、存储溢出,原因多了去了。我记得在内蒙古一个风场,连续三天SCADA数据全是零,后来发现是交换机被老鼠咬断了线。
我的经验:拿到SCADA数据后,第一件事不是分析,而是检查时间戳是否连续。如果发现超过10%的时间点缺失,建议直接联系现场运维确认通信状态。
二、CMS数据:振动信号的“心电图”
CMS(状态监测系统)数据,主要来自齿轮箱、发电机、主轴等关键部件的振动传感器。这东西比SCADA精细得多,采样频率动辄几千赫兹。
但CMS数据有个特点——数据量巨大。一个风场几十台风机,每台风机十几个测点,一天下来就是几个GB。我刚开始做这行时,傻乎乎地全量存储,结果硬盘爆了三次。
处理CMS数据,我个人习惯分三步走:
- 降采样:把高频振动数据按分钟或小时聚合,提取有效值、峰值、峭度等特征
- 去噪:用带通滤波器滤掉工频干扰和低频晃动
- 对齐:把CMS数据的时间戳和SCADA对齐,不然分析时根本对不上号
注意:CMS数据中的“毛刺”不一定是故障信号,可能是传感器松动或电磁干扰。我曾经被一个松动的加速度计骗了整整两周,以为是齿轮箱早期故障,结果白跑一趟现场。
三、气象数据:风机的“天气预报”
气象数据包括风速、风向、温度、气压、湿度等。很多人觉得气象数据直接从气象站拿就行,其实没那么简单。
风场的气象数据有两个来源:机舱上的风速仪和测风塔。机舱风速仪受叶片尾流影响,测出来的风速往往偏低。测风塔数据准,但离风机远,存在空间差异。
我建议的做法是:用测风塔数据做基准,对机舱风速仪进行校正。具体方法可以用线性回归,也可以用更复杂的机器学习模型。但说实话,对于大多数故障诊断场景,简单的线性校正就够了。
四、数据清洗:把“垃圾”筛出去
数据清洗,说白了就是“去伪存真”。常见的脏数据包括:
- 重复记录:同一个时间点出现多条数据
- 格式错误:时间戳格式不统一、数值带单位字符
- 逻辑错误:风速为负值、功率大于额定功率两倍
- 死值:连续几十条记录数值完全不变(传感器卡死了)
我写过一个清洗脚本,核心逻辑就这几行:
# 伪代码示例:数据清洗核心逻辑
def clean_data(df):
# 1. 删除重复行
df = df.drop_duplicates(subset=['timestamp', 'device_id'])
# 2. 时间戳统一为UTC
df['timestamp'] = pd.to_datetime(df['timestamp'], utc=True)
# 3. 删除逻辑错误
df = df[(df['wind_speed'] >= 0) & (df['wind_speed'] < 50)]
df = df[(df['active_power'] >= 0) & (df['active_power'] <= 1.5 * rated_power)]
# 4. 检测死值:连续10个点数值不变,标记为异常
df['is_stuck'] = df.groupby('device_id')['value'].transform(
lambda x: x.rolling(10).std() == 0
)
return df[~df['is_stuck']]
五、缺失值处理:别让“空白”毁了分析
缺失值处理,是预处理里最让人头疼的。为什么?因为处理方式直接影响后续分析结果。
我总结了三类处理方法:
| 方法 | 适用场景 | 风险 |
|---|---|---|
| 直接删除 | 缺失比例<5%,且随机分布 | 丢失信息,可能引入偏差 |
| 均值/中位数填充 | 缺失比例5%-20%,数据平稳 | 降低方差,掩盖真实波动 |
| 插值法(线性/样条) | 缺失比例20%-40%,有趋势性 | 可能过度平滑,忽略突变 |
| 向前/向后填充 | 短时间缺失(<10分钟) | 不适用于长时间缺失 |
我个人最常用的是线性插值,尤其是处理SCADA数据中的短时间缺失。但要注意,如果缺失超过1小时,千万别用插值——那等于在编造数据。
避坑指南:我曾经处理一个齿轮箱温度数据,缺失了整整4个小时,我用插值法补上了。结果故障分析时,那个时间段正好是齿轮箱过温报警的临界点,插值把温度峰值给“抹平”了,导致漏判了故障。从那以后,超过1小时的缺失我坚决不插值,直接标记为“数据不可用”。
六、异常值检测:揪出“捣乱分子”
异常值检测,是预处理里最有技术含量的环节。异常值分两种:一种是“真异常”(传感器故障、通信错误),另一种是“假异常”(真实发生的极端工况,比如切出风速时的停机)。
常用的检测方法:
- 3σ原则:超出均值±3倍标准差的值视为异常。简单粗暴,但数据必须服从正态分布
- IQR方法:四分位距法,对非正态分布更鲁棒。超出Q1-1.5IQR或Q3+1.5IQR的值视为异常
- DBSCAN聚类:基于密度的聚类算法,能发现孤立点。适合多维数据
- 孤立森林:机器学习方法,适合高维数据
我一般先用IQR方法快速筛查,再用DBSCAN做精细检测。为什么?因为IQR快,适合海量数据;DBSCAN准,但计算量大。
# 伪代码:IQR异常检测
def detect_outliers_iqr(df, column):
Q1 = df[column].quantile(0.25)
Q3 = df[column].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
return df[(df[column] < lower_bound) | (df[column] > upper_bound)]
重要提醒:千万别把异常值一股脑全删了!先标记,再人工复核。我见过一个案例,运维把风机正常切出时的功率骤降当成异常值删了,结果后续的功率曲线分析完全失真。
七、数据对齐:让“三驾马车”步调一致
SCADA是分钟级数据,CMS是秒级甚至毫秒级数据,气象数据可能是小时级。这三者时间分辨率不同,必须对齐才能联合分析。
我的做法是:以SCADA数据的时间戳为基准,把CMS和气象数据“降采样”到同一时间粒度。具体来说:
- CMS数据:取每个SCADA时间点前后各30秒内的振动特征值(均值、峰值、峭度)
- 气象数据:取每个SCADA时间点前后各5分钟内的气象数据均值
这样对齐后,每条记录都包含SCADA参数、CMS特征、气象条件,形成一个完整的“数据快照”。
好了,数据采集与预处理就聊到这儿。记住一句话:数据预处理花的时间越多,后面故障诊断走的路越顺。别嫌麻烦,这是基本功。