Pandas分组中仅保留每组内channel=X的首次出现行
Pandas分组保留指定Channel首次出现行的解决方案
原始DataFrame
import pandas as pd df = pd.DataFrame({ 'group': ['A', 'A', 'B', 'B', 'B', 'C', 'C'], 'channel':['X','Y','Y','X','X','A','X'], 'value': [1, 2, 3, 3, 4, 5, 5] })
需求说明
按group字段分组后,仅对每个分组内的channel='X'行做去重(只保留首次出现的那一行),其他channel值的行全部保留,不做任何处理。
原代码的问题
你之前写的代码会删除分组内所有重复channel值的行(比如分组里如果有多个相同的非X channel也会被去重),完全不符合需求:
df = df.groupby('group').apply(lambda x: x.drop_duplicates(subset='channel', keep='first') if 'X' in x['channel'].values else x)
正确解决方案
方法一:分组自定义函数过滤
通过自定义函数,给每个分组生成保留掩码,只保留非X行和第一个X行:
def keep_first_x(group): # 掩码规则:非X行全部保留,X行仅保留首次出现的那一行 mask = (group['channel'] != 'X') | (group['channel'] == 'X').cumsum() == 1 return group[mask] # 应用分组处理,group_keys=False避免保留分组索引 result_df = df.groupby('group', group_keys=False).apply(keep_first_x) print(result_df)
方法二:transform生成掩码直接过滤
更简洁的写法,用transform把分组内的标记广播到原DataFrame,直接做布尔索引过滤:
# 生成全局掩码:非X行 或者 是分组内第一个出现的X行 mask = (df['channel'] != 'X') | df.groupby('group')['channel'].transform( lambda x: (x == 'X').cumsum() == 1 ) result_df = df[mask]
最终输出结果
group channel value 0 A X 1 1 A Y 2 2 B Y 3 3 B X 3 5 C A 5 6 C X 5
内容的提问来源于stack exchange,提问作者deega
相关产品推荐
相关产品推荐

