如何按ID分组后剔除value列含0的整组DataFrame数据?
问题描述
现有如下Pandas DataFrame数据:
ID date value A 2020Q1 5 A 2020Q2 5 A 2020Q3 7 A 2020Q4 6 A 2021Q1 9 B 2019Q1 4 B 2019Q2 0 B 2019Q3 9 C 2019Q1 3 C 2019Q2 2 C 2019Q3 2 C 2019Q4 0 D 2019Q3 7 D 2019Q4 7 D 2020Q1 8 E 2020Q1 1 E 2020Q2 1 E 2020Q3 1 E 2020Q4 5 F 2018Q1 7 F 2018Q2 8 F 2018Q3 8 G 2018Q1 0 G 2018Q2 0 G 2018Q3 4 G 2018Q4 8 ..
需要按ID分组,仅保留value列中无0值的分组,剔除所有包含0值的分组,期望输出如下:
ID date value A 2020Q1 5 A 2020Q2 5 A 2020Q3 7 A 2020Q4 6 A 2021Q1 9 D 2019Q3 7 D 2019Q4 7 D 2020Q1 8 E 2020Q1 1 E 2020Q2 1 E 2020Q3 1 E 2020Q4 5 F 2018Q1 7 F 2018Q2 8 F 2018Q3 8 ..
实现方案
方法1:groupby + filter直接筛选分组
这是最简洁的写法,直接对ID分组后,过滤出value列全不为0的分组:
import pandas as pd # 假设原始数据存储在df变量中 filtered_df = df.groupby('ID').filter(lambda x: (x['value'] != 0).all())
- 逻辑:
filter方法会遍历每个分组,用lambda函数判断该分组的所有value是否都不等于0,仅保留符合条件的分组数据。
方法2:先提取合法ID再过滤
先通过分组聚合找出所有符合条件的ID,再用这些ID筛选原始数据:
# 计算每个ID对应的分组是否满足value全不为0 valid_id_mask = df.groupby('ID')['value'].apply(lambda x: (x != 0).all()) # 提取符合条件的ID列表 valid_ids = valid_id_mask[valid_id_mask].index # 筛选原始数据中属于合法ID的行 filtered_df = df[df['ID'].isin(valid_ids)]
- 逻辑:先明确哪些ID是符合要求的,再精准筛选这些ID的所有记录,适合需要单独保留合法ID列表的场景。
方法3:transform标记后筛选
通过transform给每行标记所属分组是否合法,再筛选出合法行:
# 给每行添加辅助列,标记所属分组是否满足value全不为0 df['valid_group'] = df.groupby('ID')['value'].transform(lambda x: (x != 0).all()) # 筛选合法行并删除辅助列 filtered_df = df[df['valid_group']].drop(columns='valid_group')
- 逻辑:
transform会将分组的判断结果广播到该分组的每一行,方便后续基于行的筛选操作。
内容的提问来源于stack exchange,提问作者Olive
相关产品推荐
相关产品推荐

