本文目录导读:

数据清洗是数据分析中最耗时但最重要的环节,Python 的 Pandas 库是处理这类问题的首选工具。
以下我为你整理了 10 个高频且适合作为练习案例的数据清洗场景,每个都附带核心代码和解决思路。
处理缺失值
场景:数据集中有 NaN 或空字符串。
常见操作:
- 删除含有缺失值的行/列
- 填充缺失值(均值、中位数、众数、前向/后向填充)
核心案例:
import pandas as pd
import numpy as np
df = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': [5, np.nan, np.nan, 8],
'C': ['x', 'y', None, 'z']
})
# 1. 检查缺失值
print(df.isnull().sum())
# 2. 删除任何含有缺失值的行
df_drop = df.dropna()
# 3. 填充数值列用均值,类别列用众数
df['A'].fillna(df['A'].mean(), inplace=True)
df['C'].fillna(df['C'].mode()[0], inplace=True) # 众数可能有多个,取第一个
# 4. 前向填充(时间序列常用)
df['B'].fillna(method='ffill', inplace=True)
去除重复数据
场景:数据中存在完全重复或部分列重复的行。
核心案例:
df = pd.DataFrame({
'ID': [1, 2, 2, 3, 3],
'Name': ['Alice', 'Bob', 'Bob', 'Charlie', 'Charlie'],
'Age': [25, 30, 30, 35, 35]
})
# 1. 检查重复行
print(df.duplicated().sum())
# 2. 删除完全重复的行
df_unique = df.drop_duplicates()
# 3. 基于特定列去重(保留第一次出现的)
df_unique_id = df.drop_duplicates(subset=['ID'], keep='first')
# 4. 标记重复(用于审计)
df['is_duplicate'] = df.duplicated(subset=['ID'], keep=False)
数据类型转换
场景:日期列是字符串、数字列是对象类型、单位混用。
核心案例:
df = pd.DataFrame({
'date': ['2023-01-01', '2023/02/15', '20230320'],
'price': ['$100', '¥200', '300元'],
'age': ['25', '30', '三十五']
})
# 1. 统一日期格式(自动推断)
df['date'] = pd.to_datetime(df['date'], errors='coerce') # 无法解析的置为NaT
# 2. 去除货币符号并转为浮点数
df['price'] = df['price'].str.replace(r'[^\d.]', '', regex=True).astype(float)
# 3. 处理中文数字(需要映射字典)
age_map = {'二十五': 25, '三十': 30, '三十五': 35}
# 先用正则提取数字,若失败则用映射
# 简化方案:仅保留数字(会丢失'三十五')
df['age'] = pd.to_numeric(df['age'], errors='coerce') # '三十五' -> NaN
处理异常值
场景:年龄出现200岁、销售额为负数、超出3个标准差的数据。
核心案例:
import numpy as np
np.random.seed(42)
df = pd.DataFrame({'value': np.random.randn(100) * 50 + 100})
# 人为加入异常值
df.loc[0, 'value'] = 1000
df.loc[1, 'value'] = -500
# 1. 基于标准差(3σ原则)
mean = df['value'].mean()
std = df['value'].std()
df_no_outlier = df[(df['value'] >= mean - 3*std) & (df['value'] <= mean + 3*std)]
# 2. 基于四分位数(IQR)
Q1 = df['value'].quantile(0.25)
Q3 = df['value'].quantile(0.75)
IQR = Q3 - Q1
df_iqr = df[(df['value'] >= Q1 - 1.5*IQR) & (df['value'] <= Q3 + 1.5*IQR)]
# 3. 替换异常值为上下限(缩尾处理)
lower = Q1 - 1.5*IQR
upper = Q3 + 1.5*IQR
df['value'] = df['value'].clip(lower, upper)
字符串清洗(正则表达式)
场景:姓名首字母大写、去除多余空格、提取邮箱域名、手机号脱敏。
核心案例:
df = pd.DataFrame({
'name': [' alice ', 'BOB', 'Charlie '],
'email': ['alice@example.com', 'bob@test.org', 'charlie@company.com'],
'phone': ['138-1234-5678', '139 8765 4321', '021-12345678']
})
# 1. 去除空格 & 标题化
df['name'] = df['name'].str.strip().str.title()
# 2. 提取邮箱域名
df['domain'] = df['email'].str.split('@').str[1]
# 3. 手机号脱敏(保留前3后4)
df['phone_clean'] = df['phone'].str.replace(r'[^0-9]', '', regex=True)
df['phone_masked'] = df['phone_clean'].str.replace(r'(\d{3})\d{4}(\d{4})', r'\1****\2')
拆分及合并列
场景:全名列拆分为姓和名、地址拆分为省市、日期拆分为年月日。
核心案例:
df = pd.DataFrame({
'full_name': ['张三', '李四'],
'addr': ['上海市浦东新区', '北京市海淀区'],
'date': pd.to_datetime(['2023-01-15', '2024-06-20'])
})
# 1. 拆分列(中文无分隔符,需按字符长度,或使用正则)
df['last_name'] = df['full_name'].str[0]
df['first_name'] = df['full_name'].str[1:]
# 2. 拆分地址(提取省份)
df['province'] = df['addr'].str.extract(r'(.+?(?:省|市|自治区))')
# 3. 提取日期部件
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['day'] = df['date'].dt.day
统一文本格式(映射)
场景:性别包括“男/女/M/F/男性/女性”。
核心案例:
df = pd.DataFrame({
'gender': ['男', 'M', 'female', '女性', 'F', 'male']
})
# 1. 建立映射字典
gender_map = {
'男': 'M', 'M': 'M', 'male': 'M', 'Male': 'M',
'女': 'F', 'F': 'F', 'female': 'F', 'Female': 'F',
'男性': 'M', '女性': 'F'
}
df['gender_std'] = df['gender'].map(gender_map)
# 2. 检查映射是否完全(未映射的为NaN)
print(df['gender_std'].isnull().sum())
索引重置与排序
场景:删除行后索引不连续、需要按某列排序。
核心案例:
df = pd.DataFrame({'A': [3, 1, 2]}, index=[5, 2, 8])
# 1. 重置索引(从0开始,原索引变为列)
df_reset = df.reset_index()
# 2. 排序后重置索引
df_sorted = df.sort_values('A').reset_index(drop=True)
# 3. 按索引排序
df_indexed = df.sort_index()
合并与连接时去重
场景:两个数据表通过ID关联,但存在一对多关系导致笛卡尔积。
核心案例:
df1 = pd.DataFrame({'ID': [1, 2, 3], 'Name': ['A', 'B', 'C']})
df2 = pd.DataFrame({'ID': [1, 1, 2, 3], 'Score': [90, 95, 80, 70]})
# 1. 左连接(会重复行,因为ID=1在df2中有两条)
df_merged = df1.merge(df2, on='ID', how='left')
# 2. 若只需第一个匹配,先对df2去重
df2_first = df2.drop_duplicates(subset='ID', keep='first')
df_clean = df1.merge(df2_first, on='ID')
# 3. 或对结果进行聚合
df_agg = df1.merge(df2.groupby('ID', as_index=False)['Score'].mean(), on='ID')
数据透视与重塑
场景:宽表变长表(pivot→melt)、学生多门成绩转置。
核心案例:
# 宽表:每个学生一行,数学/语文/英语是列
df_wide = pd.DataFrame({
'name': ['Alice', 'Bob'],
'math': [90, 85],
'eng': [88, 92],
'chi': [95, 78]
})
# 1. 宽表转长表(melt)
df_long = df_wide.melt(id_vars=['name'],
value_vars=['math', 'eng', 'chi'],
var_name='subject',
value_name='score')
# 2. 长表转宽表(pivot)
df_back_wide = df_long.pivot(index='name', columns='subject', values='score').reset_index()
推荐练习的公开数据集
- Titanic(泰坦尼克号):经典的缺失值、属性编码、异常年龄清洗。
- 2015 Flight Delays(航班延误):时间格式、大面积缺失、分类编码。
- Instacart Market Basket(购物篮分析):重复订单、属性一致化、重采样。
- 自己收集的 CSV 数据(如商品详情页爬取):命名规范不一致、价格带符号、缺字段。
学习路径建议:先熟练掌握以上 10 个案例,然后找一个真实的脏数据集(如 Kaggle 上标记为 Data Cleaning 的比赛),完整跑一遍 EDA(探索性分析)前的工作。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播