Pandas按col_1分组后,如何基于col_2过滤掉大于1的数据?
问题分析与解决方法
首先明确你的需求:从my_df中移除所有col_2严格大于1的行,最终得到每个col_1对应col_2=1的记录。先解释你两种写法的问题:
现有写法的问题
第一种写法:
df_ts = my_df.groupby('col_1').filter(lambda x: (x['col_2'] <= 1).any())groupby.filter()的作用是保留/丢弃整个分组,判断逻辑是:只要分组内存在至少一条满足条件的行,就保留整个分组的所有行。你的每个分组(A/B/C)都包含col_2=1的行,所以整个分组被完整保留,自然返回原DataFrame。第二种写法:
df_ts = my_df.groupby('col_1').filter(lambda x: x['col_2'] <= 1)filter()要求传入的lambda必须返回单个布尔值(用于判断整个分组是否保留),但这里返回的是与分组行数一致的布尔数组,不符合要求,因此报错。
正确实现方法
方法一:直接布尔索引(最简单高效)
你的需求本质是筛选col_2<=1的行,无需分组即可实现:
import pandas as pd my_df = pd.DataFrame({'col_1': ['A', 'A', 'B', 'B', 'C', 'C'], 'col_2': [1, 2, 1, 2, 1, 2]}) final_df = my_df[my_df['col_2'] <= 1].reset_index(drop=True)
方法二:结合groupby和apply(适合复杂组内筛选场景)
如果需要基于分组进行更复杂的筛选逻辑,可以用groupby.apply():
final_df = my_df.groupby('col_1').apply(lambda x: x[x['col_2'] <= 1]).reset_index(drop=True)
方法三:groupby+transform生成掩码
通过transform()生成与原DataFrame长度一致的布尔掩码,再筛选:
mask = my_df.groupby('col_1')['col_2'].transform(lambda x: x <= 1) final_df = my_df[mask].reset_index(drop=True)
以上三种方法最终得到的final_df均符合你的预期:
col_1 col_2 0 A 1 1 B 1 2 C 1
内容的提问来源于stack exchange,提问作者user1700890
相关产品推荐
相关产品推荐

