数据预处理技术:缺失值处理、异常值检测、数据归一化与标准化
各位同仁,大家好。今天我们来聊聊数据预处理。
说实话,在风电场运维这个行当里,我见过太多人拿到数据就直接建模。结果呢?模型跑出来一塌糊涂。为什么?因为原始数据太「脏」了。传感器故障、通信中断、人为误操作……这些都会让数据变得不靠谱。
我个人习惯,拿到数据的第一件事,不是急着分析,而是先做预处理。这就像做饭前先洗菜切菜,虽然麻烦,但省不了。今天我们就重点讲三个最常用的技术:缺失值处理、异常值检测、数据归一化与标准化。
核心观点:数据预处理不是可选项,而是必选项。它直接决定了后续分析的成败。
一、缺失值处理
风电场的数据,缺失太常见了。我记得有一次做某风场的历史数据分析,发现风速传感器在某个时间段内连续缺失了3个小时的数据。后来一查,是传感器被冻住了。这种情况,你怎么办?
处理缺失值,主要有三种思路:
- 直接删除:如果缺失比例很小(比如低于5%),且是随机缺失,直接删掉整行或整列。简单粗暴,但有效。
- 填充:这是最常用的方法。填充方式有很多种:
- 均值/中位数填充:对于数值型特征,用该列的平均值或中位数填进去。我一般倾向于用中位数,因为它对异常值不敏感。
- 前向/后向填充:对于时间序列数据,比如风速、功率,用前一个时刻的值填充后一个时刻的缺失。这在风电场数据中很实用,因为物理量变化通常是连续的。
- 插值法:线性插值、样条插值等。精度更高,但计算量也大。
- 模型预测:用其他特征作为输入,训练一个模型来预测缺失值。比如用温度、湿度来预测缺失的风速。这个方法最复杂,但效果也最好。
我的经验:在风电场运维中,对于风速、功率这类关键参数,我建议优先使用前向填充或线性插值。因为物理量变化有惯性,前一个时刻的值往往是最合理的估计。
下面是一个简单的Python代码示例,演示如何使用pandas进行缺失值处理:
import pandas as pd
import numpy as np
# 创建一个示例数据
data = {'风速': [5.2, np.nan, 6.1, 5.8, np.nan, 6.5],
'功率': [1200, 1150, np.nan, 1300, 1250, 1400]}
df = pd.DataFrame(data)
# 查看缺失值
print(df.isnull().sum())
# 方法1:删除缺失值
df_drop = df.dropna()
# 方法2:用中位数填充
df_fill_median = df.fillna(df.median())
# 方法3:前向填充(时间序列常用)
df_fill_ffill = df.fillna(method='ffill')
# 方法4:线性插值
df_interpolate = df.interpolate(method='linear')
注意:千万不要在缺失值很多的情况下(比如超过30%)还强行填充。那样会引入大量噪声,还不如直接删除该特征。
二、异常值检测
异常值,说白了就是那些「不对劲」的数据点。比如风速突然从5m/s跳到了50m/s,这明显不合理。我曾经在某个项目中,发现一个风机的功率曲线图上有个「飞点」,功率高达额定值的两倍。后来一查,是数据采集卡的一个寄存器读错了。
异常值检测的方法有很多,我挑几个最常用的:
- 3σ原则:假设数据服从正态分布,超出均值±3倍标准差的数据点视为异常。简单,但要求数据近似正态分布。
- 箱线图法(IQR):用四分位距来识别异常。任何小于Q1-1.5*IQR或大于Q3+1.5*IQR的点,都算异常。这个方法不要求数据分布,更稳健。
- 基于模型的方法:比如孤立森林、LOF(局部异常因子)。适合高维数据,但需要调参。
在风电场场景中,我推荐先用箱线图法快速筛查。为什么?因为风速、功率这些数据往往不是严格的正态分布,用3σ原则容易误判。
来看一个箱线图法的代码示例:
# 使用IQR方法检测异常值
Q1 = df['风速'].quantile(0.25)
Q3 = df['风速'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# 标记异常值
df['风速_异常'] = (df['风速'] < lower_bound) | (df['风速'] > upper_bound)
# 查看异常值
print(df[df['风速_异常']])
避坑指南:我曾经犯过一个错误——把所有异常值都删掉了。后来发现,有些「异常值」其实是真实的极端工况,比如台风天气下的高风速。所以,检测出异常值后,一定要结合业务场景去判断,是删除、修正还是保留。
三、数据归一化与标准化
这个问题,很多新手容易搞混。归一化和标准化,到底有什么区别?
简单说:
- 归一化(Min-Max Scaling):把数据缩放到[0,1]区间。公式是 (x - min) / (max - min)。适合数据有明确边界的情况,比如图像像素值。
- 标准化(Z-score Scaling):把数据变成均值为0、标准差为1的分布。公式是 (x - mean) / std。适合数据近似正态分布的情况,很多机器学习算法(如SVM、神经网络)都要求输入数据标准化。
在风电场运维中,我个人的习惯是:如果后续要用到距离度量(比如KNN、聚类),优先用标准化。如果数据分布差异很大(比如风速0-30,温度-10-40),归一化会更合适。
代码示例:
from sklearn.preprocessing import MinMaxScaler, StandardScaler
# 归一化
scaler_minmax = MinMaxScaler()
df_normalized = scaler_minmax.fit_transform(df[['风速', '功率']])
# 标准化
scaler_std = StandardScaler()
df_standardized = scaler_std.fit_transform(df[['风速', '功率']])
重要提醒:归一化和标准化,一定要先拆分训练集和测试集,然后在训练集上fit,再transform测试集。千万不要对整个数据集一起做,否则会造成数据泄露,导致模型评估结果虚高。
知识体系框架
为了让大家更直观地理解这三部分的关系,我画了一张图:
这张图把整个流程串起来了。你想想看,原始数据进来,经过缺失值处理、异常值检测、归一化与标准化这三道工序,最后出来的才是能用的「干净数据」。
好了,关于数据预处理,我就讲这么多。记住一句话:数据预处理花的时间,永远值得。别急着建模,先把数据收拾利索了再说。
公众号:蓝海数据掘金营,微信deep3321