🧹 数据清洗基础

特征工程 · 实战课
⭐ 缺失值 · 重复数据 · 异常值 —— 让数据干净如新

📌 1. 处理缺失值 删除 · 填充 · 插值

🧽 删除缺失

  • dropna() — 直接丢弃含缺失的行/列
  • 适用于缺失比例极小 < 5%
  • ⚠️ 可能丢失有效信息
# 删除任何含有缺失的行
df.dropna(inplace=True)

# 删除缺失比例超过50%的列
df.dropna(thresh=len(df)*0.5, axis=1)

🧴 填充 & 插值

  • 固定值填充 (0, 均值, 中位数)
  • 前向/后向填充 (ffill / bfill)
  • 插值 (线性, 多项式, 样条)
# 均值填充
df['age'].fillna(df['age'].mean())

# 线性插值
df['temperature'].interpolate(method='linear')

# 前向填充
df['sales'].fillna(method='ffill')
原始缺失 插值填补

🔁 2. 处理重复数据 识别 & 删除

🔍 检测重复

  • df.duplicated() 返回布尔序列
  • df.duplicated(subset=['col1','col2'])
  • 查看重复行:df[df.duplicated()]

🗑️ 删除重复

  • df.drop_duplicates() 保留第一次出现
  • keep='last' 保留最后一次
  • keep=False 删除所有重复
# 删除完全重复的行
df.drop_duplicates(inplace=True)

# 基于特定列去重
df.drop_duplicates(subset=['user_id'], keep='first')
ID姓名年龄重复标记
101小美12✅ 唯一
102小智13⚠️ 重复 (第1次)
102小智13⚠️ 重复 (第2次)
103小刚11✅ 唯一

📊 3. 处理异常值 截尾 · 分箱 · 替换

✂️ 截尾 (Capping)

  • 将超出百分位数的值替换为边界值
  • 常用1% / 99% 或 IQR 法则
# IQR 截尾
Q1 = df['score'].quantile(0.25)
Q3 = df['score'].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5*IQR
upper = Q3 + 1.5*IQR
df['score'] = df['score'].clip(lower, upper)

📦 分箱 (Binning)

  • 将连续值离散化为类别
  • 等宽分箱 / 等频分箱 / 自定义
# 等宽分箱
pd.cut(df['age'], bins=3, labels=['少年','青年','成年'])

# 等频分箱
pd.qcut(df['income'], q=4, labels=['低','中低','中高','高'])

🔄 替换 (均值/中位数/众数)

  • 用统计量替换异常值,适合少量异常
  • 也可用前后值或模型预测替换
# 将异常值替换为中位数
median_val = df['price'].median()
df.loc[df['price'] > 10000, 'price'] = median_val
原始数据 截尾 分箱 替换 干净数据 异常值处理三大策略

📋 方法速查表 清洗决策

问题类型方法适用场景注意事项
缺失值删除缺失极少 <5%可能丢失信息
缺失值均值/中位数填充数值型,分布较对称可能降低方差
缺失值插值时间序列,有序数据计算成本略高
重复数据drop_duplicates完全重复或关键列重复确认保留规则
异常值截尾 (clip)极端值影响模型边界需合理
异常值分箱将连续值离散化可能损失精度
异常值替换少量明显错误避免引入偏差