数据预处理与清洗:让原始数据变得可靠
各位工程师朋友,大家好。今天我们来聊聊数据预处理与清洗。说实话,我在风电行业摸爬滚打这些年,见过太多因为数据没处理好导致模型翻车的案例。你想想看,风机载荷预测模型再牛,喂进去的是脏数据,出来的结果能信吗?
我个人习惯,拿到原始数据后,第一件事不是急着建模,而是先花 60% 的时间做数据清洗。这步省了,后面全是坑。
一、缺失值处理:别让空值毁了你的模型
风机SCADA数据里,缺失值太常见了。传感器故障、通信中断、存储异常……原因五花八门。我遇到过最夸张的一次,某风场连续3天的风速数据全是NaN,排查后发现是采集卡接触不良。
处理缺失值,我常用的方法就两种:
1. 插值法
说白了就是用已知数据去「猜」缺失的值。线性插值适合变化平缓的变量,比如环境温度。但风速这种波动大的,我建议用样条插值。
import pandas as pd
import numpy as np
# 线性插值
df['wind_speed'] = df['wind_speed'].interpolate(method='linear')
# 样条插值(二阶)
df['wind_speed'] = df['wind_speed'].interpolate(method='spline', order=2)
2. 前向填充
这个方法简单粗暴——用上一个有效值填充后面的缺失值。适合传感器短暂掉线的情况。比如叶片角度传感器偶尔丢一两个数据点,用前向填充问题不大。
# 前向填充
df['blade_angle'] = df['blade_angle'].fillna(method='ffill')
# 限制最多填充3个连续缺失
df['blade_angle'] = df['blade_angle'].fillna(method='ffill', limit=3)
二、异常值检测:揪出那些「离谱」的数据点
异常值是什么?就是那些明显不符合物理规律的数据。比如风速突然从10m/s跳到50m/s,或者发电机转速变成负数。这些数据不处理,模型学到的全是错误规律。
1. 3σ原则
这个方法假设数据服从正态分布。超出均值±3倍标准差的值,视为异常。简单好用,但有个前提——数据不能有太多离群点,否则均值和标准差本身就被污染了。
def detect_outliers_3sigma(data, col):
mean = data[col].mean()
std = data[col].std()
lower = mean - 3 * std
upper = mean + 3 * std
outliers = data[(data[col] < lower) | (data[col] > upper)]
return outliers
# 检测风速异常
outliers = detect_outliers_3sigma(df, 'wind_speed')
print(f"检测到 {len(outliers)} 个异常值")
实际案例:某次我处理一个风场的数据,用3σ检测发现大量风速异常。后来发现是台风过境期间的真实数据,不是传感器故障。所以,异常值不一定是「坏」数据,关键看上下文。
2. IQR方法
IQR(四分位距法)对数据分布不那么敏感,更稳健。它用Q1和Q3的差值来界定异常范围。我个人更偏爱这个方法,尤其是处理载荷数据时。
def detect_outliers_iqr(data, col):
Q1 = data[col].quantile(0.25)
Q3 = data[col].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
outliers = data[(data[col] < lower) | (data[col] > upper)]
return outliers
# 检测叶片弯矩异常
outliers = detect_outliers_iqr(df, 'blade_moment')
三、数据归一化与标准化:让不同量纲的数据「对话」
风速单位是m/s,载荷单位是kN·m,温度单位是℃。这些数据直接扔进模型,数值大的特征会主导学习过程。归一化和标准化就是解决这个问题的。
1. Min-Max归一化
把数据缩放到[0,1]区间。适合数据有明确边界的情况,比如风向角度(0-360°)。
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
df[['wind_speed', 'power']] = scaler.fit_transform(df[['wind_speed', 'power']])
2. Z-score标准化
把数据变成均值为0、标准差为1的分布。适合数据可能有异常值的情况,因为它不依赖最大值最小值。
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df[['blade_moment', 'tower_acceleration']] = scaler.fit_transform(
df[['blade_moment', 'tower_acceleration']]
)
四、时间序列重采样:统一数据的时间步长
风机SCADA数据采集频率经常不一致。有的传感器10Hz,有的1Hz,还有的按分钟记录。重采样就是把它们对齐到统一的时间频率上。
我常用的重采样策略:
| 重采样方式 | 适用场景 | 示例 |
|---|---|---|
| 降采样(聚合) | 高频数据转低频 | 10Hz → 1Hz,取均值 |
| 升采样(插值) | 低频数据转高频 | 1分钟 → 10秒,线性插值 |
| 对齐到整点 | 多源数据时间戳对齐 | 统一到整分钟时刻 |
# 降采样:10Hz数据聚合为1Hz(取均值)
df_resampled = df.resample('1S').mean()
# 升采样:1分钟数据插值为10秒
df_resampled = df.resample('10S').interpolate(method='linear')
# 对齐到整分钟
df_resampled = df.resample('1T', label='right', closed='right').mean()
好了,数据预处理这块就聊到这儿。这些方法看着简单,但真正用好需要大量实践。记住一句话:数据清洗花的时间,会在模型效果上加倍回报。
公众号:蓝海资料掘金营,微信deep3321