数据预处理基础:缺失值处理、异常值检测、数据标准化与归一化

大家好,我是老周。今天咱们聊数据预处理——说白了就是让原始数据变得“干净”且“规整”。你想想看,模型吃进去的是垃圾,吐出来的肯定是垃圾。我在项目里吃过不少亏,所以这部分经验我特别想分享出来。

1. 缺失值处理

缺失值最让人头大。不是所有缺失都一样,我习惯先分清楚机制:

类型含义通俗理解
MCAR完全随机缺失缺失和任何变量都没关系,就像随手扔掉了几个值
MAR随机缺失(依赖于其他变量)比如收入缺失,但可能和职业、学历有关
MNAR非随机缺失缺失本身就隐含信息,比如高收入者故意不填

一般做法分两种:删和补。但直接删数据要慎重。

  • 删除法:dropna() 简单粗暴,但样本少时别乱用。我见过有人直接删掉30%的行,结果模型直接崩了。
  • 填充法:均值/中位数/众数填充最基础,但会改变分布。前向/后向填充适合时序数据。
  • 插值法:pandas的interpolate() 对连续性数据很友好。
  • 模型预测:KNNImputer、IterativeImputer 效果不错,但计算量大。我曾经在金融风控项目里用KNNImputer修复缺失字段,准确率提升了3个点。
import pandas as pd
from sklearn.impute import KNNImputer

df = pd.DataFrame({'A': [1, 2, None, 4], 'B': [5, None, 7, 8]})
imputer = KNNImputer(n_neighbors=2)
df_imputed = pd.DataFrame(imputer.fit_transform(df), columns=df.columns)
print(df_imputed)

我的习惯:先看缺失比例。大于50%的列直接扔掉,小于5%的用中位数填充,中间的尝试模型插值。记得填充前一定要分析缺失原因。

2. 异常值检测

异常值像老鼠屎,坏一锅汤。特别是线性模型和KNN这类对异常敏感的算法。

常用方法:

方法适用场景缺点
Z-score(3σ原则)近似正态分布对非正态分布不准
IQR(箱线图)任意分布,快速阈值固定(1.5倍IQR)
Isolation Forest高维数据,非线性需要调参
DBSCAN密度聚类异常检测对密度变化敏感

我个人习惯先用IQR快速扫一遍。有一次线上跑模型,发现预测值忽高忽低,查了半天原来是某个传感器数据串了,IQR直接把它标出来了。之后再拿Isolation Forest处理高维数据。

import numpy as np

def detect_outliers_iqr(data):
    Q1 = np.percentile(data, 25)
    Q3 = np.percentile(data, 75)
    IQR = Q3 - Q1
    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR
    return (data < lower_bound) | (data > upper_bound)

避坑指南:我曾经在电信用户流失预测中误把高价值用户当作异常值删除,后来发现那些高额消费客户恰恰是模型要识别的目标。所以先想想业务含义再动手。

3. 数据标准化与归一化

标准化和归一化是让不同量纲的特征“站到同一起跑线”。

方法公式输出范围适用场景
Z-score标准化 (StandardScaler)(x-μ)/σ均值0,标准差1数据近似正态分布,有异常值也建议Robust
MinMax归一化(x-min)/(max-min)[0, 1]有明确边界(如像素值0-255)
RobustScaler(x-中位数)/IQR更抗异常值数据包含异常值

记住一个铁律:先分割训练集和测试集,再对训练集fit transform,然后用训练集的参数transform测试集。我见过有人直接对整个数据集做标准化,结果模型在测试集上过拟合,因为包含了未来信息。

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

4. 处理顺序与协同

这三个步骤有先后逻辑。我建议:先处理缺失值,再检测异常值,最后做标准化或归一化。因为异常值检测时如果数据有缺失,很多方法会报错;而标准化前要保证数据完整。

数据预处理协同流程图 原始数据 缺失值处理 异常值检测 标准化 / 归一化

核心原则:数据预处理不是流水线式的死步骤,要根据业务和数据特点灵活组合。比如树模型对标准化不敏感,但缺失值和异常值依然要处理。

5. 实战避坑

  • 注意数据泄露:所有预处理参数(均值、标准差、异常阈值)都必须从训练集计算,不能全量计算。
  • 缺失值与异常值的顺序:我建议先处理缺失,再检测异常。因为缺失值可能本身就是异常。
  • 不要盲目删除异常值:先可视化分析,确认是否真的是噪声。有时候异常值恰恰是“金矿”。
  • 标准化后特征含义改变:比如身高标准化后变成了“身高偏离均值几个标准差”,对可解释性要求高的场景要小心。

我曾经踩过的坑:在某次销量预测项目中,我直接对时间序列做了MinMax归一化,忽略了未来最大值未知的问题。结果测试集的最大值远大于训练集,归一化后数值全部大于1,模型彻底崩溃。正确做法是用滚动窗口或业务理论最大值。