第2章 数据预处理实战:缺失值处理、异常值检测与数据标准化

大家好,我是老张。在风机运维这行摸爬滚打了十几年,我越来越觉得:数据预处理这事儿,看着不起眼,但真能决定你后面所有分析的成败。说白了,垃圾数据进,垃圾结果出。今天咱们就聊聊数据预处理的几个核心环节——缺失值处理、异常值检测、还有标准化归一化。

核心观点:数据预处理不是可有可无的“清洁工”,而是整个数据挖掘流程的“地基”。地基不稳,楼盖得再高也得塌。

数据预处理实战知识体系 数据预处理 缺失值处理 删除法 均值/中位数填充 插值法 异常值检测 3σ法则 IQR方法 箱线图 标准化与归一化 Z-score标准化 Min-Max归一化 RobustScaler

2.1 缺失值处理——别让“空”坑了你

风机运行数据里,缺失值太常见了。传感器故障、通信中断、存储异常……随便哪个环节出点问题,数据就空了。我遇到过最夸张的一次,某台风机连续3天的风速数据全是NaN,排查下来发现是采集模块的电源松了。

处理缺失值,我个人习惯先看缺失比例。如果某个特征缺失超过70%,我一般直接扔掉——补出来的数据也不靠谱。如果缺失不多,那就看情况处理。

常用的几种方法

  • 删除法:简单粗暴。缺失比例小的时候用,比如不到5%。但要注意,删除后样本量别太少。
  • 均值/中位数填充:数值型数据常用。风速、功率这些,用中位数填充更稳健,不容易被极端值带偏。
  • 插值法:时间序列数据的好选择。比如温度曲线,前后值线性插值,效果往往不错。

我的经验:处理风机功率数据时,我一般不用均值填充。因为功率和风速是非线性关系,用均值会引入偏差。我更喜欢用风速相近时刻的功率值来填充,或者用插值法。

import pandas as pd
import numpy as np

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

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

# 方法1:删除缺失比例超过70%的列
df = df.dropna(thresh=len(df)*0.3, axis=1)

# 方法2:用中位数填充数值列
numeric_cols = ['wind_speed', 'power_output', 'rotor_speed']
for col in numeric_cols:
    df[col].fillna(df[col].median(), inplace=True)

# 方法3:时间序列插值
df['temperature'].interpolate(method='linear', inplace=True)

2.2 异常值检测——揪出那些“捣乱分子”

异常值在风机数据里太常见了。传感器瞬间跳变、雷击干扰、叶片结冰……都会产生异常值。如果不处理,模型会被它们带偏。你想想看,一个异常点可能让均值偏移好几个百分点。

我常用的两种方法:3σ法则和IQR方法。它们各有适用场景。

2.2.1 3σ法则——适合正态分布的数据

3σ法则基于正态分布假设。数据落在均值±3个标准差之外的概率只有0.3%,这些点就可以视为异常。说白了,就是“小概率事件”原则。

但要注意,风机数据很多并不服从正态分布。比如风速数据,通常是威布尔分布。这时候用3σ法则会误判很多正常点。我曾经踩过这个坑,后来改用IQR方法了。

def detect_outliers_3sigma(data, col):
    mean = data[col].mean()
    std = data[col].std()
    lower_bound = mean - 3 * std
    upper_bound = mean + 3 * std
    outliers = data[(data[col] < lower_bound) | (data[col] > upper_bound)]
    return outliers

# 检测功率异常值
outliers_power = detect_outliers_3sigma(df, 'power_output')
print(f"检测到 {len(outliers_power)} 个异常点")

2.2.2 IQR方法——更稳健的选择

IQR方法不依赖正态分布假设。它用四分位距来定义异常边界:下边界是Q1 - 1.5*IQR,上边界是Q3 + 1.5*IQR。超出这个范围的就是异常。

我个人更推荐IQR方法处理风机数据。为什么?因为它对偏态分布更友好。风速、功率这些数据,用IQR方法很少误判。

避坑指南:我曾经用3σ法则处理风速数据,结果把很多正常的高风速点标记为异常。后来发现,风速分布是右偏的,3σ法则的上界太窄了。换成IQR方法后,问题就解决了。

def detect_outliers_iqr(data, col):
    Q1 = data[col].quantile(0.25)
    Q3 = data[col].quantile(0.75)
    IQR = Q3 - Q1
    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR
    outliers = data[(data[col] < lower_bound) | (data[col] > upper_bound)]
    return outliers

# 检测风速异常值
outliers_wind = detect_outliers_iqr(df, 'wind_speed')
print(f"IQR方法检测到 {len(outliers_wind)} 个异常点")

2.2.3 箱线图——可视化异常检测

箱线图是IQR方法的可视化版本。它能直观展示数据的分布和异常点位置。我每次做数据探索,第一件事就是画箱线图,一眼就能看出哪些特征有问题。

import matplotlib.pyplot as plt

# 绘制箱线图
plt.figure(figsize=(10, 6))
df[['wind_speed', 'power_output', 'rotor_speed']].boxplot()
plt.title('风机关键参数箱线图')
plt.ylabel('数值')
plt.show()

2.3 数据标准化与归一化——让数据“站在同一起跑线”

风机数据里,不同特征的量纲差异很大。风速是0-30m/s,功率是0-2000kW,温度是-20-50℃。如果不做标准化,模型会天然偏向数值大的特征。说白了,就是“以大欺小”。

我常用的两种方法:Z-score标准化和Min-Max归一化。选哪个?看你的模型需求。

2.3.1 Z-score标准化——适合有异常值的数据

Z-score标准化把数据变成均值为0、标准差为1的分布。公式很简单:z = (x - μ) / σ。它不改变数据的分布形状,只是缩放。

我个人习惯,如果后续要用线性模型或距离度量(比如KNN、SVM),我会用Z-score。因为它对异常值不那么敏感。

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
cols_to_scale = ['wind_speed', 'power_output', 'rotor_speed']
df[cols_to_scale] = scaler.fit_transform(df[cols_to_scale])

print("标准化后的均值:", df[cols_to_scale].mean().round(2))
print("标准化后的标准差:", df[cols_to_scale].std().round(2))

2.3.2 Min-Max归一化——适合有边界的数据

Min-Max归一化把数据缩放到[0,1]区间。公式:x_norm = (x - min) / (max - min)。它会把数据压缩到固定范围。

但要注意,Min-Max对异常值非常敏感。如果数据里有极端值,归一化后大部分数据会被压缩到很小的区间。嗯,这里要注意,用之前最好先处理异常值。

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
df[cols_to_scale] = scaler.fit_transform(df[cols_to_scale])

print("归一化后的最小值:", df[cols_to_scale].min().round(2))
print("归一化后的最大值:", df[cols_to_scale].max().round(2))

2.3.3 RobustScaler——抗异常值的标准化

还有一种方法叫RobustScaler,它用中位数和四分位距来缩放。公式:x_robust = (x - median) / IQR。它对异常值非常稳健。

我在处理风机振动数据时特别喜欢用这个方法。振动数据经常有突发性的尖峰,用Z-score会被带偏,用RobustScaler就稳多了。

from sklearn.preprocessing import RobustScaler

scaler = RobustScaler()
df[cols_to_scale] = scaler.fit_transform(df[cols_to_scale])

总结一下我的选择原则:

场景 推荐方法 原因
数据近似正态分布 Z-score标准化 保持分布形态,适合线性模型
数据有明确边界 Min-Max归一化 适合神经网络等需要固定输入范围的模型
数据含较多异常值 RobustScaler 抗异常值能力强,结果稳定
不确定分布情况 IQR方法+RobustScaler 最稳健的组合,适合风机数据

好了,数据预处理这块就聊到这儿。记住一句话:预处理做得好,后面分析事半功倍。别嫌麻烦,这一步省下的时间,后面会加倍还回来。


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