drop_duplicates()需指定subset参数按列去重,默认keep='first',保留最新行需先排序;删除特定条件重复行需结合duplicated()与布尔索引;keep=false可全删重复项;去重后应重置索引以防越界。

用 drop_duplicates() 指定列和条件去重
直接删重复行最常用的就是 drop_duplicates(),但它默认对所有列比对——你如果只想看某几列是否重复(比如只关心 'user_id' 和 'date' 是否相同),必须显式传 subset 参数,否则容易误删。
常见错误是写成 df.drop_duplicates(subset=['user_id', 'date']) 却没注意默认保留第一次出现的行(keep='first'),而业务上可能需要保留最新的一条(比如按时间排序后留最后一条):
- 先按时间列降序排序:
df.sort_values('timestamp', ascending=False, inplace=True) - 再去重并保留第一条:
df.drop_duplicates(subset=['user_id'], keep='first', inplace=True) - 如果不想改原顺序,排序时加
ignore_index=True,或去重后用df.reset_index(drop=True)
删除“满足某条件”的重复行,不是简单列组合重复
比如:只删除 status == 'cancelled' 的重复订单,但保留 'paid' 的重复记录——这时 drop_duplicates() 本身做不到,得拆开处理。
典型做法是分组 + 条件过滤:
- 用
df.groupby(['order_id', 'user_id'], group_keys=False)分组 - 对每组应用
apply():如果组内有'cancelled'且数量 > 1,就筛掉部分;否则全留 - 更稳妥的是先标记要删的索引:
mask = df.duplicated(subset=['order_id'], keep=False) & (df['status'] == 'cancelled'),再配合df[~mask]
注意 duplicated() 返回布尔 Series,和条件组合时务必用括号包裹每个子表达式,否则运算符优先级会导致逻辑错乱。
keep 参数选错导致删多或删少
keep 看似简单,但实际影响很大:'first'(默认)、'last'、False(全删)三者行为差异明显。尤其当数据未排序时,'first' 留下的那条可能是任意一条,不一定是你想要的“有效”记录。
- 想留最新时间的行?必须先按时间列排序,再设
keep='first' - 想把完全重复的行全部踢掉(即重复项一个不留),用
keep=False,此时返回的 DataFrame 会变小,且不会保留任何副本 -
keep对性能无影响,但逻辑错误很难回溯——建议在去重前用df.duplicated(subset=[...]).sum()先看有多少重复,心里有数
去重后索引断裂,别忘了重置
drop_duplicates() 不会自动重排索引,删掉中间几行后,索引可能变成 [0, 1, 4, 7, 8]。后续如果用 .iloc[2] 或做循环,容易越界或漏数据。
- 安全做法是链式调用:
df.drop_duplicates(...).reset_index(drop=True) - 如果原索引有意义(比如是时间戳或 ID),就别用
drop=True,保留它更利于追踪来源 - 用
inplace=True要谨慎:一旦出错没法撤回,建议先赋值新变量调试
真正容易被忽略的不是语法,而是“哪几列才算重复”这个业务定义——它往往藏在需求文档角落,而不是代码里。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











