在dplyr中如何用另一张表的两列进行同时过滤?验证自身实现思路的正确性
关于你的过滤逻辑验证与修正建议
嗨,刚好能帮你厘清这个问题~你的预期结果和想要实现的逻辑是对的,但当前写的filter代码其实没法准确实现「匹配col1与col2的对应组合」这个需求,我来给你拆解下:
为什么当前代码有问题
你写的:
final_table <- table_2 %>% filter(col1 %in% table_1$col1 & col2 %in% table_1$col2)
这个逻辑是分别检查col1是否在table_1的col1列表里,同时col2是否在table_1的col2列表里,但这两个条件是独立的,不是绑定在一起的组合匹配。举个极端点的例子:
如果table_1的数据是:
| col1 | col2 | col3 |
|---|---|---|
| One | 3 | A |
| Three | 1 | C |
那table_2里的One 1 A这一行,会被当前代码保留——因为One在table_1的col1里,1也在table_1的col2里,但这个**(One,1)的组合其实根本不在table_1里**,这就不符合你想要的「对应组合匹配」的逻辑了。
正确的实现方式
要实现「匹配两列的对应组合」,用dplyr里的semi_join是最直接的,它专门用来保留左表(这里是table_2)中在右表(table_1)存在完全匹配组合的行:
final_table <- table_2 %>% semi_join(table_1, by = c("col1", "col2"))
运行这段代码后,你会得到完全符合预期的结果:
| col1 | col2 | col3 |
|---|---|---|
| One | 1 | A |
| Three | 3 | C |
补充说明(用filter实现的替代方案)
如果一定要用filter来实现,也可以先把table_1的col1和col2组合成一个唯一标识,再做匹配:
# 先给table_1生成组合列 table_1_with_key <- table_1 %>% mutate(key = paste(col1, col2, sep = "_")) # 过滤table_2 final_table <- table_2 %>% mutate(key = paste(col1, col2, sep = "_")) %>% filter(key %in% table_1_with_key$key) %>% select(-key) # 删掉临时生成的key列
不过这种方法不如semi_join简洁高效,尤其是数据量较大的时候,优先推荐用semi_join。
内容的提问来源于stack exchange,提问作者PotterFan
相关产品推荐
相关产品推荐

