pandas对groupby对象调用filter按列值过滤报TypeError的解决
报错核心原因拆解
你遇到的报错本质是混淆了两类filter方法的适用场景,还搞错了代码执行后的对象类型:
- 执行
df.groupby(...).aggregate('sum')后,返回的不是可调用filter(lambda)的GroupBy分组对象,而是完成聚合计算的普通DataFrame。 - 普通DataFrame的
filter方法是用来按标签名称筛选行/列的,入参仅支持列名列表、模糊匹配的类名/正则规则,不接受lambda函数作为位置参数。你传入的lambda被默认映射到了items参数,pandas尝试把这个函数对象当成可迭代的列名列表遍历,最终抛出TypeError: 'function' object is not iterable。 - 退一步说,就算你在未聚合的GroupBy对象上调用filter,你的lambda逻辑也不满足要求:GroupBy.filter的入参是当前分组对应的子DataFrame块,必须返回布尔值判断整个分组是否保留,不能直接用列名比较得到布尔序列。
正确实现方案
方案1:最直接的原始行筛选(符合你预期结果的最优解)
你要的是location值为loc2的所有原始数据行,根本不需要走分组、聚合流程,直接对原始DataFrame做布尔索引即可:
# 直接按列值筛选,一步得到带原始text、日期、来源的结果 result = df[df['location'] == 'loc2']
方案2:需要走分组流程时的正确filter写法
如果你的业务逻辑确实需要先做分组、再保留满足条件的分组对应的所有原始行,需要在未执行聚合的GroupBy对象上调用filter,不能在聚合后的普通DataFrame上调:
# 第一步:仅生成分组对象,不提前执行聚合 grouped_obj = df.groupby(['category', 'source_num', 'source', 'location']) # 第二步:在GroupBy对象上调用filter,lambda返回布尔值判断分组是否保留 # 因为location是分组键,每个分组内的location值固定,取首个值判断即可 result = grouped_obj.filter(lambda x: x['location'].iloc[0] == 'loc2')
代码中的隐藏坑提醒
- 你提供的报错代码里,分组列名写的是
'category ',字符串前后带有多余空格,和原始DataFrame的category列名不匹配,后续执行分组操作时会触发列不存在的报错,需要把列名前后的多余空格清理掉。 - 你之前的执行顺序逻辑颠倒:
.aggregate('sum')会把文本、日期类型的列从结果中剔除,根本无法回到你期望的带原始文本、日期的表结构,想筛原始行的动作必须放在聚合操作之前。
内容的提问来源于stack exchange,提问作者DevLeb2022
相关产品推荐
相关产品推荐

