快速上手:使用 Pandas 进行数据清洗的实用教程
在数据分析和机器学习项目中,数据清洗通常占据大量时间。杂乱、不一致或缺失的数据会严重影响模型效果。Pandas 作为 Python 数据处理的核心库,提供了强大且高效的数据清洗工具。本文将带你从零开始,掌握使用 Pandas 进行数据清洗的关键技能。
简介
数据清洗是指发现并纠正数据文件中可识别错误的最后一道程序,包括检查数据一致性、处理无效值和缺失值等。一个干净、规整的数据集是后续分析的基石。Pandas 以其 DataFrame 数据结构为核心,集成了众多用于数据探索、转换和清洗的函数,是 Python 数据科学生态中不可或缺的一环。
前置准备
在开始之前,请确保你的环境已准备就绪。
- 安装 Python:建议安装 Python 3.8 或更高版本。
- 安装 Pandas:在终端或命令行中运行以下命令。
bash
pip install pandas - 安装 Jupyter Notebook(可选但推荐):它提供了一个交互式编程环境,非常适合数据探索。
bash
pip install notebook - 准备示例数据:我们将创建一个包含常见数据问题的模拟数据集。
为了获得更好的开发体验,一台性能不错的笔记本电脑会很有帮助。
步骤一:加载与初步探索数据
首先,我们需要将数据加载到 Pandas DataFrame 中。这里我们创建一个示例 DataFrame 来演示。
import pandas as pd
import numpy as np
# 创建一个包含典型数据问题的示例 DataFrame
data = {
'姓名': ['张三', '李四', '王五', np.nan, '赵六', '张三'],
'年龄': [25, 30, -5, 28, 100, 25],
'城市': ['北京', '上海', '北京 ', '广州', '上海', '北京'],
'注册日期': ['2023-01-10', '2023/02/15', '2023-3-20', '未知', '2023-05-01', '2023-01-10'],
'消费金额': ['¥500.0', '¥300', '€200', '¥150', '¥99.9', '¥500.0']
}
df = pd.DataFrame(data)
print("原始数据:")
print(df)
print("\n数据基本信息:")
df.info()
代码解读:df.info() 是探索性数据分析的第一步,它能告诉我们每列的数据类型、非空值数量以及内存使用情况。在我们的示例中,姓名 列有缺失值,年龄 列有异常值,注册日期 和 消费金额 的格式不统一。
步骤二:处理缺失值
缺失值是数据中最常见的问题。处理方法主要有删除和填充两种。
# 1. 查看缺失值情况
print("每列缺失值数量:")
print(df.isnull().sum())
# 2. 删除包含缺失值的行(谨慎使用,可能丢失大量数据)
df_dropped = df.dropna()
print("\n删除缺失值后的数据:")
print(df_dropped)
# 3. 用特定值填充缺失值(更常用)
# 用众数填充‘姓名’列
mode_name = df['姓名'].mode()[0] # mode() 返回一个Series,取第一个众数
df['姓名'] = df['姓名'].fillna(mode_name)
print("\n用众数填充‘姓名’后:")
print(df)
提示:对于数值型数据(如年龄、收入),常用均值、中位数填充;对于分类型数据(如城市、类别),常用众数填充。使用 inplace=True 参数可以直接在原 DataFrame 上修改。
步骤三:处理异常值与数据转换
异常值会扭曲分析结果,不一致的数据格式则需要统一转换。
# 1. 处理年龄列的异常值(负数和明显过大的年龄)
# 假设合理年龄范围为 0-100
df.loc[df['年龄'] < 0, '年龄'] = np.nan # 先将负年龄设为NaN
df.loc[df['年龄'] > 100, '年龄'] = np.nan # 再将过大年龄设为NaN
df['年龄'] = df['年龄'].fillna(df['年龄'].median()) # 用中位数填充
print("处理异常年龄后:")
print(df[['姓名', '年龄']])
# 2. 清洗和统一字符串格式(城市列)
df['城市'] = df['城市'].str.strip() # 去除前后空格
print("\n去除空格后的城市列:")
print(df['城市'])
# 3. 转换日期列格式
# 使用 to_datetime 函数,并设置 errors='coerce' 将无法解析的日期变为NaT
df['注册日期'] = pd.to_datetime(df['注册日期'], errors='coerce')
print("\n转换后的日期列:")
print(df['注册日期'])
print("日期列数据类型:", df['注册日期'].dtype)
一个全功能的机械键盘能显著提升你编写和调试代码的效率。
步骤四:处理重复数据与格式标准化
重复记录和非标准格式也是清洗的重点。
# 1. 查看并删除重复行
print("重复行数量:", df.duplicated().sum())
df = df.drop_duplicates()
print("\n删除重复行后:")
print(df)
# 2. 标准化“消费金额”列(去除货币符号并转换为浮点数)
# 使用正则表达式提取数字部分
df['消费金额'] = df['消费金额'].str.replace(r'[^\d.]', '', regex=True) # 只保留数字和小数点
df['消费金额'] = df['消费金额'].astype(float) # 转换为浮点数类型
print("\n标准化后的消费金额列:")
print(df['消费金额'])
# 3. 可选:创建新特征(例如从注册日期中提取年份)
df['注册年份'] = df['注册日期'].dt.year
print("\n新增注册年份列:")
print(df[['姓名', '注册日期', '注册年份']])
步骤五:导出清洗后的数据
完成所有清洗步骤后,将干净的数据保存到新文件中。
# 保存到新的 CSV 文件,不包含索引列
output_file = 'cleaned_data.csv'
df.to_csv(output_file, index=False, encoding='utf-8-sig') # 使用 utf-8-sig 编码防止中文乱码
print(f"\n清洗后的数据已保存到:{output_file}")
相关工具推荐
- Pandas:本文的核心工具,用于数据操作和清洗。
- NumPy:Pandas 底层的计算库,处理数值计算。
- Jupyter Notebook:交互式数据分析和可视化的优秀环境。
- Regex101:在线正则表达式测试工具,在处理复杂字符串时非常有用。
- VS Code:强大的代码编辑器,配合 Python 扩展,提供出色的开发体验。一台性能良好的台式电脑或笔记本电脑能流畅运行这些工具。
常见问题
Q1: 数据量很大时,Pandas 处理速度很慢怎么办?
A1: 可以考虑使用 dtype 参数在读取数据时指定列类型,减少内存占用。对于超大数据集,可以探索 Dask 或 Vaex 等支持 out-of-memory 计算的库。
Q2: 如何处理类别型数据中的多种写法(例如“北京”、“北京市”、“BJ”)?
A2: 使用 map 或 replace 方法创建一个映射字典,将不同写法统一到标准名称。例如:df['城市'] = df['城市'].map({'北京市': '北京', 'BJ': '北京', ...})。
Q3: 清洗后发现某些数据被误改了,如何回溯?
A3: 良好的实践是:不要直接修改原始数据。始终保留一份原始数据的副本。或者使用 copy() 方法创建 DataFrame 的副本进行清洗操作。在 Jupyter Notebook 中,可以重新运行单元格。
总结
数据清洗是数据科学项目中至关重要的一步,一个清晰、一致的数据集能大幅提升后续建模和分析的准确性与效率。本文通过一个具体的示例,演示了使用 Pandas 处理缺失值、异常值、重复数据、格式转换等常见数据问题的核心流程。记住,理解业务背景 是有效数据清洗的关键——什么算异常值,如何填充缺失值,往往需要结合具体业务场景来判断。
掌握这些 Pandas 技巧后,你可以将其应用于各种数据集,无论是从数据库导出、从API获取,还是通过网页抓取获得的原始数据。现在,就动手开始你的数据清洗实践吧!为你的工作空间添置一个高效的显示器也能让你更好地查看数据和代码。