基于id与ticker组合识别DataFrame重复项并按条件过滤处理
解决DataFrame中(id,ticker)重复项的展示与过滤删除问题
嘿,我明白你想要的是先找出所有id和ticker组合的重复行,再通过过滤的方式(而非排序)根据state列的条件清理重复项,这就来一步步帮你实现:
第一步:展示所有(id,ticker)组合的重复项
我们可以用duplicated()方法,指定检查重复的列是id和ticker,并设置keep=False来获取所有重复的行(包括第一次出现的重复行):
# 筛选并展示所有id与ticker组合的重复行 duplicate_entries = df[df.duplicated(subset=['id', 'ticker'], keep=False)] display(duplicate_entries)
运行这段代码后,你就能看到所有存在重复(id,ticker)组合的行,比如你数据里的396496和396588相关的行都会被列出来。
第二步:通过过滤方式删除不符合条件的重复项
这里关键是先明确你的state保留规则,比如:
- 对于重复的(id,ticker)组合,优先保留
state="Done"的行 - 如果没有
Done状态,就保留非NULL的行 - 如果同组内都是相同的有效state(比如你的
396588两行都是Order Sent),可以选择全部保留或只留一行(根据你的需求调整)
方案1:用groupby+自定义过滤函数
这种方式直接按分组过滤,逻辑清晰:
def filter_group(group): # 优先保留state为Done的行 if 'Done' in group['state'].values: return group[group['state'] == 'Done'] # 没有Done的话,排除NULL的行 else: return group[group['state'] != 'NULL'] # 按id和ticker分组,应用过滤函数,合并结果 cleaned_df = df.groupby(['id', 'ticker'], group_keys=False).apply(filter_group) display(cleaned_df)
针对你的示例数据,这段代码会保留396496对应的Done行,排除NULL行;而396588的两行都是Order Sent,会全部保留(如果想每个组合只留一行,可以在最后加上.drop_duplicates(subset=['id','ticker'], keep='first'))。
方案2:用transform标记保留行再过滤
如果你更喜欢用列标记的方式,也可以这样做:
# 给每行标记是否需要保留 df['to_keep'] = df.groupby(['id', 'ticker'])['state'].transform( lambda x: x == 'Done' if 'Done' in x.values else x != 'NULL' ) # 过滤出需要保留的行,删除标记列 cleaned_df = df[df['to_keep']].drop('to_keep', axis=1) display(cleaned_df)
这个方案的效果和方案1完全一致,只是实现方式不同,都是纯过滤逻辑,没有依赖排序操作。
内容的提问来源于stack exchange,提问作者Peter Lucas
相关产品推荐
相关产品推荐

