第三章 数据采集与预处理:SCADA系统数据采集原理,数据清洗(缺失值、异常值处理),数据标准化与归一化方法

各位同行,咱们直接进入正题。数据采集与预处理,说白了就是风电后评估的“地基工程”。地基没打好,后面分析得再漂亮也是空中楼阁。我见过太多项目,模型跑得飞起,结果一查,原始数据里全是坑。今天咱们就把这块硬骨头啃下来。

3.1 SCADA系统数据采集原理

SCADA系统,全称是监控与数据采集系统。在风电场里,它就像人的神经系统,遍布全身。每个传感器就是一个神经末梢,把风速、转速、温度、电压、电流这些信号,源源不断地传回中控室。

我个人习惯把SCADA数据采集分成三个层级:

  • 现场层:传感器、变送器直接安装在风机上。比如机舱上的风速仪、齿轮箱上的振动传感器。它们把物理量转成电信号。
  • 控制层:风机的主控制器(PLC)负责收集这些信号。它按一定频率(比如1秒一次或10秒一次)轮询所有传感器。
  • 站控层:所有风机的数据通过光纤或无线网络汇总到中控室的服务器。这里的数据已经是处理过的,比如10分钟平均值。

这里有个关键点:采样频率。SCADA系统通常存储的是10分钟平均数据,但原始高频数据(比如1Hz)往往只保留一段时间。我在项目中遇到过,做振动分析时发现数据不够用,就是因为高频数据已经被覆盖了。所以,做后评估前,一定要先搞清楚你的数据是哪个层级的。

核心要点:SCADA数据采集的三大要素——采样频率、数据精度、存储周期。这三个参数直接决定了你能做什么分析。

另外,数据标签(Tag)的命名规范也很重要。不同厂家、不同机型,标签名千奇百怪。比如“风速”这个参数,有的叫“WindSpeed”,有的叫“WS”,还有的叫“WSPD_AVG”。我建议你在项目一开始就建立一份数据字典,把每个标签的含义、单位、范围都列清楚。否则后面光对数据就要花掉一半时间。

3.2 数据清洗:缺失值与异常值处理

数据清洗,说白了就是“去伪存真”。SCADA系统跑久了,什么稀奇古怪的数据都会出现。传感器漂移、通信中断、风机停机维护……这些都会导致数据质量问题。

3.2.1 缺失值处理

缺失值是最常见的问题。原因很多:传感器故障、网络丢包、风机停机时某些参数不采集等等。

处理缺失值,我一般按以下步骤来:

  1. 先诊断:看看缺失是随机的,还是成片出现的。如果是成片缺失,比如连续几天都没有数据,那很可能是风机停机了。这时候直接删除这段数据更合理。
  2. 再处理:对于零星缺失,常用的方法有:
    • 删除法:直接删掉缺失值所在的行。适用于缺失比例很小(比如<5%)的情况。
    • 填充法:用均值、中位数、前向填充或后向填充。我个人比较喜欢用线性插值,尤其是对于风速、功率这种连续变化的参数。
    • 模型预测法:用其他相关参数来预测缺失值。比如用风速和桨距角来预测功率。这个方法精度高,但计算量大。

我的经验:对于功率曲线分析,我建议直接删除缺失值。因为填充的数据会引入人为偏差,影响功率曲线的真实性。但对于温度、压力这种变化缓慢的参数,线性插值效果很好。

下面是一个简单的Python代码示例,演示如何用线性插值填充缺失值:

import pandas as pd
import numpy as np

# 假设df是包含风速和功率的DataFrame
# 风速列名为'wind_speed',功率列名为'power'

# 检查缺失值
print(df.isnull().sum())

# 对风速列进行线性插值
df['wind_speed'] = df['wind_speed'].interpolate(method='linear')

# 对功率列进行线性插值
df['power'] = df['power'].interpolate(method='linear')

# 或者,直接删除所有包含缺失值的行
df_clean = df.dropna()

3.2.2 异常值处理

异常值,就是那些明显不合理的数据点。比如风速显示-5m/s,或者功率超过额定功率的150%。

我曾经在一个项目里,发现某台风机在风速3m/s时功率竟然有800kW。这明显不对。后来一查,是功率传感器接线松了,导致信号漂移。

处理异常值,我常用的方法有:

  • 物理阈值法:根据设备参数设定合理范围。比如风速0-40m/s,功率0-额定功率的1.1倍。超出范围的直接剔除。
  • 统计方法:比如3σ原则(拉依达准则),或者箱线图(IQR)方法。对于正态分布的数据,3σ原则很有效。
  • 领域知识法:结合风机的运行状态来判断。比如风机在停机状态下,功率应该接近0。如果停机时功率还有几百kW,那肯定是异常。

注意:不要盲目剔除异常值。有些异常值可能反映了真实的故障信息。比如齿轮箱温度突然飙升,这可能是故障的前兆。在故障诊断分析中,这些“异常值”恰恰是最有价值的数据。

下面是用箱线图法检测异常值的代码:

# 使用IQR方法检测异常值
Q1 = df['power'].quantile(0.25)
Q3 = df['power'].quantile(0.75)
IQR = Q3 - Q1

# 定义异常值范围
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

# 标记异常值
df['is_outlier'] = (df['power'] < lower_bound) | (df['power'] > upper_bound)

# 剔除异常值
df_clean = df[df['is_outlier'] == False]

3.3 数据标准化与归一化方法

数据标准化和归一化,说白了就是把不同量纲的数据拉到同一个尺度上。比如风速的单位是m/s,功率的单位是kW,温度的的单位是℃。如果不做处理,直接扔进模型里,数值大的特征就会主导模型,数值小的特征就被淹没了。

我常用的方法有两种:

方法 公式 适用场景 特点
Min-Max归一化 X' = (X - X_min) / (X_max - X_min) 数据有明确边界,比如功率、风速 将数据映射到[0,1]区间,对异常值敏感
Z-score标准化 X' = (X - μ) / σ 数据近似正态分布,比如温度、振动 处理后均值为0,标准差为1,对异常值不敏感

我个人习惯:做功率曲线分析时,用Min-Max归一化。因为功率和风速都有明确的物理边界(风速0-40m/s,功率0-额定功率)。做故障预测时,用Z-score标准化。因为振动、温度这些参数,异常值往往意味着故障,用Z-score可以保留异常信息。

代码实现也很简单:

from sklearn.preprocessing import MinMaxScaler, StandardScaler

# Min-Max归一化
scaler_minmax = MinMaxScaler()
df[['wind_speed', 'power']] = scaler_minmax.fit_transform(df[['wind_speed', 'power']])

# Z-score标准化
scaler_zscore = StandardScaler()
df[['temperature', 'vibration']] = scaler_zscore.fit_transform(df[['temperature', 'vibration']])

避坑指南:我曾经犯过一个错误,把训练集和测试集的数据一起做归一化。结果模型在测试集上表现很好,但一上线就崩了。为什么?因为测试集的分布和训练集不一样。正确的做法是:先用训练集的数据计算归一化参数(比如均值和标准差),然后用这些参数去转换测试集。

3.4 本章知识体系总览

下面这张图,是我自己总结的数据采集与预处理的知识体系。你可以把它当作一个检查清单,做项目时对照着来。

数据采集与预处理知识体系 SCADA数据采集 数据清洗 数据标准化/归一化 采集原理 现场层 → 控制层 → 站控层 采样频率:1Hz / 10min平均 数据标签命名规范 清洗方法 缺失值:删除 / 插值 / 预测 异常值:阈值 / 统计 / 领域知识 注意:异常值可能包含故障信息 变换方法 Min-Max归一化:[0,1]区间 Z-score标准化:均值0,标准差1 注意:训练/测试集分开处理 高质量、可用的分析数据集 数据预处理是风电后评估的基石,直接决定分析结果的可靠性

嗯,到这里,数据采集与预处理的核心内容就讲完了。记住一句话:垃圾进,垃圾出。数据质量不过关,再牛的分析模型也是白搭。希望今天的分享能帮你少走一些弯路。