您的位置:首页 > 手游攻略 > Pandas清洗数据和预处理的7种核心做法实用指南

Pandas清洗数据和预处理的7种核心做法实用指南

作者:互联网  时间: 2026-11-11 08:40:02  

平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“Pandas清洗数据和预处理的7种核心做法”来说,它看着像小点,放到项目里常会牵出环境、配置、兼容性和维护成本。下面按实际采用顺序,把思路、关键写法和容易踩坑的地方讲清楚,便于大家直接对照操作。

1. 缺失值处理

实际处理时,缺失值是数据清洗的首要问题,核心原则是「能填充不删除」,以下是不同场景的最优处理方案:

操作方法适用场景
删除缺失值dropna()缺失值占比极低(<5%)且无填充意义
固定值填充fillna(固定值)业务上有明确默认值(如未知性别填 'unknown')
统计值填充fillna(mean/median/mode)数值列(均值 / 中位数)、分类列(众数)
方向填充fillna(method='ffill/bfill')时序数据(如价格、传感器数据)
分组填充groupby + transform + fillna需按维度填充(如按地区填充该地区均值)

示例代码

import pandas as pd
import numpy as np
# 构造测试数据
df = pd.DataFrame({
    '地区': ['北京', '北京', '上海', '上海', '广州', '广州'],
    '销售额': [100, np.nan, 200, 150, np.nan, 300],
    '品类': ['家电', np.nan, '数码', '数码', '家电', '家电']
})
# 1. 删除缺失值(仅删除销售额列有缺失的行)
df_drop = df.dropna(subset=['销售额'])
# 2. 数值列用分组均值填充(按地区填充该地区销售额均值)
df['销售额'] = df.groupby('地区')['销售额'].transform(lambda x: x.fillna(x.mean()))
# 3. 分类列用众数填充
df['品类'] = df['品类'].fillna(df['品类'].mode()[0])
# 4. 时序数据方向填充(示例)
df_time = pd.DataFrame({'温度': [25, np.nan, 27, np.nan, 28]},
                       index=pd.date_range('2026-03-01', periods=5))
df_time['温度'] = df_time['温度'].fillna(method='ffill') # 前向填充

2. 重复数据处理

重复数据会导致分析结果偏差,重点是「精准识别 + 合理保留」:

操作方法说明
检测重复duplicated()得到布尔值,标记重复行
删除重复drop_duplicates()可指定列、保留规则

示例代码

# 构造测试数据
df = pd.DataFrame({
    'ID': [1, 1, 2, 3, 3],
    '姓名': ['张三', '张三', '李四', '王五', '王五'],
    '金额': [100, 200, 150, 300, 300]
})
# 1. 检测重复(默认全部列相同才视为重复)
df['是否重复'] = df.duplicated()
# 2. 按指定列检测重复(仅ID相同即视为重复)
df['ID重复'] = df.duplicated(subset=['ID'])
# 3. 删除重复行(保留第一次出现的行)
df_clean = df.drop_duplicates()
# 4. 按ID去重,保留金额最大的行(进阶用法)
df_clean = df.sort_values('金额', ascending=False).drop_duplicates(subset=['ID'], keep='first')

3. 数据类型转换

数据类型错误是隐性坑,需确保「类型匹配业务含义」:

操作方法适用场景
基础转换astype()数值 / 字符串 / 分类类型互转
数值转换pd.to_numeric()清洗非标准数值(如带逗号的 "1,000")
日期转换pd.to_datetime()字符串 / 数字转日期
分类类型astype('category')低基数分类列(如性别、地区)

示例代码

# 构造测试数据
df = pd.DataFrame({
    '年龄': ['25', '30', '未知'],
    '收入': ['5,000', '8,000', '10,000'],
    '日期': ['2026-03-01', '2026/03/02', '20260303'],
    '性别': ['男', '女', '男']
})
# 1. 字符串转数值(处理异常值)
df['年龄'] = pd.to_numeric(df['年龄'], errors='coerce') # "未知"转为NaN
df['收入'] = pd.to_numeric(df['收入'].str.replace(',', '')) # 去掉逗号再转数值
# 2. 字符串转日期(自动识别多种格式)
df['日期'] = pd.to_datetime(df['日期'])
# 3. 转为分类类型(节省内存,加速分组)
df['性别'] = df['性别'].astype('category')
# 4. 日期提取年/月/日(衍生字段)
df['年'] = df['日期'].dt.year
df['月'] = df['日期'].dt.month
df['星期'] = df['日期'].dt.dayofweek # 0=周一,6=周日

4. 数据重塑与变形

数据重塑用来调整数据结构,适配分析需求,核心是「长表↔宽表」转换:

操作方法适用场景
透视表pivot_table()聚合统计(如按地区 + 品类统计销售额)
长转宽pivot()单列多值转为多列
宽转长melt()多列转为键值对形式
堆叠 / 解堆stack()/unstack()层级索引转换

示例代码

# 构造测试数据
df = pd.DataFrame({
    '地区': ['北京', '北京', '上海', '上海'],
    '品类': ['家电', '数码', '家电', '数码'],
    '2025年': [100, 200, 150, 250],
    '2026年': [120, 220, 180, 280]
})
# 1. 宽转长(将年份列转为行)
df_long = df.melt(
    id_vars=['地区', '品类'], # 保留的标识列
    value_vars=['2025年', '2026年'], # 要转换的列
    var_name='年份', # 新列名(原列名)
    value_name='销售额' # 新值列名
)
# 2. 长转宽(恢复宽表)
df_wide = df_long.pivot(
    index=['地区', '品类'],
    columns='年份',
    values='销售额'
).reset_index()
# 3. 透视表(聚合统计)
df_pivot = df.pivot_table(
    index='地区',
    columns='品类',
    values=['2025年', '2026年'],
    aggfunc='sum' # 聚合方式
)

5. 文本数据处理

文本数据易出现格式混乱,需「标准化 + 提取关键信息」:

操作方法说明
格式标准化str.strip()/lower()/upper()去空格、统一大小写
替换 / 删除str.replace()清理特殊字符
拆分 / 合并str.split()/str.cat()拆分多值列、合并列
匹配 / 提取str.contains()/str.extract()筛选、提取关键信息

示例代码

# 构造测试数据
df = pd.DataFrame({
    '姓名': [' 张三 ', '李四 ', ' 王五'],
    '手机号': ['138-1234-5678', '139 9876 5432', '13788889999'],
    '地址': ['北京市朝阳区XX小区', '上海市浦东新区XX路', '广州市天河区XX街'],
    '爱好': ['篮球,足球', '读书,旅游', '跑步,游泳']
})
# 1. 格式标准化
df['姓名'] = df['姓名'].str.strip() # 去空格
df['地址'] = df['地址'].str.replace('市', '') # 去掉"市"字
# 2. 清理特殊字符
df['手机号'] = df['手机号'].str.replace('-', '').str.replace(' ', '') # 去掉横线和空格
# 3. 拆分多值列
df_hobby = df['爱好'].str.split(',', expand=True)
df_hobby.columns = ['爱好1', '爱好2']
df = pd.concat([df, df_hobby], axis=1)
# 4. 提取关键信息(从地址提取省份)
df['省份'] = df['地址'].str.extract('(北京|上海|广州)')
# 5. 筛选包含指定内容的行
df_bj = df[df['地址'].str.contains('北京')]

6. 数据分箱与离散化

将连续数值转为分类(如年龄分档、收入分级),适配统计 / 建模需求:

操作方法说明
等宽分箱pd.cut()区间宽度相同(如 0-20,20-40...)
等频分箱pd.qcut()每个区间样本数相同
自定义分箱pd.cut( bins=自定义列表 )按业务规则分箱

示例代码

# 构造测试数据
df = pd.DataFrame({
    '年龄': [18, 25, 32, 45, 58, 65, 72, 80],
    '收入': [3000, 8000, 15000, 25000, 50000, 80000, 100000, 150000]
})
# 1. 等宽分箱(年龄分为4个等宽区间)
df['年龄分档_等宽'] = pd.cut(df['年龄'], bins=4, labels=['青年', '中年', '中老年', '老年'])
# 2. 等频分箱(收入分为3个区间,每个区间样本数相同)
df['收入分档_等频'] = pd.qcut(df['收入'], q=3, labels=['低收入', '中收入', '高收入'])
# 3. 自定义分箱(按业务规则分年龄)
age_bins = [0, 18, 30, 50, 100]
age_labels = ['未成年', '青年', '中年', '老年']
df['年龄分档_自定义'] = pd.cut(df['年龄'], bins=age_bins, labels=age_labels, right=False)
# 4. 分箱后统计(各年龄档的收入均值)
df.groupby('年龄分档_自定义')['收入'].mean()

7. 其他常用转换

涵盖日常清洗中高频但未归类的操作:

示例代码

# 构造测试数据
df = pd.DataFrame({
    'A': [1, 2, 3, 4],
    'B': [10, 20, 30, 40],
    'C': ['a', 'b', 'a', 'b']
})
# 1. 列运算(创建新列)
df['A+B'] = df['A'] + df['B'] # 简单运算
df['A*B'] = df['A'] * df['B'] # 乘法
df['B/A'] = df['B'] / df['A'] # 除法
# 2. 映射替换(按字典替换值)
map_dict = {'a': '类别1', 'b': '类别2'}
df['C_映射'] = df['C'].map(map_dict)
# 3. 排序(按多列排序)
df_sorted = df.sort_values(by=['C', 'A'], ascending=[True, False])
# 4. 重置索引(清洗后索引不连续时)
df_reset = df_sorted.reset_index(drop=True)
# 5. 重命名列
df_rename = df.rename(columns={'A': '列1', 'B': '列2', 'C': '列3'})
# 6. 过滤行(按条件筛选)
df_filter = df[df['B'] > 20] # B列大于20的行

总结

  1. 核心逻辑:数据清洗的本质是「发现问题→针对性处理→适配分析需求」,以上 7 类方法覆盖 95% 以上的日常场景。
  2. 优先级:先处理缺失 / 重复值,再做类型转换,最后根据业务需求做重塑、分箱等进阶操作。
  3. 技巧:复杂清洗任务建议封装为函数,配合异常处理和日志,便于复用和排查问题。

相关资讯

最新游戏

更多

Copyright©2010-2019. All rights reserved | 波波三国游戏官网|[email protected]

备案编号:湘ICP备2022015115号-4