模块三-数据清洗与预处理——14. 重复值处理
2026/5/14 5:28:07 网站建设 项目流程

14. 重复值处理

1. 概述

重复值是数据中的常见问题,可能来自数据录入错误、系统重复导出、数据合并等原因。重复数据会导致统计偏差、模型过拟合,需要在数据预处理阶段处理。

importpandasaspdimportnumpyasnp# 创建包含重复值的示例数据df=pd.DataFrame({'ID':[1,2,3,4,5,6,7,8,9,10],'姓名':['张三','李四','王五','张三','赵六','李四','钱七','张三','孙八','李四'],'年龄':[25,30,28,25,32,30,35,25,27,30],'城市':['北京','上海','广州','北京','深圳','上海','杭州','北京','成都','上海'],'工资':[8000,12000,10000,8000,15000,12000,11000,8000,9500,12000]})print("原始数据:")print(df)

2. 检测重复值

2.1 duplicated() 方法

duplicated()返回布尔 Series,True 表示重复(除第一次出现外)。

# 检测完全重复的行print("完全重复检测:")print(df.duplicated())# 查看重复行print("\n重复的行:")print(df[df.duplicated()])# 保留最后一次出现print("\n保留最后一次出现(标记第一次为重复):")print(df[df.duplicated(keep='last')])# 标记所有重复(包括第一次)print("\n标记所有重复:")print(df[df.duplicated(keep=False)])

2.2 指定列检测

# 基于指定列检测重复print("基于'姓名'列检测重复:")print(df.duplicated(subset=['姓名']))# 查看姓名重复的行print("\n姓名重复的行:")print(df[df.duplicated(subset=['姓名'])])# 基于多列检测print("\n基于'姓名'和'年龄'检测重复:")print(df.duplicated(subset=['姓名','年龄']))

3. 删除重复值

3.1 drop_duplicates() 基础

# 删除完全重复的行(保留第一次出现)print("删除完全重复:")df_dedupe=df.drop_duplicates()print(df_dedupe)print(f"删除前:{len(df)}行, 删除后:{len(df_dedupe)}行")# 保留最后一次出现print("\n保留最后一次出现:")print(df.drop_duplicates(keep='last'))# 删除所有重复(包括第一次)print("\n删除所有重复(只保留唯一值):")print(df.drop_duplicates(keep=False))

3.2 指定列删除

# 基于姓名列去重print("基于姓名去重:")print(df.drop_duplicates(subset=['姓名']))# 基于多列去重print("\n基于姓名和年龄去重:")print(df.drop_duplicates(subset=['姓名','年龄']))# 原地修改df_copy=df.copy()df_copy.drop_duplicates(inplace=True)print("\n原地修改后:")print(df_copy)

4. 重复值处理策略

4.1 聚合重复值

# 对重复值进行聚合(求和、均值等)print("按姓名聚合工资:")df_agg=df.groupby('姓名').agg({'年龄':'first','城市':'first','工资':'sum'}).reset_index()print(df_agg)# 保留最大值print("\n保留每个姓名的最大工资:")df_max=df.sort_values('工资',ascending=False).drop_duplicates(subset=['姓名'])print(df_max)# 保留最新记录(假设有日期列)# df_sorted = df.sort_values('日期', ascending=False).drop_duplicates(subset=['姓名'])

4.2 标记重复值

# 添加重复标记列df['是否重复']=df.duplicated(keep=False)print("添加重复标记:")print(df)# 添加重复次数print("\n添加重复次数:")df['重复次数']=df.groupby('姓名')['姓名'].transform('size')print(df)

5. 重复值统计

# 统计完全重复行数print(f"完全重复行数:{df.duplicated().sum()}")# 统计各列的重复情况forcolindf.columns:dup_count=df.duplicated(subset=[col]).sum()print(f"{col}列重复行数:{dup_count}")# 查看重复值的分布print("\n姓名重复次数:")print(df['姓名'].value_counts())# 查看重复行详细信息print("\n重复行详情:")dup_rows=df[df.duplicated(keep=False)].sort_values('姓名')print(dup_rows)

6. 完整示例:用户数据去重

# 创建用户数据np.random.seed(42)users=pd.DataFrame({'user_id':[1001,1002,1003,1001,1004,1002,1005,1001,1006,1002],'姓名':['张三','李四','王五','张三','赵六','李四','钱七','张三','孙八','李四'],'年龄':[25,30,28,25,32,30,35,25,27,30],'城市':['北京','上海','广州','北京','深圳','上海','杭州','北京','成都','上海'],'注册时间':pd.date_range('2024-01-01',periods=10,freq='D'),'消费金额':np.random.randint(100,1000,10)})print("="*60)print("用户数据去重处理")print("="*60)print("\n原始数据:")print(users)print("\n1. 重复检测:")print(f"完全重复行数:{users.duplicated().sum()}")print(f"user_id 重复行数:{users.duplicated(subset=['user_id']).sum()}")print(f"姓名重复行数:{users.duplicated(subset=['姓名']).sum()}")# 2. 查看重复用户print("\n2. 重复的用户:")dup_users=users[users.duplicated(subset=['user_id'],keep=False)].sort_values('user_id')print(dup_users)# 3. 按 user_id 去重(保留最新注册的)print("\n3. 按 user_id 去重(保留最新注册):")users_unique=users.sort_values('注册时间',ascending=False).drop_duplicates(subset=['user_id'])print(users_unique)# 4. 聚合重复用户数据print("\n4. 聚合重复用户:")users_agg=users.groupby('user_id').agg({'姓名':'first','年龄':'first','城市':'first','注册时间':'max','消费金额':'sum'}).reset_index()print(users_agg)# 5. 最终数据print("\n5. 最终去重后数据:")print(f"去重前:{len(users)}行")print(f"去重后:{len(users_unique)}行")

7. 重复值处理决策流程

发现重复值 │ ├─ 完全重复(所有列相同) │ │ │ └─ 直接删除,保留一条 │ ├─ 部分列重复(如 ID 相同但其他列不同) │ │ │ ├─ 需要合并信息 → 聚合(求和、均值、拼接) │ ├─ 需要保留最新 → 按时间排序后去重 │ ├─ 需要保留最完整 → 按完整度排序后去重 │ └─ 无法确定 → 标记后人工处理 │ └─ 业务逻辑决定 │ ├─ 用户 ID 必须唯一 → 基于 ID 去重 ├─ 订单号必须唯一 → 基于订单号去重 └─ 允许重复 → 保留

8. 常见陷阱

陷阱说明解决方案
大小写敏感‘张三’ 和 '张三 ’ 被视为不同先用str.strip()str.lower()标准化
浮点数精度1.0 和 1.0000001 被视为不同使用round()np.isclose()
缺失值NaN 与 NaN 不被视为重复先处理缺失值再去重
索引影响索引不同但数据相同也会去重使用ignore_index=True
# 处理大小写和空格print("\n处理大小写和空格:")df_name=pd.DataFrame({'姓名':['张三','张三 ',' 张三','李四','李四']})df_name['姓名_clean']=df_name['姓名'].str.strip().str.lower()print(df_name)print(f"清洗后重复:{df_name['姓名_clean'].duplicated().sum()}")

9. 总结

方法用途示例
duplicated()检测重复df.duplicated()
duplicated(keep='last')标记最后出现为重复df.duplicated(keep='last')
duplicated(keep=False)标记所有重复df.duplicated(keep=False)
duplicated(subset=[...])基于指定列检测df.duplicated(subset=['col1','col2'])
drop_duplicates()删除重复df.drop_duplicates()
drop_duplicates(keep='last')保留最后出现df.drop_duplicates(keep='last')
drop_duplicates(keep=False)删除所有重复df.drop_duplicates(keep=False)
drop_duplicates(subset=[...])基于指定列删除df.drop_duplicates(subset=['col1'])
groupby().agg()聚合重复值df.groupby('key').agg({'value':'sum'})

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询