人工智能之数据分析 Pandas:第六章 数据清洗 - 详解

人工智能之数据分析 Pandas

第六章 数据清洗



前言

数据清洗(Data Cleaning) 是数据分析中最关键、最耗时的环节,通常占整个分析流程的 60%~80% 时间。Pandas 提供了强大而灵活的工具来高效完成这项任务。

本文将从 缺失值、重复值、异常值、数据类型、格式标准化、文本清洗、列/行操作 等维度,系统、详细、实战化地介绍 Pandas 数据清洗的核心方法与技巧。


一、为什么需要数据清洗?

真实世界的数据往往存在以下问题:

  • 缺失值(NaN, NULL, 空字符串)
  • 重复记录
  • 错误或异常值(如年龄为 -5、工资为 1 亿)
  • 数据类型不一致(数字存为字符串)
  • 格式混乱(日期格式多样、单位不统一)
  • 噪声数据(乱码、特殊符号)
  • 列名/值命名不规范

目标:将“脏数据”转化为结构清晰、类型正确、逻辑合理、可直接用于分析的干净数据。


二、数据概览:清洗前的第一步

在动手清洗前,先全面了解数据:

import pandas as pd
import numpy as np
df = pd.read_csv('dirty_data.csv')
# 基本信息
print(df.shape)               # (行数, 列数)
print(df.dtypes)              # 每列类型
print(df.info())              # 非空计数 + 内存
print(df.describe())          # 数值列统计
print(df.head())              # 查看前几行
# 缺失值分布
print(df.isnull().sum())      # 每列缺失数量
print((df.isnull().sum() / len(df)) * 100)  # 缺失百分比
# 唯一值 & 频次(用于发现异常类别)
for col in df.select_dtypes(include='object').columns:
print(f"{col}:\n{df[col].value_counts(dropna=False)}\n")

三、处理缺失值(Missing Values)

1. 识别缺失值

Pandas 将以下视为缺失:

  • np.nan
  • None
  • pd.NaT(时间缺失)
  • 读取时通过 na_values 指定的值(如 'N/A', '-'
df.isnull()        # 返回布尔 DataFrame
df.isna()          # 同 isnull()

2. 处理策略与方法

策略方法适用场景
删除dropna()缺失比例高、无法填补
填充fillna()有合理填充值
插值interpolate()时间序列或有序数据
标记新增列标识是否缺失保留缺失信息用于建模

✅ 删除缺失

# 删除含任意缺失的行(默认)
df_clean = df.dropna()
# 删除所有值都缺失的行
df.dropna(how='all')
# 删除某列缺失的行
df.dropna(subset=['age'])
# 删除缺失超过阈值的列
df.dropna(axis=1, thresh=len(df)*0.8)  # 保留至少 80% 非空的列

✅ 填充缺失

# 填充固定值
df.fillna(0)                     # 数值填 0
df.fillna('Unknown')             # 分类填 'Unknown'
# 填充统计量
df['salary'].fillna(df['salary'].mean(), inplace=True)
df['city'].fillna(df['city'].mode()[0], inplace=True)  # 众数
# 前向/后向填充(时间序列常用)
df.fillna(method='ffill')   # forward fill
df.fillna(method='bfill')   # backward fill
# 按组填充(更合理!)
df['salary'] = df.groupby('department')['salary'].transform(
lambda x: x.fillna(x.mean())
)

✅ 插值(适用于连续变量)

df['temperature'].interpolate(method='linear')  # 线性插值
df['price'].interpolate(method='time')          # 按时间索引插值

建议:避免简单全局均值填充,优先考虑分组填充模型预测填充(如 KNNImputer)。


四、处理重复值(Duplicates)

1. 检测重复

# 全行重复
df.duplicated().sum()           # 重复行数
df[df.duplicated()]             # 查看重复行(保留首次出现)
# 指定列重复
df.duplicated(subset=['user_id'])

2. 删除重复

# 保留首次出现(默认)
df.drop_duplicates(inplace=True)
# 保留最后一次
df.drop_duplicates(keep='last', inplace=True)
# 基于特定列去重
df.drop_duplicates(subset=['email'], keep='first')

⚠️ 注意:去重前确认业务逻辑——有些“重复”可能是合法的(如多次购买记录)。


⚠️ 五、处理异常值(Outliers)

异常值 ≠ 错误值,需结合业务判断。

1. 检测方法

  • 统计法:3σ 原则(正态分布)、IQR(四分位距)
  • 可视化:箱线图、散点图
  • 领域规则:年龄 > 150?工资 < 0?

IQR 方法示例:

def detect_outliers_iqr(series):
Q1 = series.quantile(0.25)
Q3 = series.quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
return (series < lower) | (series > upper)
  outliers = detect_outliers_iqr(df['salary'])
  print(df[outliers])

2. 处理策略

策略方法
删除df[~outliers]
截断(Winsorize)用上下限值替换
转换对数变换 np.log(x)
保留若为真实极端值(如富豪收入)

截断示例:

upper_limit = df['salary'].quantile(0.95)
df['salary'] = np.where(df['salary'] > upper_limit, upper_limit, df['salary'])

六、数据类型修正

错误的数据类型会导致计算错误或内存浪费。

1. 常见问题

  • 数字被读成 object(因含非数字字符)
  • 日期未解析为 datetime
  • 整数含缺失 → 变为 float64

2. 修正方法

转换数值类型

# 强制转数字,错误变 NaN
df['price'] = pd.to_numeric(df['price'], errors='coerce')
# 指定整数类型(支持缺失)
df['user_id'] = df['user_id'].astype('Int64')  # 注意大写 I

解析日期

df['date'] = pd.to_datetime(df['date'], errors='coerce', format='%Y-%m-%d')
# 自动推断格式(慢但灵活)
df['date'] = pd.to_datetime(df['date'], infer_datetime_format=True)

优化内存(分类变量)

# 将低基数字符串转为 category
df['gender'] = df['gender'].astype('category')
df['city'] = df['city'].astype('category')
# 查看内存节省
df.info(memory_usage='deep')

七、格式标准化与单位统一

1. 字符串清洗(使用 .str 访问器)

# 去除空格
df['name'] = df['name'].str.strip()
# 大小写统一
df['email'] = df['email'].str.lower()
# 替换非法字符
df['phone'] = df['phone'].str.replace(r'\D', '', regex=True)  # 只留数字
# 提取模式
df['area_code'] = df['phone'].str[:3]
# 拆分列
df[['first', 'last']] = df['full_name'].str.split(' ', expand=True)

2. 单位统一

# 工资单位统一为“元”
df['salary'] = np.where(
df['salary_unit'] == '千元',
df['salary'] * 1000,
df['salary']
)

️ 八、列与行的结构调整

1. 重命名列

df.rename(columns={'old_name': 'new_name'}, inplace=True)
# 批量标准化列名
df.columns = df.columns.str.lower().str.replace(' ', '_')

2. 删除无用列

df.drop(['temp_col', 'id_backup'], axis=1, inplace=True)

3. 重排列顺序

df = df[['id', 'name', 'age', 'salary']]  # 指定顺序

4. 行过滤(基于业务规则)

# 年龄合理范围
df = df[(df['age'] >= 0) & (df['age'] <= 120)]
# 邮箱格式校验
df = df[df['email'].str.contains('@', na=False)]

九、清洗后验证

清洗不是一次性任务,需验证结果:

# 再次检查缺失
assert df.isnull().sum().sum() == 0, "仍有缺失值!"
# 检查类型
assert df['age'].dtype == 'int64'
assert df['date'].dtype == 'datetime64[ns]'
# 检查唯一性
assert df['user_id'].is_unique, "user_id 不唯一!"
# 保存清洗后数据
df.to_csv('clean_data.csv', index=False)

十、高级技巧与工具推荐

场景工具/方法
自动检测数据质量问题pandas-profiling(现 ydata-profiling
交互式清洗OpenRefine(外部工具)
复杂文本清洗正则表达式 + str.extract()
批量清洗多文件glob + 循环
可复现清洗流程封装为函数或使用 sklearnTransformer

示例:封装清洗函数

def clean_employee_data(df):
df = df.copy()
df.columns = df.columns.str.lower().str.replace(' ', '_')
df['salary'] = pd.to_numeric(df['salary'], errors='coerce')
df['age'] = pd.to_numeric(df['age'], errors='coerce')
df = df[(df['age'] >= 18) & (df['age'] <= 65)]
df['email'] = df['email'].str.lower().str.strip()
df = df.drop_duplicates(subset=['email'])
return df
clean_df = clean_employee_data(raw_df)

✅ 总结:数据清洗 Checklist

步骤操作
1️⃣ 概览shape, info(), isnull().sum()
2️⃣ 缺失值删除 / 填充 / 插值
3️⃣ 重复值drop_duplicates()
4️⃣ 异常值检测 + 截断/删除
5️⃣ 类型修正to_numeric, to_datetime, astype('category')
6️⃣ 格式标准化.str 方法清洗文本
7️⃣ 结构调整重命名、删列、重排序
8️⃣ 验证断言检查 + 保存

记住
“垃圾进,垃圾出”(Garbage In, Garbage Out)
再强大的模型也无法弥补脏数据带来的偏差。

后续

python过渡项目部分代码已经上传至gitee,后续会逐步更新。

资料关注

公众号:咚咚王
gitee:https://gitee.com/wy18585051844/ai_learning

《Python编程:从入门到实践》
《利用Python进行数据分析》
《算法导论中文第三版》
《概率论与数理统计(第四版) (盛骤) 》
《程序员的数学》
《线性代数应该这样学第3版》
《微积分和数学分析引论》
《(西瓜书)周志华-机器学习》
《TensorFlow机器学习实战指南》
《Sklearn与TensorFlow机器学习实用指南》
《模式识别(第四版)》
《深度学习 deep learning》伊恩·古德费洛著 花书
《Python深度学习第二版(中文版)【纯文本】 (登封大数据 (Francois Choliet)) (Z-Library)》
《深入浅出神经网络与深度学习+(迈克尔·尼尔森(Michael+Nielsen)》
《自然语言处理综论 第2版》
《Natural-Language-Processing-with-PyTorch》
《计算机视觉-算法与应用(中文版)》
《Learning OpenCV 4》
《AIGC:智能创作时代》杜雨+&+张孜铭
《AIGC原理与实践:零基础学大语言模型、扩散模型和多模态模型》
《从零构建大语言模型(中文版)》
《实战AI大模型》
《AI 3.0》

posted on 2026-01-06 17:28  ljbguanli  阅读(61)  评论(0)    收藏  举报