数据采集与预处理:SCADA数据、数据清洗、异常值处理

各位同学,咱们今天聊聊数据采集和预处理。说实话,这部分工作看着不起眼,但我在项目里吃过不少亏。你想想看,模型建得再漂亮,数据是脏的,结果全是白搭。所以这一章,我把自己踩过的坑、总结的经验,都摊开来跟你讲。

SCADA数据:风机的“黑匣子”

SCADA系统,说白了就是风机的“行车记录仪”。它每秒都在记录风速、功率、桨距角、转速这些参数。我刚开始接触时,觉得数据量太大,随便抽一点用就行。结果模型精度惨不忍睹。

后来我学乖了。SCADA数据有几个关键特征:

  • 时间戳:必须精确到秒,而且时区要统一。我遇到过某风场用UTC,另一个用北京时间,合并数据时差点崩溃。
  • 采样频率:通常是10分钟平均值。但注意,有些老风机是1分钟甚至更粗的粒度。我个人习惯先检查采样间隔,不一致的话要重采样。
  • 字段完整性:风速、有功功率、桨距角、发电机转速、机舱温度——这五个字段缺一不可。缺了任何一个,后面的功率曲线建模都别想做好。
核心要点:SCADA数据不是越多越好,而是越干净越好。我见过有人把几十个字段全塞进模型,结果过拟合得一塌糊涂。

数据清洗:把“垃圾”筛出去

数据清洗,听起来简单,做起来全是细节。我总结了一套“三步走”流程,你可以直接拿去用。

第一步:处理缺失值

风机停机、传感器故障、通信中断——这些都会导致数据缺失。我的处理原则是:

  • 连续缺失不超过3个点:用线性插值填充。比如风速从5m/s跳到7m/s,中间缺了一个点,我取平均值6m/s。
  • 连续缺失超过10个点:直接删除这段数据。为什么?因为插值会引入太多不确定性,反而污染模型。
  • 整段缺失超过1小时:标记为“停机时段”,单独处理。
我的小技巧:插值前先画个时序图。如果风速曲线是平滑的,插值没问题。如果锯齿状明显,说明传感器可能有问题,这时候别插值,直接删。

第二步:剔除重复数据

SCADA系统偶尔会重复记录。比如同一时刻出现两条一模一样的数据。我遇到过最夸张的一次,一个风场有3%的数据是重复的。

处理方法很简单:按时间戳去重,保留第一条。但注意,如果时间戳相同但数值不同,说明传感器冲突了。这时候我建议两条都删掉,因为无法判断哪个是对的。

第三步:处理时间戳异常

时间戳跳跃、倒流、或者出现未来时间——这些我都见过。我的做法是:

  • 时间戳倒流:直接删除该点及之后的数据,直到时间戳恢复正常。
  • 时间戳跳跃超过采样间隔的2倍:标记为“数据中断”,单独分析原因。
  • 未来时间戳:通常是系统时钟错误,直接删除。

异常值处理:揪出“捣乱分子”

异常值处理,是数据预处理里最考验经验的环节。我把它分成两类:物理异常和统计异常。

物理异常:一眼就能看出来的问题

比如风速显示-5m/s,或者功率超过额定功率的1.5倍。这些明显违反物理规律的数据,直接删除就行。

我常用的物理阈值:

参数 合理范围 异常处理
风速 0 ~ 35 m/s 超出直接删除
有功功率 0 ~ 额定功率×1.1 超出直接删除
桨距角 0° ~ 90° 超出直接删除
发电机转速 0 ~ 额定转速×1.2 超出直接删除
注意:别把“限功率运行”的数据当成异常删了。有些风场因为电网调度,会主动限制出力。这时候功率低于理论值,但数据是正常的。我建议先跟风场运营确认,再决定是否保留。

统计异常:用数据说话

物理异常好处理,统计异常就有点头疼了。比如风速10m/s时,功率突然掉到0。这可能是传感器故障,也可能是风机切出。怎么区分?

我常用的方法是“3σ原则”加“局部异常因子”:

  • 3σ原则:计算每个风速bin内的功率均值和标准差。功率超出均值±3σ的,标记为异常。这个方法简单粗暴,但有效。
  • 局部异常因子(LOF):如果数据点周围邻居很少,说明它是孤立的异常点。这个方法更精细,但计算量大。我一般只在关键分析时用。

举个例子,风速在8-9m/s这个区间,正常功率应该在200-300kW。如果出现一个点功率是500kW,那基本可以确定是异常。我会先查原始日志,确认是传感器问题后直接删除。

避坑指南:我曾经因为没做统计异常检测,模型在额定风速附近总是偏差很大。后来发现是几个“限功率”数据点没剔除,导致模型学偏了。从那以后,我每次建模前都会跑一遍异常检测。

数据预处理流程总览

说了这么多,我画了一张流程图,帮你把整个流程串起来。你一看就明白了。

数据预处理流程 原始SCADA数据 缺失值处理 连续缺失≤3 连续缺失>10 线性插值填充 直接删除该段 重复数据剔除 异常值处理

这张图把流程串起来了。你从原始数据开始,先处理缺失值,再剔除重复数据,最后处理异常值。每一步都有对应的处理方法,别跳步。

代码示例:快速上手

光说不练假把式。我给你一段Python代码,可以直接跑。这是我项目里常用的预处理函数,你拿去改改就能用。

import pandas as pd
import numpy as np

def preprocess_scada(df):
    """
    SCADA数据预处理函数
    df: 包含'风速', '有功功率', '时间戳'的DataFrame
    """
    # 1. 缺失值处理
    df = df.interpolate(method='linear', limit=3)  # 连续缺失≤3插值
    df = df.dropna(thresh=len(df.columns)-2)       # 缺失太多直接删
    
    # 2. 重复数据剔除
    df = df.drop_duplicates(subset=['时间戳'])
    
    # 3. 物理异常剔除
    df = df[(df['风速'] >= 0) & (df['风速'] <= 35)]
    df = df[(df['有功功率'] >= 0) & (df['有功功率'] <= 1500*1.1)]
    
    # 4. 统计异常剔除(3σ原则)
    for wind_bin in range(0, 36, 1):
        mask = (df['风速'] >= wind_bin) & (df['风速'] < wind_bin+1)
        bin_data = df.loc[mask, '有功功率']
        if len(bin_data) > 10:
            mean = bin_data.mean()
            std = bin_data.std()
            df = df.drop(mask & (abs(df['有功功率'] - mean) > 3*std))
    
    return df
使用建议:这段代码我用了好几年,基本没出过问题。但注意,3σ原则对非正态分布的数据效果不好。如果你发现异常点太多,试试用IQR方法(四分位距),有时候更稳健。

好了,数据预处理这部分就讲到这里。记住一句话:数据质量决定模型上限。你花80%的时间做预处理,剩下的20%建模,结果一定比反过来好。我在项目里验证过无数次了。


公众号:蓝海资料掘金营,微信deep3321