数据清洗为什么重要
数据科学界有句名言:垃圾进,垃圾出(Garbage In, Garbage Out)。无论你的分析模型多先进,输入脏数据只会得到错误结论。真实世界的数据集通常有10-30%的脏数据:缺失值、异常值、格式不一致、重复记录、编码错误。数据清洗通常占数据分析师60%的时间。用Pandas可以系统化、可复用地处理这些问题,比Excel手动操作快100倍。
第一步:数据加载与初步检查
拿到数据后第一步是了解数据全貌:
- 导入库:
import pandas as pd - 读取数据:
df = pd.read_csv('data.csv')或df = pd.read_excel('data.xlsx') - 查看前5行:
df.head() - 查看数据信息:
df.info()(显示列名、数据类型、非空值数量) - 查看描述性统计:
df.describe()(均值、标准差、最值、分位数) - 查看缺失值情况:
df.isnull().sum() - 查看数据形状:
df.shape(行数×列数) - 查看重复行数:
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方法(箱线图法)
- 计算Q1(25%分位数)和Q3(75%分位数)
- 计算IQR = Q3 – Q1
- 下界 = Q1 – 1.5 * IQR
- 上界 = Q3 + 1.5 * IQR
- 超出范围的为异常值
- 处理:删除、截断(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]
第四步:数据类型转换
错误的数据类型会导致分析出错:
- 查看类型:
df.dtypes - 字符串转数值:
df['price'] = df['price'].astype(float) - 字符串转日期:
df['date'] = pd.to_datetime(df['date']) - 处理混合格式日期:
pd.to_datetime(df['date'], format='mixed') - 数值转分类:
df['category'] = df['category'].astype('category')(节省内存) - 处理含非数字的数值列:
df['price'] = pd.to_numeric(df['price'], errors='coerce')(非数字转为NaN)
第五步:文本清洗
文本数据的脏数据最复杂,需要系统化清洗:
- 去除首尾空格:
df['name'] = df['name'].str.strip() - 统一大小写:
df['name'] = df['name'].str.title() - 替换特殊字符:
df['name'] = df['name'].str.replace('特殊字符', '替换值') - 用正则提取:
df['phone'] = df['text'].str.extract(r'([0-9]{11})')) - 分割列:
df[['first', 'last']] = df['name'].str.split(' ', expand=True) - 合并列:
df['full_name'] = df['first'] + ' ' + df['last']
第六步:重复值处理
重复数据会导致统计偏差:
- 查找完全重复的行:
df.duplicated().sum() - 查找特定列重复:
df.duplicated(subset=['email']).sum() - 删除重复行:
df = df.drop_duplicates() - 按关键字去重保留最后一条:
df = df.drop_duplicates(subset=['id'], keep='last') - 标记重复项:
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小时