为何df.groupby(...).agg(set)与lambda x:set(x)执行结果不同?
关于Pandas中
groupby.agg(set)与groupby.agg(lambda x: set(x))的差异问题 我之前也踩过这个坑,咱们结合你给出的测试数据把这个问题拆解明白:
首先先定义测试用的DataFrame:
import pandas as pd df = pd.DataFrame({ 'user_id': [1, 2, 3, 4, 1, 2, 3], 'class_type': ['Krav Maga', 'Yoga', 'Ju-jitsu', 'Krav Maga', 'Ju-jitsu','Krav Maga', 'Karate'], 'instructor': ['Bob', 'Alice','Bob', 'Alice','Alice', 'Alice','Bob'] })
两种调用方式的结果差异
先看你给出的lambda包装的调用结果,这是完全符合预期的——每个用户对应的课程类型和教练都被转换成了无重复的集合:
df.groupby('user_id').agg(lambda x: set(x))
输出:
class_type instructor user_id 1 {Krav Maga, Ju-jitsu} {Alice, Bob} 2 {Yoga, Krav Maga} {Alice} 3 {Ju-jitsu, Karate} {Bob} 4 {Krav Maga} {Alice}
但如果直接使用df.groupby('user_id').agg(set),你会发现结果大概率和预期不符——比如在部分Pandas版本中,它可能返回包含Series索引的集合,或者触发奇怪的内部逻辑,导致结果不是单纯的列值集合。
背后的原因
核心问题出在Pandas对agg()参数的解析逻辑:
- 当你用
lambda x: set(x)时,相当于明确告诉Pandas:对每个分组后的单列Series对象x,直接把它的迭代值(也就是列里的实际数据)转换成集合。这个逻辑直白无歧义,完全按照你的预期执行。 - 而直接传入
set时,Pandas内部会尝试将其匹配为官方支持的内置聚合函数(比如sum、mean这类),但set并不是Pandas认可的聚合函数,所以在不同版本的Pandas中,它的处理路径会出现差异——有的版本会把整个Series对象传入set(导致集合里包含索引元素),有的版本甚至会直接抛出错误。
解决方案
如果想稳定地得到分组列值的集合,优先使用lambda包装的方式,也就是lambda x: set(x),它的行为更明确,不会受Pandas版本或内部逻辑变化的影响。如果追求更高性能,也可以用x.unique()再转集合,但lambda的方式可读性更好,更适合大多数场景。
内容的提问来源于stack exchange,提问作者MaxU - stand with Ukraine
相关产品推荐
相关产品推荐

