当前位置: 首页 > news >正文

模块三-数据清洗与预处理——14. 重复值处理

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'})

http://www.jsqmd.com/news/813386/

相关文章:

  • PostgreSQL进程僵局:从死循环到优雅终止的深度剖析
  • 手机市场饱和下的细分突围:从功能过剩到场景化专用设备
  • Windows XP图标主题完整指南:在现代Linux系统上重现经典视觉体验
  • 从淘宝几块钱的2804云台电机开始,手把手教你DIY一个桌面机械臂关节(STM32/GD32 + SimpleFOC)
  • 2026年比较好的老家轻钢别墅/自住轻钢别墅/独栋轻钢别墅热门公司推荐 - 行业平台推荐
  • STM32H7串口DMA+空闲中断实战:告别频繁中断,实现稳定长数据接收(附双缓冲代码)
  • 量子电路编译与Trotter分解技术详解
  • 基于LLM与多智能体架构的科研文献检索系统设计与实现
  • 保姆级教程:手把手教你用SOEM的eepromtool.c读写EtherCAT从站EEPROM(附完整代码解析)
  • LeetCode 22. 括号生成
  • 深入解析tausik-core:构建高性能微服务通信核心的设计与实践
  • ncmdumpGUI:3步完成网易云音乐NCM文件格式转换的终极指南 [特殊字符]
  • 构建AI安全测试框架:从越狱攻击到自动化评估实践
  • Python类型转换陷阱:从ValueError: invalid literal for int() with base 10说开去
  • 给芯片设计新人的DFT DRC避坑指南:从RTL到Post-DFT的完整检查清单
  • Spring Boot 3.x 集成AD域实战:从SSL证书踩坑到密码重置,一篇讲透
  • Sveltos:多集群Kubernetes应用分发与配置管理的核心利器
  • 让老旧PL-2303串口设备在Windows 10/11重获新生的终极指南
  • 模块三-数据清洗与预处理——15. 异常值检测与处理
  • 手把手教你用Vivado配置Xilinx ERNIC IP,实现FPGA上的RoCE v2硬件加速
  • 别只会改设置!Chrome/Edge浏览器主页被劫持的三种隐藏原因与根治方法
  • 深入GD32F407时钟树:对比STM32F4,聊聊国产MCU时钟设计的异同与调试技巧
  • wangEditor 粘贴 Word 图文混合内容的完整解决方案与避坑指南
  • OAuth 2.0与动态路由集成:构建安全、智能的API网关实践
  • LeetCode 70. 爬楼梯
  • PvZ Toolkit终极指南:如何快速上手植物大战僵尸PC版最强修改器
  • 2026年知名的全案设计/设计工作室/南充装修设计/南充别墅设计装修行业公司推荐 - 品牌宣传支持者
  • C++多线程编程:深入剖析std::thread的使用方法
  • 伺服系统高频啸叫故障排查:从机械共振到控制回路不稳定的诊断历程
  • 告别内存泄漏和数组越界:用CppCheck给你的C++项目做一次免费‘体检’