2. 数据采集与预处理:SCADA系统数据采集、数据清洗与异常值处理、数据归一化与标准化

各位工程师朋友,咱们直接进入正题。功率曲线分析这件事,说白了就是「垃圾进,垃圾出」。你采集的数据质量不行,后面再牛的算法也白搭。我见过太多项目,一上来就搞深度学习,结果数据里全是坏点,最后折腾几个月还不如老老实实把预处理做好。

这一章,我就把我在风电场摸爬滚打这些年积累的预处理经验,掰开了揉碎了讲给你听。

2.1 SCADA系统数据采集——源头决定一切

SCADA系统每10分钟记录一次数据,这是行业惯例。但你要注意,这个「10分钟」是平均值还是瞬时值?我踩过这个坑。

我记得有一次做某风电场的功率曲线分析,发现数据点特别散。查了半天才发现,SCADA配置里把「10分钟平均风速」和「10分钟最大风速」混在一起存了。你想想看,这俩数据能一样吗?

所以,采集数据前,先搞清楚这几个关键字段:

  • 时间戳:统一用UTC还是北京时间?我建议统一用UTC,避免跨时区问题。
  • 平均风速:10分钟平均值,单位m/s。
  • 有功功率:10分钟平均值,单位kW。
  • 桨距角:这个参数很多人忽略,但它对异常识别很有用。
  • 发电机转速:配合风速看,能发现很多问题。

核心要点:SCADA数据采集频率建议统一为10分钟间隔。如果遇到1分钟或1小时的数据,先做重采样处理。我个人习惯用pandas的resample功能,简单高效。

2.2 数据清洗与异常值处理——别让坏点毁了你的模型

数据清洗这块,我把它分成三步走。这三步走下来,基本能筛掉90%以上的异常数据。

2.2.1 第一步:剔除停机数据

风机停机时,风速可能很高但功率为零。这些数据点如果混进去,功率曲线会多出一条「尾巴」。怎么处理?

我的做法很简单:功率小于某个阈值(比如10kW)且风速大于切入风速(通常3m/s)的数据,直接剔除。

# 伪代码示例
import pandas as pd

# 假设df是原始数据
df_clean = df[(df['power'] > 10) | (df['wind_speed'] < 3)]

注意:不要一刀切地把所有功率为0的数据都删掉。风速低于切入风速时,功率为0是正常现象。我曾经犯过这个错误,把低风速段的正常数据全删了,结果功率曲线在低风速段直接断开了。

2.2.2 第二步:处理限功率数据

电网调度要求限功率运行时,风机会主动降低出力。这时候的数据点会偏离理论功率曲线。怎么识别?

我一般看两个指标:桨距角和发电机转速。如果桨距角明显偏大(比如大于5度),同时功率低于同风速下的理论值,那大概率是限功率了。

嗯,这里要注意:限功率数据要不要剔除?看你的分析目的。如果是做功率曲线认证,必须剔除。如果是做运行状态评估,可以保留并单独标记。

2.2.3 第三步:剔除传感器异常数据

风速计结冰、功率传感器漂移,这些情况在风电场太常见了。我遇到过最离谱的一次,某台风机风速计冻了整整一个冬天,SCADA记录的风速全是0.5m/s以下,但功率却有500kW。这种数据不删留着过年?

我的判断标准:

  • 风速为负值或超过切出风速(25m/s)且功率不为零 → 异常
  • 功率为负值 → 异常(除非是吸收无功的情况,但那是另一回事)
  • 风速变化率超过5m/s/10min → 可能是传感器抖动

小技巧:我习惯用3σ原则做初步筛选。先计算每个风速bin(比如0.5m/s一个bin)内的功率均值和标准差,然后剔除超出均值±3σ范围的数据点。这个方法简单粗暴,但很有效。

2.3 数据归一化与标准化——让不同风机站在同一起跑线

为什么要做归一化?说白了,不同风机的额定功率不一样。有的2MW,有的3MW。如果不做归一化,你没法直接比较它们的功率曲线。

我常用的方法有两种:

方法 公式 适用场景
Min-Max归一化 x' = (x - min) / (max - min) 功率数据,范围固定(0到额定功率)
Z-score标准化 x' = (x - μ) / σ 风速数据,分布未知时使用

我个人习惯:功率用Min-Max归一化,风速用Z-score标准化。为什么?功率的范围是确定的(0到额定功率),用Min-Max能保留物理意义。风速的分布可能偏态(比如有些风电场年平均风速低),用Z-score能消除这种偏差。

# Python代码示例
from sklearn.preprocessing import MinMaxScaler, StandardScaler

# 功率归一化
power_scaler = MinMaxScaler(feature_range=(0, 1))
df['power_norm'] = power_scaler.fit_transform(df[['power']])

# 风速标准化
wind_scaler = StandardScaler()
df['wind_std'] = wind_scaler.fit_transform(df[['wind_speed']])

避坑指南:我曾经在项目里直接用全局的Min-Max做归一化,结果发现新来的风机额定功率更大,导致之前归一化的数据全部需要重新计算。所以,建议先确定好所有风机的额定功率范围,再统一做归一化。或者,直接用额定功率做分母:x' = x / P_rated。这样更稳定。

2.4 本章知识体系总览

说了这么多,我画了一张图帮你梳理整个流程。从SCADA原始数据到最终可用的标准化数据,每一步都有坑,每一步也都有解法。

数据采集与预处理流程 SCADA数据采集 10分钟间隔,关键字段 数据清洗与异常值处理 ① 剔除停机数据 ② 处理限功率数据 ③ 剔除传感器异常 数据归一化与标准化 功率:Min-Max归一化 风速:Z-score标准化 标准化数据集 原始数据 清洗过程 特征工程 最终输出

这张图把整个流程串起来了。你照着这个流程走,预处理这块基本不会出大问题。当然,实际项目中总会遇到一些「惊喜」,比如某台风机SCADA系统突然抽风,连续三天数据全是NaN。这时候别慌,先检查通讯链路,再考虑用插值法补全短时间缺失的数据。

好了,数据预处理就讲到这里。记住一句话:预处理花的时间越多,后面分析就越省心。别急着跑模型,先把数据收拾利索了。


专注资料整理