数据清洗与预处理:从原始数据到可用信息

大家好,我是老张。今天咱们聊聊数据清洗与预处理。说实话,这活儿看着不起眼,但在我十几年的数据分析生涯里,80%的项目翻车都栽在这一步。你想想看,数据都没整干净,后面分析得再花哨也是白搭。

核心观点:数据清洗不是体力活,而是信息优势的起点。脏数据进,脏决策出,这是铁律。

缺失值处理:别让空白毁了你的模型

缺失值,说白了就是数据表里的窟窿。我见过最夸张的项目,某个关键字段缺失率高达60%。当时客户还想直接建模,被我拦住了——这不是建模,这是算命。

常见的缺失值类型

  • 完全随机缺失(MCAR):缺失跟数据本身没关系,比如传感器偶尔抽风
  • 随机缺失(MAR):缺失跟其他变量有关,比如高收入人群更不愿意透露收入
  • 非随机缺失(MNAR):缺失跟自身值有关,比如温度计超过量程就爆表

我个人习惯,拿到数据先做缺失值热力图。一眼就能看出哪些字段是「重灾区」。

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# 加载数据
df = pd.read_csv('sensor_data.csv')

# 缺失值热力图
plt.figure(figsize=(12, 8))
sns.heatmap(df.isnull(), cbar=False, cmap='viridis')
plt.title('缺失值分布热力图')
plt.show()

# 统计缺失率
missing_rate = df.isnull().sum() / len(df) * 100
print(missing_rate.sort_values(ascending=False))

我的经验:缺失率低于5%的字段,直接删除行问题不大。超过30%的,你得认真想想这个字段到底要不要留。

缺失值处理方法

方法 适用场景 注意事项
删除法 缺失率低(<5%) 会损失样本量
均值/中位数填充 数值型、分布较对称 会降低方差
众数填充 分类型变量 可能引入偏差
前向/后向填充 时间序列数据 假设数据有连续性
插值法 有序数据 计算量较大
模型预测填充 缺失率较高 小心过拟合

嗯,这里要注意:千万别在测试集上用训练集的均值去填充。我曾经有个同事就这么干,结果模型上线后直接崩了——因为线上数据的分布跟训练集完全不一样。

异常值检测与处理:揪出那些「不听话」的数据点

异常值,就是数据里的「刺头」。它们可能是真实的事件,也可能是传感器故障。怎么区分?我教你几招。

常用检测方法

  1. Z-Score法:假设数据服从正态分布,Z-Score绝对值大于3的算异常
  2. IQR四分位距法:低于Q1-1.5*IQR或高于Q3+1.5*IQR的算异常
  3. 孤立森林:基于树模型的集成方法,适合高维数据
  4. DBSCAN聚类:密度聚类,孤立点自动归为噪声
from scipy import stats
import numpy as np

# Z-Score法
z_scores = np.abs(stats.zscore(df['temperature']))
outliers_z = df[z_scores > 3]

# IQR法
Q1 = df['temperature'].quantile(0.25)
Q3 = df['temperature'].quantile(0.75)
IQR = Q3 - Q1
outliers_iqr = df[(df['temperature'] < Q1 - 1.5*IQR) | 
                  (df['temperature'] > Q3 + 1.5*IQR)]

print(f'Z-Score发现异常值: {len(outliers_z)} 个')
print(f'IQR发现异常值: {len(outliers_iqr)} 个')

避坑指南:我曾经在金融风控项目里,直接用Z-Score把大额交易全标成了异常。结果呢?把真正的洗钱行为漏掉了。后来改用IQR+业务规则组合,才把准确率提上来。记住:统计方法只是工具,业务理解才是灵魂

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

为什么需要标准化?你想想看,年龄0-100,收入0-100万,这两个变量放在一起,收入直接碾压年龄。模型会以为收入最重要,其实不一定。

两种主流方法

方法 公式 输出范围 适用场景
Min-Max归一化 (x - min) / (max - min) [0, 1] 数据有明确边界
Z-Score标准化 (x - μ) / σ 均值为0,标准差为1 数据近似正态分布
from sklearn.preprocessing import MinMaxScaler, StandardScaler

# Min-Max归一化
scaler_minmax = MinMaxScaler()
df_normalized = pd.DataFrame(
    scaler_minmax.fit_transform(df[['age', 'income']]),
    columns=['age', 'income']
)

# Z-Score标准化
scaler_standard = StandardScaler()
df_standardized = pd.DataFrame(
    scaler_standard.fit_transform(df[['age', 'income']]),
    columns=['age', 'income']
)

print('归一化后:\n', df_normalized.describe())
print('标准化后:\n', df_standardized.describe())

我的建议:如果后续要用PCA、SVM、KNN这类对尺度敏感的算法,标准化是必须的。树模型(随机森林、XGBoost)倒是不太在意这个。

数据去重与一致性检查:别让重复数据骗了你

数据去重听起来简单,但坑不少。我见过一个电商项目,因为没处理好用户ID的重复问题,导致复购率算出来是120%。老板差点以为用户都在他家「进货」。

去重策略

  • 完全重复:所有字段都一样,直接删
  • 部分重复:关键字段相同,但其他字段有差异,需要合并或保留最新
  • 近似重复:比如「张三」和「张 三」,需要模糊匹配
# 完全去重
df_clean = df.drop_duplicates()

# 按指定列去重,保留最后一条
df_clean = df.drop_duplicates(subset=['user_id'], keep='last')

# 模糊去重(使用fuzzywuzzy)
from fuzzywuzzy import fuzz

def dedup_fuzzy(names, threshold=90):
    unique_names = []
    for name in names:
        if not any(fuzz.ratio(name, uniq) > threshold 
                   for uniq in unique_names):
            unique_names.append(name)
    return unique_names

一致性检查清单

  1. 数据类型检查:年龄字段里有没有「不详」这种字符串?
  2. 范围检查:温度有没有-999这种占位符?
  3. 逻辑检查:出生日期晚于死亡日期?这种数据必须揪出来
  4. 格式检查:手机号是不是11位?邮箱有没有@符号?

血的教训:我曾经在医疗项目里,没做日期一致性检查。结果分析出来「患者平均住院天数」是负数——因为出院日期比入院日期还早。后来花了整整两天重新清洗数据,从此以后,一致性检查成了我的「铁律」。

本章知识体系

下面这张图,是我自己总结的数据清洗全流程。每次做项目前,我都会对着它过一遍,确保没有遗漏。

数据清洗与预处理核心流程 原始数据 缺失值处理 异常值检测与处理 标准化与归一化 数据去重与一致性检查 清洗后数据 删除/填充/插值 Z-Score/IQR/孤立森林 Min-Max/Z-Score 完全去重/模糊匹配/逻辑校验 数据清洗不是一次性工作,而是迭代优化的过程

数据清洗这件事,说白了就是「磨刀不误砍柴工」。我见过太多人急着建模,结果被脏数据坑得欲哭无泪。记住:你花在清洗上的每一分钟,都会在后续分析中十倍回报给你

本章要点回顾:

  • 缺失值处理要区分类型,别一刀切
  • 异常值检测要结合业务,别迷信统计
  • 标准化和归一化选对方法,别乱用
  • 去重和一致性检查要细致,别偷懒

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