Python数据去重方法与drop\_duplicates使用详解
从现在开始,努力学习吧!本文《Python数据去重方法及drop\_duplicates参数详解》主要讲解了等等相关知识点,我会在golang学习网中持续更新相关的系列文章,欢迎大家关注并积极留言建议。下面就先一起来看一下本篇正文内容吧,希望能帮到你!
数据去重在数据分析中至关重要,因为它确保了数据的准确性、减少资源浪费并提升数据质量。1. 使用Pandas库中的drop_duplicates()方法是最常见且强大的工具;2. 该方法支持通过subset参数指定去重的列,默认检查所有列;3. keep参数控制保留重复项的方式,可选'first'(默认)、'last'或False(删除所有重复项);4. inplace参数允许直接在原数据上操作;5. 去重常用于移除完全重复记录、提取最新状态或找出唯一记录等场景,结合排序等操作能更灵活应对实际需求。
用Python实现数据去重,最常用也最强大的工具无疑是Pandas库里的drop_duplicates()
方法。它能高效地识别并移除DataFrame或Series中重复的行或值,让你的数据变得更干净、分析结果更可靠。在我看来,这是数据清洗流程里最基础也最关键的一步,少了它,很多后续分析都可能跑偏。

解决方案
要使用drop_duplicates()
,首先你需要有一个Pandas DataFrame或Series。这个方法提供了几个参数,让你能灵活控制去重逻辑。
我们先从一个简单的例子开始:

import pandas as pd import numpy as np # 构造一个示例DataFrame data = { 'ID': [1, 2, 3, 1, 4, 2, 5], 'Name': ['Alice', 'Bob', 'Charlie', 'Alice', 'David', 'Bob', 'Eve'], 'Score': [85, 90, 78, 85, 92, 90, 88], 'City': ['NY', 'LA', 'SF', 'NY', 'CHI', 'LA', 'MIA'] } df = pd.DataFrame(data) print("原始DataFrame:") print(df) # 最简单的去重:移除所有列都相同的重复行 df_deduplicated_all = df.drop_duplicates() print("\n去重后 (所有列都相同才算重复):") print(df_deduplicated_all) # 针对特定列去重,例如只看'ID'和'Name'是否重复 # 默认保留第一次出现的重复项 df_deduplicated_subset = df.drop_duplicates(subset=['ID', 'Name']) print("\n去重后 (只看'ID'和'Name'是否重复):") print(df_deduplicated_subset) # 去重并保留最后一次出现的重复项 df_deduplicated_keep_last = df.drop_duplicates(subset=['ID', 'Name'], keep='last') print("\n去重后 (只看'ID'和'Name'是否重复, 保留最后出现的):") print(df_deduplicated_keep_last) # 去重并删除所有重复项(即如果出现过重复,所有重复项都会被删除) df_deduplicated_keep_false = df.drop_duplicates(subset=['ID', 'Name'], keep=False) print("\n去重后 (只看'ID'和'Name'是否重复, 删除所有重复项):") print(df_deduplicated_keep_false) # 直接在原DataFrame上进行去重操作,不创建新的DataFrame df_inplace = df.copy() # 先复制一份,以免影响原始df df_inplace.drop_duplicates(inplace=True) print("\n原地去重后的DataFrame (df_inplace):") print(df_inplace)
drop_duplicates()
方法的关键参数包括:
subset
: 这是一个列表,指定在哪些列上检查重复项。如果省略,则检查所有列。keep
: 决定保留哪个重复项。'first'
(默认): 保留第一次出现的重复项。'last'
: 保留最后一次出现的重复项。False
: 删除所有重复项,即如果一个行是重复的,那么所有与其重复的行都会被删除。
inplace
: 一个布尔值,如果为True
,则在原始DataFrame上进行操作并返回None;如果为False
(默认),则返回一个去重后的新DataFrame。
为什么数据去重在数据分析中至关重要?
说实话,数据去重的重要性常常被低估,或者说,很多人只有在分析结果出现明显偏差时,才会回头审视是不是数据源头就有问题。在我看来,这就像盖房子,地基不稳,上层建筑再华丽也可能倾斜。重复数据会带来一系列麻烦,远不止是占用存储空间那么简单。

首先,它直接影响统计结果的准确性。比如,你正在分析用户行为,如果一个用户ID因为某种系统错误被记录了两次,那么你在计算活跃用户数、平均购买次数时,结果就会被虚增。这会导致你对业务的判断失真,甚至做出错误的决策。一个用户被算成两个,那你的转化率、留存率可能就没那么好看了,或者说,你以为的数据规模是真实的,但实际上却掺了水分。
其次,重复数据会浪费计算资源和时间。在处理大规模数据集时,多余的数据意味着更多的内存占用和更长的处理时间。无论是进行复杂的数据转换、模型训练还是可视化,每一步都会因为这些“冗余”而变得更慢。想象一下,你训练一个机器学习模型,如果训练集里有大量重复样本,模型可能会过度拟合这些重复数据,导致泛化能力下降,这可不是我们想看到的。
最后,从数据质量和信任度来看,干净的数据是任何分析项目的基础。如果你给出的报告或模型,其背后数据充斥着重复项,那么它的可信度会大打折扣。所以,数据去重不仅仅是技术操作,更是数据治理和保障数据质量的重要环节。它确保了我们所看到、所分析的数据,是真实、独立且有意义的。
理解drop_duplicates()
的subset
和keep
参数
drop_duplicates()
的强大之处,很大程度上就体现在它对subset
和keep
这两个参数的灵活控制上。它们决定了“重复”的定义以及“保留”的策略,这在实际工作中至关重要。
先说subset
。默认情况下,如果你不指定subset
,drop_duplicates()
会检查DataFrame中所有列的值是否都完全相同。只有当两行在所有列上的值都一模一样时,才会被认为是重复的。这在很多情况下是合理的,比如你只想找出完全相同的记录。
但更多时候,我们对“重复”的定义是基于部分列的。例如,一个用户可能在不同时间购买了不同的商品,所以他的所有购买记录行不可能完全相同。但如果你想找出“重复的用户”,那么你可能只需要看UserID
这一列。如果UserID
相同,就认为这是同一个用户的记录。
# 假设我们有一个订单记录,想找出哪些用户是重复的(即出现多次) order_data = { 'OrderID': [101, 102, 103, 104, 105, 106], 'UserID': ['A001', 'B002', 'A001', 'C003', 'B002', 'A001'], 'Product': ['Laptop', 'Mouse', 'Keyboard', 'Monitor', 'Laptop', 'Mouse'], 'Price': [1200, 25, 80, 300, 1000, 30] } df_orders = pd.DataFrame(order_data) print("原始订单数据:") print(df_orders) # 找出所有不重复的UserID(即每个UserID只出现一次) unique_users_df = df_orders.drop_duplicates(subset=['UserID']) print("\n按UserID去重后的用户列表 (默认保留第一次出现):") print(unique_users_df)
这里,subset=['UserID']
告诉Pandas,只要UserID
这一列的值相同,就视为重复。至于Product
和Price
列的值是否相同,则不予考虑。这非常实用,比如你只想获取一个不重复的用户ID列表,而不在乎他们具体买了什么。
接下来是keep
参数。这真的是一个需要仔细考量的地方,因为它直接决定了哪条数据被留下,哪条被移除。
keep='first'
(默认): 这是最常见的选择。它会保留第一次出现的重复项。比如你有三条记录:A, B, A' (A和A'在subset
列上是重复的,A先出现,A'后出现),那么A会被保留,A'会被删除。这适用于你认为“最早记录”或“原始记录”最有意义的场景。keep='last'
: 这会保留最后一次出现的重复项。在上面的例子中,A'会被保留,A会被删除。这在某些情况下非常有用,比如你有一个用户状态的历史记录,你可能只想保留最新的状态。keep=False
: 这个选项则更为激进。它会删除所有重复项。也就是说,如果A和A'是重复的,那么A和A'都会被删除。只有那些在subset
列上是完全唯一的行才会被保留。这适用于你只想找出那些“绝对唯一”的记录,任何一点重复都不能容忍的场景。
# 假设我们有员工打卡记录,有时员工会重复打卡,我们想保留最新的记录 checkin_data = { 'EmployeeID': ['E001', 'E002', 'E001', 'E003', 'E002'], 'CheckInTime': ['2023-10-26 08:00', '2023-10-26 08:05', '2023-10-26 08:10', '2023-10-26 08:15', '2023-10-26 08:20'] } df_checkin = pd.DataFrame(checkin_data) # 确保时间列是datetime类型,方便排序 df_checkin['CheckInTime'] = pd.to_datetime(df_checkin['CheckInTime']) print("原始打卡记录:") print(df_checkin) # 先按时间排序,确保“最后一次”真的是最新的 df_checkin_sorted = df_checkin.sort_values(by='CheckInTime', ascending=True) # 保留每个员工的最新打卡记录 latest_checkins = df_checkin_sorted.drop_duplicates(subset=['EmployeeID'], keep='last') print("\n每个员工的最新打卡记录:") print(latest_checkins) # 如果我们想找出那些只打卡一次的员工(即没有重复记录的) unique_only_checkins = df_checkin.drop_duplicates(subset=['EmployeeID'], keep=False) print("\n只打卡一次的员工记录:") print(unique_only_checkins)
选择keep
参数时,真的需要结合你的业务逻辑和数据特点来判断。没有绝对的“正确”答案,只有最适合你当前分析目标的策略。
结合实际场景,如何灵活运用drop_duplicates()
?
drop_duplicates()
在实际数据处理中简直是万金油,它的灵活运用能解决很多看似复杂的问题。这里我分享几个常见的场景和我的思考。
场景一:移除完全相同的冗余记录
这是最直接的用法,通常用于导入数据后初步清洗。比如你从某个数据库导出了一批日志,由于系统故障或者多次导出合并,可能存在完全相同的日志条目。这时候,不带任何参数的drop_duplicates()
就能派上用场。
# 假设日志数据 log_data = { 'Timestamp': ['2023-10-26 10:00:00', '2023-10-26 10:01:00', '2023-10-26 10:00:00', '2023-10-26 10:02:00'], 'EventType': ['Login', 'Click', 'Login', 'Logout'], 'UserID': ['userA', 'userB', 'userA', 'userC'] } df_logs = pd.DataFrame(log_data) print("原始日志数据:") print(df_logs) df_logs_cleaned = df_logs.drop_duplicates() print("\n完全去重后的日志:") print(df_logs_cleaned)
这里,('2023-10-26 10:00:00', 'Login', 'userA')
这条记录出现了两次,第一次去重后它只剩一条。
场景二:基于部分关键字段去重,保留“最新”或“最旧”状态
这在处理用户资料、商品信息等主数据时非常常见。比如,你有一个用户资料表,用户可以多次更新他们的地址。你可能只关心他们当前的最新地址,而不是所有的历史地址。
# 用户地址更新记录 user_address_data = { 'UserID': ['U001', 'U002', 'U001', 'U003', 'U002'], 'Address': ['Street A', 'Street B', 'Street C', 'Street D', 'Street E'], 'UpdateTime': ['2023-01-01', '2023-02-01', '2023-03-01', '2023-04-01', '2023-05-01'] } df_address = pd.DataFrame(user_address_data) df_address['UpdateTime'] = pd.to_datetime(df_address['UpdateTime']) # 转换为日期时间类型 print("原始用户地址记录:") print(df_address) # 找出每个用户的最新地址 # 关键步骤:先按UpdateTime排序,确保最新的记录在后面 df_address_sorted = df_address.sort_values(by='UpdateTime', ascending=True) latest_addresses = df_address_sorted.drop_duplicates(subset=['UserID'], keep='last') print("\n每个用户的最新地址:") print(latest_addresses)
这里,我们先对数据按UpdateTime
升序排序,这样最新的记录就会在重复项的最后面。然后,使用drop_duplicates(subset=['UserID'], keep='last')
,就能精准地提取出每个用户的最新地址了。这种先排序再去重的模式,在处理带有时间戳的数据时,是极其常用的技巧。
场景三:找出“真正独特”的记录,即任何重复都不保留
有时候,你可能想找出那些在某个维度上是“独一无二”的实体,任何出现过一次以上的情况,你都想剔除。这就像在班级里找“独生子女”,只要有兄弟姐妹的,都不算。
# 假设我们有一个产品销售记录,想找出那些只被购买过一次的产品ID sales_data = { 'ProductID': ['P001', 'P002', 'P001', 'P003', 'P004', 'P002'], 'SaleDate': ['2023-10-01', '2023-10-02', '2023-10-03', '2023-10-04', '2023-10-05', '2023-10-06'] } df_sales = pd.DataFrame(sales_data) print("原始销售记录:") print(df_sales) # 找出只被购买过一次的产品 unique_products_only = df_sales.drop_duplicates(subset=['ProductID'], keep=False) print("\n只被购买过一次的产品记录:") print(unique_products_only)
在这个例子中,P001
和P002
都出现了不止一次,所以它们都被keep=False
移除了。只有P003
和P004
因为只出现了一次,被保留了下来。
在处理非常大的数据集时,drop_duplicates()
的性能通常是很好的,因为它在底层是用C优化的。但如果你发现性能瓶颈,可以考虑在去重前,先对数据进行必要的筛选或抽样,减少处理的数据量。总的来说,理解并灵活运用drop_duplicates()
的参数,能让你在数据清洗的道路上事半功倍。
以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于文章的相关知识,也可关注golang学习网公众号。

- 上一篇
- 豆包AI卡顿?实用优化技巧分享

- 下一篇
- 通灵义码操作技巧全解析
-
- 文章 · python教程 | 16分钟前 |
- PyCharm新手教程,基础操作全攻略
- 263浏览 收藏
-
- 文章 · python教程 | 26分钟前 |
- Pythonif语句用法及elifelse详解
- 490浏览 收藏
-
- 文章 · python教程 | 30分钟前 |
- Python自动化报表:Jinja2模板使用教程
- 472浏览 收藏
-
- 文章 · python教程 | 33分钟前 |
- Python正则匹配Unicode字符技巧
- 201浏览 收藏
-
- 文章 · python教程 | 36分钟前 |
- Python中id的作用与对象识别解析
- 212浏览 收藏
-
- 文章 · python教程 | 46分钟前 |
- PythonORM原理及数据库映射详解
- 305浏览 收藏
-
- 文章 · python教程 | 48分钟前 |
- PythonGUI自动化教程:PyAutoGUI实战教学
- 255浏览 收藏
-
- 文章 · python教程 | 48分钟前 |
- Python定时任务实现全攻略
- 255浏览 收藏
-
- 文章 · python教程 | 55分钟前 |
- Python报告生成教程:Jinja2模板使用指南
- 454浏览 收藏
-
- 文章 · python教程 | 1小时前 |
- Python图像特征提取方法详解
- 345浏览 收藏
-
- 文章 · python教程 | 1小时前 | Python 异常处理 多线程 try-except-else-finally else块
- try-except-else-finally用法详解
- 141浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 509次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 边界AI平台
- 探索AI边界平台,领先的智能AI对话、写作与画图生成工具。高效便捷,满足多样化需求。立即体验!
- 353次使用
-
- 免费AI认证证书
- 科大讯飞AI大学堂推出免费大模型工程师认证,助力您掌握AI技能,提升职场竞争力。体系化学习,实战项目,权威认证,助您成为企业级大模型应用人才。
- 370次使用
-
- 茅茅虫AIGC检测
- 茅茅虫AIGC检测,湖南茅茅虫科技有限公司倾力打造,运用NLP技术精准识别AI生成文本,提供论文、专著等学术文本的AIGC检测服务。支持多种格式,生成可视化报告,保障您的学术诚信和内容质量。
- 508次使用
-
- 赛林匹克平台(Challympics)
- 探索赛林匹克平台Challympics,一个聚焦人工智能、算力算法、量子计算等前沿技术的赛事聚合平台。连接产学研用,助力科技创新与产业升级。
- 617次使用
-
- 笔格AIPPT
- SEO 笔格AIPPT是135编辑器推出的AI智能PPT制作平台,依托DeepSeek大模型,实现智能大纲生成、一键PPT生成、AI文字优化、图像生成等功能。免费试用,提升PPT制作效率,适用于商务演示、教育培训等多种场景。
- 522次使用
-
- Flask框架安装技巧:让你的开发更高效
- 2024-01-03 501浏览
-
- Django框架中的并发处理技巧
- 2024-01-22 501浏览
-
- 提升Python包下载速度的方法——正确配置pip的国内源
- 2024-01-17 501浏览
-
- Python与C++:哪个编程语言更适合初学者?
- 2024-03-25 501浏览
-
- 品牌建设技巧
- 2024-04-06 501浏览