3、数据预处理基础:数据清洗、标准化与重采样

各位同行,大家好。我是老张,干风电运维这行有十几年了。今天咱们聊聊数据预处理。说实话,很多人觉得这步枯燥,不就是洗数据嘛。但我跟你说,这一步要是没做好,后面挖出来的全是垃圾。

我记得有一次,一个兄弟兴冲冲跑来说发现某台风机振动异常,结果我一查,是传感器掉线了,数据全是0。嗯,这就是典型的脏数据问题。所以,预处理不是走过场,是决定成败的关键。

3.1 数据清洗:把垃圾倒掉

数据清洗,说白了就是把那些「不靠谱」的数据揪出来。主要分两类:缺失值和异常值。

3.1.1 缺失值处理

风机SCADA系统里,缺失值太常见了。通讯中断、传感器故障、存储异常,都会导致数据断档。我个人习惯,先看看缺失比例。

  • 缺失比例 < 5%:直接删除该行。简单粗暴,但有效。
  • 缺失比例 5% - 20%:用插值法补全。比如线性插值、均值填充。
  • 缺失比例 > 20%:这列数据基本废了。我建议直接扔掉,别心疼。

避坑指南:我曾经遇到一个项目,某台风机功率曲线异常。查了半天,发现是风速仪结冰导致数据缺失,但系统自动用前一天的均值填充了。结果呢?完全掩盖了结冰故障。所以,填充前一定要搞清楚缺失原因。

代码示例,用pandas处理缺失值:

import pandas as pd
import numpy as np

# 读取数据
df = pd.read_csv('wind_turbine_data.csv')

# 查看缺失情况
print(df.isnull().sum())

# 删除缺失比例超过20%的列
df = df.dropna(thresh=len(df)*0.8, axis=1)

# 线性插值填充
df['wind_speed'] = df['wind_speed'].interpolate(method='linear')

# 均值填充(慎用)
df['temperature'] = df['temperature'].fillna(df['temperature'].mean())

3.1.2 异常值处理

异常值比缺失值更隐蔽。你想想看,风机功率突然飙到3000kW,但额定功率才2000kW,这明显有问题。我常用的方法有几种:

  • 3σ原则:超出均值±3倍标准差的数据,视为异常。
  • 箱线图法:超出上下四分位数1.5倍IQR的数据,视为异常。
  • 业务规则:比如风速不能为负,功率不能超过额定值。

我的经验:别完全依赖统计方法。有一次,箱线图把某台风机的正常停机数据标成了异常,差点误删。所以,一定要结合业务逻辑判断。

# 3σ法检测异常值
mean = df['power'].mean()
std = df['power'].std()
df_clean = df[(df['power'] > mean - 3*std) & (df['power'] < mean + 3*std)]

# 箱线图法
Q1 = df['power'].quantile(0.25)
Q3 = df['power'].quantile(0.75)
IQR = Q3 - Q1
df_clean = df[(df['power'] > Q1 - 1.5*IQR) & (df['power'] < Q3 + 1.5*IQR)]

3.2 数据标准化与归一化

为什么要做标准化?说白了,不同传感器的量纲不一样。风速是0-30m/s,温度是-20-50℃,功率是0-2000kW。如果不处理,模型会天然偏向数值大的特征。

我常用的两种方法:

方法 公式 适用场景
Z-score标准化 x' = (x - μ) / σ 数据近似正态分布,无上下界
Min-Max归一化 x' = (x - min) / (max - min) 数据有明确上下界,如功率、温度

注意:归一化后数据会压缩到[0,1]区间。但如果有极端异常值,会把正常数据挤到很小范围。我建议先做异常值处理,再做归一化。

from sklearn.preprocessing import StandardScaler, MinMaxScaler

# Z-score标准化
scaler = StandardScaler()
df['power_scaled'] = scaler.fit_transform(df[['power']])

# Min-Max归一化
scaler = MinMaxScaler()
df['wind_speed_norm'] = scaler.fit_transform(df[['wind_speed']])

3.3 时间序列数据重采样

风机SCADA数据通常是秒级或分钟级采集。但做故障诊断时,我们往往不需要这么高的频率。重采样就是把高频数据降为低频,比如从1分钟降为10分钟。

为什么要这么做?

  • 减少噪声:秒级数据抖动太大,掩盖了趋势。
  • 降低计算量:10分钟一个点,数据量只有原来的1/10。
  • 对齐不同数据源:有的传感器是1分钟,有的是5分钟,统一重采样才能一起分析。

我常用的重采样方法:

方法 说明 适用场景
均值重采样 取时间段内的平均值 功率、风速等平稳信号
最大值重采样 取时间段内的最大值 捕捉峰值,如振动冲击
最小值重采样 取时间段内的最小值 捕捉谷值,如低电压穿越
# 设置时间索引
df['timestamp'] = pd.to_datetime(df['timestamp'])
df = df.set_index('timestamp')

# 重采样为10分钟均值
df_10min = df.resample('10T').mean()

# 重采样为1小时最大值
df_1h = df.resample('1H').max()

# 重采样为1天最小值
df_1d = df.resample('1D').min()

我的习惯:做故障诊断时,我通常保留原始数据,同时生成多个重采样版本。比如,用10分钟均值看趋势,用1分钟最大值看冲击。不同尺度能发现不同问题。

3.4 本章知识体系

下面这张图,是我自己总结的数据预处理流程。你照着做,基本不会出大问题。

数据预处理核心流程 原始SCADA数据 数据清洗(缺失值 + 异常值) 标准化 / 归一化 时间序列重采样 干净可用的数据

嗯,以上就是数据预处理的核心内容。你可能会问,这些方法够用吗?说实话,够用。但真正的高手,是在实践中不断调整参数、优化流程。我建议你拿自己场站的数据跑一遍,遇到问题再回来翻翻这章。


专注资料整理