如何在R中实现左/右排除连接及带双列返回的左连接?
解决你的R数据连接问题
先把我们要用的数据集定义好,方便后续演示:
A <- data.frame(A = c("Amsterdam", "Copenhagen", "LA", "Lisbon", "London", "Madrid", "New York", "Paris", "Rome", "Stockholm"), stringsAsFactors = FALSE) B <- data.frame(B = c("Amsterdam", "Buenos Aires", "Copenhagen", "LA", "London", "Sydney", "Tokyo"), stringsAsFactors = FALSE)
1. 等价于SQL左排除连接的R实现(仅存在于A的城市)
你提到的SQL左排除连接,目的是获取只在A里存在、不在B里出现的记录。在R里有两种常用方法:
方法一:Base R的merge()函数
利用merge的all.x = TRUE先做左连接,再筛选出B列(匹配列)为NA的行:
# 先做左连接 left_join_result <- merge(A, B, by.x = "A", by.y = "B", all.x = TRUE) # 筛选B列是NA的行(即仅在A存在的记录) only_in_A <- left_join_result[is.na(left_join_result$B), "A", drop = FALSE]
运行后only_in_A就是你要的Lisbon、Madrid、New York、Paris、Rome、Stockholm这些城市。
方法二:Tidyverse的dplyr::anti_join()
如果用dplyr包,anti_join()就是专门干这个的——返回在第一个数据框里但不在第二个里的记录,完全等价于你的SQL左排除连接:
library(dplyr) only_in_A <- anti_join(A, B, by = c("A" = "B"))
这个写法更简洁,可读性也强。
2. 获取仅存在于B的城市列表
和上面的逻辑反过来就行:
Base R方法
先做右连接,再筛选A列为NA的行:
right_join_result <- merge(A, B, by.x = "A", by.y = "B", all.y = TRUE) only_in_B <- right_join_result[is.na(right_join_result$A), "B", drop = FALSE]
dplyr方法
用anti_join交换两个数据框的顺序:
only_in_B <- anti_join(B, A, by = c("B" = "A"))
结果就是Buenos Aires、Sydney、Tokyo这些城市。
3. 左连接后返回包含A和B列的结果
你说用merge(A, B, by.x = "A", by.y = "B", all.x = T)只得到A列?这应该是个小误会,我测试了一下,这个代码本来就会返回两列:A列是所有A里的城市,B列是匹配到的城市,没匹配到的显示NA。
你可以再运行一遍这段代码,然后打印left_join_result看看:
left_join_result <- merge(A, B, by.x = "A", by.y = "B", all.x = TRUE) print(left_join_result)
输出应该是这样的:
A B 1 Amsterdam Amsterdam 2 Copenhagen Copenhagen 3 LA LA 4 Lisbon <NA> 5 London London 6 Madrid <NA> 7 New York <NA> 8 Paris <NA> 9 Rome <NA> 10 Stockholm <NA>
如果你的结果真的只有A列,可能是之前的代码里不小心加了drop = TRUE或者其他筛选条件?可以检查一下代码哦。
内容的提问来源于stack exchange,提问作者Luther_Blissett
相关产品推荐
相关产品推荐

