数据清洗与预处理:把脏数据变成可用的“原料”

数据清洗这事儿,说白了就是给数据“洗澡”。

我在工厂里见过太多人,拿到数据就直接建模、画图。结果呢?模型跑出来全是错的。你想想看,原料是坏的,做出来的菜能好吃吗?

这一章,我们就聊聊怎么把那些脏数据、乱数据、缺数据,变成能用的“好原料”。

为什么数据清洗这么重要?

生产溯源数据,来源特别杂。

  • 传感器采集的,可能有噪声
  • 人工录入的,可能有错别字
  • 系统对接的,可能有重复

我见过一个案例:某工厂的温控数据,因为传感器故障,连续三天报了 200°C。实际上生产线最高才 80°C。如果不处理,这个异常值会把整个分析结果带偏。

核心原则:数据清洗不是“删掉不好的数据”,而是“让数据真实反映生产过程”。

处理缺失值:数据里的“空洞”怎么办?

缺失值,就是数据表里那些空着的格子。原因很多:传感器没记录、工人忘了填、系统传输丢包。

常见的处理方法

方法 适用场景 我个人的建议
直接删除 缺失比例 < 5%,且随机分布 简单粗暴,但别滥用
均值/中位数填充 数值型数据,分布较稳定 生产数据常用,但会降低方差
前向/后向填充 时间序列数据 比如温度、压力,用前一时刻的值补
插值法 数据有趋势或周期性 线性插值、样条插值,精度更高
模型预测 缺失值较多,且与其他变量相关 用回归或KNN预测,但计算量大

我的经验:生产数据里,时间序列的缺失值,我一般先用前向填充。如果连续缺失超过3个点,再用插值。别一上来就用模型,太慢了。

异常值检测:揪出那些“不听话”的数据

异常值,就是明显偏离正常范围的数据点。可能是传感器故障、操作失误,也可能是真正的生产异常——后者恰恰是我们最关心的。

方法一:3σ原则(拉依达准则)

这个方法基于正态分布。数据在均值±3σ范围内的概率是99.73%。超出这个范围的,就算异常。

import numpy as np

def detect_outliers_3sigma(data):
    mean = np.mean(data)
    std = np.std(data)
    lower = mean - 3 * std
    upper = mean + 3 * std
    outliers = [x for x in data if x < lower or x > upper]
    return outliers, lower, upper

# 示例:某生产线日产量数据
daily_output = [120, 118, 122, 121, 119, 123, 117, 320, 121, 120]
outliers, low, up = detect_outliers_3sigma(daily_output)
print(f"异常值: {outliers}")
print(f"正常范围: [{low:.2f}, {up:.2f}]")

注意:3σ原则对数据分布敏感。如果数据本身不是正态分布,或者样本量太小(比如少于10个),这个方法会误判。我曾经在一个小批量试产项目里用过,结果把正常数据都标成异常了,尴尬得很。

方法二:IQR方法(四分位距法)

这个方法不依赖正态分布,更稳健。它用四分位数来定义正常范围。

def detect_outliers_iqr(data):
    q1 = np.percentile(data, 25)
    q3 = np.percentile(data, 75)
    iqr = q3 - q1
    lower = q1 - 1.5 * iqr
    upper = q3 + 1.5 * iqr
    outliers = [x for x in data if x < lower or x > upper]
    return outliers, lower, upper

# 同样的数据
outliers_iqr, low_iqr, up_iqr = detect_outliers_iqr(daily_output)
print(f"IQR异常值: {outliers_iqr}")
print(f"IQR正常范围: [{low_iqr:.2f}, {up_iqr:.2f}]")

你看,同样的数据,3σ把320标为异常,IQR也标为异常。但如果数据分布偏斜,IQR会更靠谱。

两种方法对比

特性 3σ原则 IQR方法
分布假设 正态分布 无严格假设
对极端值敏感度 高(极端值会拉偏均值和标准差) 低(基于中位数和分位数)
样本量要求 建议 > 30 建议 > 10
适用场景 质量稳定的批量生产 小批量、多品种、分布未知

我的习惯:拿到数据后,先用IQR快速扫一遍。如果发现异常值,再结合业务判断是“真异常”还是“假异常”。别一棍子打死,有些异常值恰恰是安全改进的线索。

数据标准化与归一化:让不同尺度的数据“对话”

生产数据里,温度可能是几十度,压力可能是几兆帕,产量可能是几百件。这些数据尺度不同,直接放一起分析,大尺度的变量会“吃掉”小尺度的变量。

标准化(Z-score标准化)

把数据变成均值为0、标准差为1的分布。公式:z = (x - μ) / σ

from sklearn.preprocessing import StandardScaler

data = [[100, 0.5], [120, 0.6], [110, 0.55], [130, 0.65]]
scaler = StandardScaler()
scaled_data = scaler.fit_transform(data)
print("标准化后的数据:")
print(scaled_data)

归一化(Min-Max归一化)

把数据缩放到[0, 1]区间。公式:x' = (x - min) / (max - min)

from sklearn.preprocessing import MinMaxScaler

scaler_mm = MinMaxScaler()
normalized_data = scaler_mm.fit_transform(data)
print("归一化后的数据:")
print(normalized_data)

什么时候用哪个?

场景 推荐方法 原因
数据有异常值 标准化 归一化会被异常值压缩正常数据
数据分布未知 标准化 更稳健,不依赖边界
需要保持稀疏性 归一化 标准化会破坏稀疏结构
神经网络输入 归一化 激活函数对[0,1]区间更友好
PCA、聚类等算法 标准化 需要均值为0,方差相等

避坑指南:我曾经在一个项目里,先做了异常值检测,然后才做标准化。结果标准化之后,异常值被“压缩”进了正常范围,后续分析完全没发现。正确的顺序是:先处理缺失值和异常值,再做标准化/归一化。

数据清洗与预处理流程总览

下面这张图,是我自己总结的流程。每次做数据清洗,我都会按这个顺序走一遍。

数据清洗与预处理流程 数据清洗与预处理流程 原始生产数据 缺失值处理 异常值检测 3σ原则 IQR方法 标准化 / 归一化 清洗后可用数据 关键顺序 ① 缺失值 → ② 异常值 ③ 标准化/归一化 顺序不能乱!

这个流程,我用了好多年。每次做数据清洗,都像在给生产线做“体检”。

最后说一句:数据清洗不是一次性的工作。生产环境在变,传感器在老化,工艺在调整。我建议你定期(比如每月)重新跑一遍清洗流程,看看数据质量有没有变化。这才是“持续改进”的体现。