如何在Pandas的groupby语句中筛选同时含指定数值的ID?
解决方案:合并筛选与分组统计的链式操作
当然可以!你完全不用拆分出两个中间DataFrame,把筛选和分组统计的逻辑合并成一条链式代码就行,既简洁又不影响200万行数据的处理效率。
方法一:链式过滤+分组统计
直接把筛选逻辑嵌入到分组操作的前置步骤里,用isin替代多个或条件更简洁,再通过loc结合lambda直接过滤结果:
# 一步完成筛选、分组统计和过滤 result = df[df['Number'].isin([30, 40])] \ .groupby('ID')['Number'] \ .nunique() \ .loc[lambda x: x > 1] \ .reset_index(name='tt')
代码解释:
df['Number'].isin([30, 40]):快速筛选出Number为30或40的行,比(df['Number']==30)|(df['Number']==40)更易读,后续要加更多数值也更方便;.groupby('ID')['Number'].nunique():按ID分组,统计每个ID下不同Number的数量;.loc[lambda x: x > 1]:直接过滤出计数大于1的ID(也就是同时包含30和40的ID),用lambda避免创建中间变量;.reset_index(name='tt'):把分组后的索引(ID)变回普通列,同时给计数列命名为tt,和你原来的结果格式一致。
方法二:用transform标记后筛选(适合更复杂的条件)
如果之后需要复用“是否包含30/40”的标记,或者有更灵活的条件判断,这种方式更直观:
# 给每行标记所属ID是否包含30和40 df['has_30'] = df.groupby('ID')['Number'].transform(lambda x: (x == 30).any()) df['has_40'] = df.groupby('ID')['Number'].transform(lambda x: (x == 40).any()) # 筛选同时满足的ID并去重 result_ids = df[df['has_30'] & df['has_40']]['ID'].unique()
这个方法的好处是,标记列has_30和has_40可以保留下来做后续分析,而且对于大数据集,transform的执行效率也很可观。
两种方式都能帮你省去中间变量,直接得到目标结果,你可以根据自己的实际需求选择~
内容的提问来源于stack exchange,提问作者Gary
相关产品推荐
相关产品推荐

