如何基于两个DataFrame的EEnum与Date匹配删除DF2中的行?
问题分析与解决方法
你的代码错误原因
你当前的代码~((DF2.EEnum.isin(DF1['EEnum']))&(DF2.Date5.isin(DF1['Date'])))逻辑存在偏差:它判断的是DF2的EEnum存在于DF1的EEnum列表中,且DF2的Date5存在于DF1的Date列表中,但这两个条件是独立判断的,并没有要求是同一行的(EEnum, Date)组合匹配。举个例子,如果DF2里有一行EEnum=123, Date5=01/02/2022,你的代码也会把它删掉——因为123在DF1的EEnum里,01/02/2022在DF1的Date里(属于EEnum124的行),但这并不是你要删除的“EEnum和Date同时匹配DF1同一行”的目标行。
正确的解决方法
以下几种方法都是针对DF2的(EEnum, Date5)组合是否存在于DF1的(EEnum, Date)组合来实现筛选,完全符合你的需求:
方法1:元组组合匹配
把DF1的目标列转成元组列表,直接判断DF2的对应组合是否在列表内:
# 生成DF1中需要匹配的(EEnum, Date)组合集合 match_pairs = set(zip(DF1['EEnum'], DF1['Date'])) # 筛选DF2中不在匹配组合里的行 DF2 = DF2[~DF2[['EEnum', 'Date5']].apply(tuple, axis=1).isin(match_pairs)]
方法2:Merge合并筛选
通过合并操作标记匹配行,再筛选出未匹配的内容:
# 左连接DF2和DF1,仅匹配(EEnum, Date5)-(EEnum, Date)的组合,添加_merge列标记匹配状态 merged_df = DF2.merge(DF1, left_on=['EEnum', 'Date5'], right_on=['EEnum', 'Date'], how='left', indicator=True) # 保留仅存在于DF2的行,删除标记列 DF2 = merged_df[merged_df['_merge'] == 'left_only'].drop('_merge', axis=1)
方法3:Query简洁写法
如果你的日期列是可直接比较的类型(比如datetime),可以用query简化代码:
valid_pairs = set(zip(DF1['EEnum'], DF1['Date'])) # 使用query语法筛选不在目标组合中的行 DF2 = DF2.query('(EEnum, Date5) not in @valid_pairs')
验证结果
用你提供的示例数据测试,以上方法都会得到你期望的结果:
| EEnum | Date5 |
|---|---|
| 123 | 05/01/2022 |
| 123 | 06/25/2022 |
| 124 | 01/03/2022 |
内容的提问来源于stack exchange,提问作者Bumbaro2217
相关产品推荐
相关产品推荐

