3个kee函数深坑,面试必问的避坑指南
官方文档翻了三遍还是晕?别慌,keep 这个概念在数据处理里太容易踩雷了。很多后端和算法岗面试必问,答不上来直接减分。
坑的现象:数据莫名消失或重复
做数据清洗时,你是不是遇到过这种崩溃瞬间:明明用 keep 去重,结果数据行数不对,或者关键列的值被错误覆盖?
典型报错场景:静默失败:代码没报错,但输出数据量比预期少,且没有日志提示。
逻辑混乱:同一个键值对,keep='first' 和 keep='last' 结果完全相反,甚至和 drop_duplicates 行为不一致。
性能雪崩:在百万级数据上,简单的 keep 操作导致内存溢出或耗时激增。我在掘金技术社区看到不少老哥吐槽,说 Pandas 的 drop_duplicates 默认行为是 keep='first',但很多人误以为是 keep='last',导致线上数据错位。
根本原因:索引与值的混淆
90% 的坑,都源于没搞清楚 keep 到底作用在行上还是列上,以及它和索引的关系。
核心误区:误区1:认为 keep 是全局去重,实际它是基于指定列(或所有列)的局部去重。
误区2:忽略索引重置。如果 DataFrame 索引不是默认的 RangeIndex,keep 操作后索引可能不连续,导致后续合并或切片出错。
误区3:混淆 keep 和 unique。unique 返回唯一值数组,keep 是保留完整行。技术细节:
keep 参数在 Pandas 中主要用于 drop_duplicates,其逻辑是:keep='first':保留每组重复数据中第一次出现的行。
keep='last':保留每组重复数据中最后一次出现的行。
keep=False:删除所有重复行,只保留完全唯一的行。注意:这里的“组”是由 subset 参数定义的列组合决定的。如果没指定 subset,则是基于所有列判断唯一性。
正确写法对比:代码即真理
错误写法:盲目依赖默认值,不检查索引状态
import pandas as pd# 构造测试数据:注意索引是乱序的
df = pd.DataFrame({'id': [1, 2, 2, 3, 3, 3],'name': ['Alice', 'Bob', 'Bob', 'Charlie', 'Charlie', 'Charlie'],'score': [80, 90, 95, 70, 75, 80]
}, index=[5, 1, 2, 3, 4, 0]) # 故意打乱索引print(原始数据索引:)
print(df.index.tolist())# 错误:直接去重,不重置索引
df_dropped = df.drop_duplicates(subset=['id'], keep='first')print(去重后数据:)
print(df_dropped)
print(去重后索引:, df_dropped.index.tolist())# 潜在问题:索引不连续,后续如果按索引操作会出错正确写法:显式指定参数,重置索引,验证结果
import pandas as pd# 构造相同测试数据
df = pd.DataFrame({'id': [1, 2, 2, 3, 3, 3],'name': ['Alice', 'Bob', 'Bob', 'Charlie', 'Charlie', 'Charlie'],'score': [80, 90, 95, 70, 75, 80]
}, index=[5, 1, 2, 3, 4, 0])# 正确步骤1:显式指定 keep 和 subset
# 正确步骤2:重置索引,确保后续操作安全
df_clean = df.drop_duplicates(subset=['id'], keep='first').reset_index(drop=True)print(清洗后数据:)
print(df_clean)
print(清洗后索引:, df_clean.index.tolist())# 进阶:如果需要保留特定分数的最大值,不能只用 keep
# 正确做法:使用 groupby + agg
df_best = df.sort_values('score', ascending=False).drop_duplicates(subset=['id'], keep='first').reset_index(drop=True)
print(每个ID最高分:)
print(df_best)关键差异:索引处理:reset_index(drop=True) 是防坑关键,避免索引错位。
业务逻辑:keep 只能按“出现顺序”保留,不能按“值大小”保留。如果需要保留最大/最小值,必须结合 sort_values。
显式参数:永远不要依赖默认参数,面试中问“默认行为是什么”,答错就是硬伤。复现与修复代码:实战避坑清单
场景1:日志数据去重,保留最新记录
import pandas as pd
from datetime import datetime# 模拟日志数据:同一用户多次登录
log_data = {'user_id': [101, 101, 102, 102, 103],'login_time': ['2023-01-01 10:00', '2023-01-01 12:00', '2023-01-01 11:00', '2023-01-01 13:00', '2023-01-01 09:00'],'ip': ['192.168.1.1', '192.168.1.2', '192.168.1.3', '192.168.1.4', '192.168.1.5']
}df_log = pd.DataFrame(log_data)
df_log['login_time'] = pd.to_datetime(df_log['login_time'])# 错误:直接 keep='last',但数据没排序,'last' 是行序最后,不是时间最后
# 正确:先按时间排序,再 keep='last'
df_latest = df_log.sort_values('login_time', ascending=True).drop_duplicates(subset=['user_id'], keep='last').reset_index(drop=True)print(每个用户最新登录记录:)
print(df_latest)场景2:多维数据唯一性校验
# 场景:订单表,需要确保 (user_id, product_id, order_time) 组合唯一
orders = pd.DataFrame({'user_id': [1, 1, 2, 2, 2],'product_id': [10, 10, 20, 20, 30],'order_time': ['2023-05-01', '2023-05-01', '2023-05-01', '2023-05-02', '2023-05-02']
})# 错误:只按 user_id 去重,导致不同商品被误删
# 正确:指定 subset 为多列
df_unique = orders.drop_duplicates(subset=['user_id', 'product_id', 'order_time'], keep='first').reset_index(drop=True)print(唯一订单记录:)
print(df_unique)# 验证:检查是否还有重复
duplicates = df_unique[df_unique.duplicated(subset=['user_id', 'product_id', 'order_time'], keep=False)]
print(剩余重复数:, len(duplicates))规避建议:面试与实战双保险
面试高频问法:问:drop_duplicates 中 keep 参数有哪些值?默认值是什么?
答:'first', 'last', False。默认是 'first'。
问:如果数据无序,keep='last' 能保证保留时间最新的记录吗?
答:不能。必须先按时间字段排序,再执行 drop_duplicates。
问:keep=False 和 drop_duplicates 默认行为有什么区别?
答:keep=False 删除所有重复行,只保留完全唯一的行;默认 keep='first' 保留每组第一次出现的行。实战最佳实践:永远重置索引:去重后加 reset_index(drop=True),避免索引污染。
先排序再去重:如果业务需要保留“最大/最小/最新”值,必须先 sort_values。
显式指定 subset:不要依赖全列去重,除非你100%确定所有列都参与唯一性判断。
日志记录:在关键去重步骤前后,打印行数变化,便于排查数据丢失。
单元测试:针对 keep 参数编写边界测试用例,覆盖索引乱序、空值、多列组合等场景。性能优化技巧:对于超大内存数据,drop_duplicates 是内存密集型操作。建议先抽样测试,确认逻辑正确后再全量执行。
如果数据量超过内存限制,考虑使用 Dask 或 Spark 的 drop_duplicates,逻辑类似,但分布式执行。
避免在循环中调用 drop_duplicates,这会显著降低性能。常见陷阱清单:❌ 依赖默认 keep='first' 而不确认业务需求。
❌ 数据未排序就直接用 keep='last' 期望保留最新记录。
❌ 忽略索引重置,导致后续 loc 或 iloc 操作出错。
❌ 在包含 NaN 的数据上直接去重,NaN 的相等性判断可能导致意外结果。
❌ 误以为 keep 可以基于值大小保留,实际需要结合 sort_values。掘金技术社区 多位作者强调,数据处理中“隐式行为”是最大的坑。Pandas 的许多函数默认值看似合理,但在复杂业务场景下容易引发隐蔽错误。养成显式指定参数的习惯,是避免踩坑的关键。
你更常用哪种写法? 是习惯先排序再去重,还是依赖 groupby 的 agg 方法?或者你有其他独门秘籍?评论区交流,看看谁的经验更实战。
企业数字化 ERP 产品动态
相关推荐
仿官方魔域最佳实践:3步搞定证书补办与查询,避开90%的坑 仿官方魔域最佳实践:3步搞定证书补办与查询,避开90%的坑 刚接手运维或开发支持岗位,最崩溃的瞬间是什么?不是代码报错,而是手里拿着一个过期的、或者根本查不到的“仿官方魔域”环境配置,复制来的脚本跑不通,报错日志长得像天书,你盯着屏幕不知道… · 2026/9/23 9:26:25
AI 应用怎么做缓存?一个省下 40% 调用量的实现方案 先交代边界
本文所有数据来自我维护的一个多语言客服消息处理服务:月调用量约 80 万次,任务覆盖意图分类、语言识别、摘要、回复生成四类。对比维度只有三个——调用量降幅、错误答案率、P95 延迟。缓存方案是我在生产环境里迭代了两轮才稳定的… · 2026/9/23 9:26:25
Yii 2 受入テスト(验收测试)实战指南:用 Codeception 从用户视角验证 Web 应用 Yii 2 受入テスト(验收测试)实战指南:用 Codeception 从用户视角验证 Web 应用 【免费下载链接】yii2 Yii 2: The Fast, Secure and Professional PHP Framework 项目地址: https://gitcode.com/gh_mirrors/yi/yii2
导读
本文围绕 Yi… · 2026/9/23 9:26:18
组建小型以太网实战:从MAC地址学习到VLAN隔离 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 8:07:15
怀旧武侠《贰点零江湖》正版官方客户端下载指引,忆往游戏正规安全渠道指南 《贰点零江湖》又名热血江湖2.0,由安徽游昕网络科技有限公司联合忆往游戏平台负责运营,是经过正版授权打造的经典怀旧武侠手游。现阶段游戏依托专属官方主站面向全网正式开放,高度复刻热血江湖端游原版 2.0 版本内容,坚持公平长久… · 2026/9/24 8:07:15
煤化工气体监测中Modbus RTU转HART网关的选型配置与实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 8:07:09
开源工业网关实战:西门子S7 PLC数据采集与MQTT上云 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 8:06:57
Qt程序打包exe全攻略:从windeployqt到安装包制作与问题排查 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 8:06:38
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程 简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13
1D-CNN时间序列建模实战:从Conv1d原理到工业落地 简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26
柔软的L:汉语语流中被忽视的舌肌张力控制 1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44