数据清洗为什么重要

数据科学界有句名言:垃圾进,垃圾出(Garbage In, Garbage Out)。无论你的分析模型多先进,输入脏数据只会得到错误结论。真实世界的数据集通常有10-30%的脏数据:缺失值、异常值、格式不一致、重复记录、编码错误。数据清洗通常占数据分析师60%的时间。用Pandas可以系统化、可复用地处理这些问题,比Excel手动操作快100倍。

第一步:数据加载与初步检查

拿到数据后第一步是了解数据全貌:

  1. 导入库:import pandas as pd
  2. 读取数据:df = pd.read_csv('data.csv') 或 df = pd.read_excel('data.xlsx')
  3. 查看前5行:df.head()
  4. 查看数据信息:df.info()(显示列名、数据类型、非空值数量)
  5. 查看描述性统计:df.describe()(均值、标准差、最值、分位数)
  6. 查看缺失值情况:df.isnull().sum()
  7. 查看数据形状:df.shape(行数×列数)
  8. 查看重复行数:df.duplicated().sum()

初步检查清单:

  • 列名是否规范(有无空格、特殊字符)
  • 数据类型是否正确(日期是否为datetime,数字是否为float/int)
  • 缺失值比例是否可接受
  • 是否有明显的异常值(最大值/最小值是否合理)

第二步:缺失值处理

缺失值是最常见的数据问题,处理策略取决于缺失原因和数据量:

策略1:删除缺失值(数据量充足时)

  • 删除含缺失值的行:df.dropna()
  • 删除全为空的列:df.dropna(axis=1, how='all')
  • 删除缺失值超过50%的行:df.dropna(thresh=len(df)*0.5)
  • 适用:缺失比例低于5%且数据量大

策略2:填充固定值

  • 数值列填充0:df['column'].fillna(0)
  • 文本列填充默认值:df['column'].fillna('未知')
  • 适用:缺失值有明确含义(如0表示无交易)

策略3:填充统计值

  • 填充均值:df['column'].fillna(df['column'].mean())
  • 填充中位数:df['column'].fillna(df['column'].median())
  • 填充众数:df['column'].fillna(df['column'].mode()[0])
  • 适用:数值型数据,分布较均匀

策略4:分组填充

  • 按分组填充:df['column'].fillna(df.groupby('category')['column'].transform('mean'))
  • 适用:不同分组的缺失值应该用该组的统计值填充

策略5:插值法

  • 线性插值:df['column'].interpolate(method='linear')
  • 时间序列插值:df['column'].interpolate(method='time')
  • 适用:时间序列数据,缺失值前后有趋势

第三步:异常值检测与处理

异常值会严重干扰分析结果,需要识别和处理:

方法1:IQR方法(箱线图法)

  1. 计算Q1(25%分位数)和Q3(75%分位数)
  2. 计算IQR = Q3 – Q1
  3. 下界 = Q1 – 1.5 * IQR
  4. 上界 = Q3 + 1.5 * IQR
  5. 超出范围的为异常值
  6. 处理:删除、截断(clip到边界)、或标记后单独分析

代码:用 Q1 = df['col'].quantile(0.25) 和 Q3 = df['col'].quantile(0.75) 计算分位数,IQR = Q3 – Q1,然后 df = df[(df['col'] >= Q1-1.5*IQR) & (df['col'] <= Q3+1.5*IQR)] 过滤异常值。

方法2:Z-score方法

  • 计算Z-score = (值 - 均值) / 标准差
  • Z-score绝对值大于3为异常值
  • 适用:数据近似正态分布

方法3:业务规则

  • 年龄不能为负数或超过150
  • 价格不能为负数
  • 日期不能在未来
  • 用条件筛选处理:df = df[df['age'] > 0]

第四步:数据类型转换

错误的数据类型会导致分析出错:

  1. 查看类型:df.dtypes
  2. 字符串转数值:df['price'] = df['price'].astype(float)
  3. 字符串转日期:df['date'] = pd.to_datetime(df['date'])
  4. 处理混合格式日期:pd.to_datetime(df['date'], format='mixed')
  5. 数值转分类:df['category'] = df['category'].astype('category')(节省内存)
  6. 处理含非数字的数值列:df['price'] = pd.to_numeric(df['price'], errors='coerce')(非数字转为NaN)

第五步:文本清洗

文本数据的脏数据最复杂,需要系统化清洗:

  1. 去除首尾空格:df['name'] = df['name'].str.strip()
  2. 统一大小写:df['name'] = df['name'].str.title()
  3. 替换特殊字符:df['name'] = df['name'].str.replace('特殊字符', '替换值')
  4. 用正则提取:df['phone'] = df['text'].str.extract(r'([0-9]{11})'))
  5. 分割列:df[['first', 'last']] = df['name'].str.split(' ', expand=True)
  6. 合并列:df['full_name'] = df['first'] + ' ' + df['last']

第六步:重复值处理

重复数据会导致统计偏差:

  1. 查找完全重复的行:df.duplicated().sum()
  2. 查找特定列重复:df.duplicated(subset=['email']).sum()
  3. 删除重复行:df = df.drop_duplicates()
  4. 按关键字去重保留最后一条:df = df.drop_duplicates(subset=['id'], keep='last')
  5. 标记重复项:df['is_dup'] = df.duplicated(subset=['email'])(用于审查而非删除)

常见问题与误区

  • 盲目删除缺失值:如果缺失值有特殊含义(如未填写=不适用),删除会丢失信息。先理解缺失原因
  • 异常值一刀切删除:有些异常值是真实数据(如大客户的交易额)。先标记再决定是否删除
  • 类型转换报错:用errors='coerce'参数将无法转换的值变为NaN而非报错
  • 文本编码问题:读取文件时指定encoding='utf-8'或encoding='gbk'
  • 内存不足:大数据集用dtype='category'转换文本列,或用chunksize分块读取
  • 修改未生效:Pandas默认返回新对象。需要 inplace=True 或重新赋值 df = df...

效率数据

  • 清洗效率:Excel处理10万行数据约2小时 → Pandas约30秒
  • 缺失值处理:5种策略一次编写,可复用于所有数据集
  • 异常值检测:IQR方法一行代码检测,比Excel条件格式快100倍
  • 文本清洗:正则表达式批量提取,比手动查找替换快50倍
  • 某数据分析团队实测:标准化清洗流程后,数据准备时间从每周10小时 → 2小时