如何连接(合并)数据帧(内、外、左、右)

给定两个数据帧:

df1 = data.frame(CustomerId = c(1:6), Product = c(rep("Toaster", 3), rep("Radio", 3)))
df2 = data.frame(CustomerId = c(2, 4, 6), State = c(rep("Alabama", 2), rep("Ohio", 1)))

df1#  CustomerId Product#           1 Toaster#           2 Toaster#           3 Toaster#           4   Radio#           5   Radio#           6   Radio

df2#  CustomerId   State#           2 Alabama#           4 Alabama#           6    Ohio

我如何做数据库样式,即 sql style, joins "")
? 也就是说,我如何得到:

• df1 和df2的 inner join#Inner_join "")
仅返回左表中与右表中的键相匹配的行

• df1 和df2的 outer join#Outer_join "")
返回两个表中的所有行,从左边连接在右边表中有匹配键的记录

• df1 和df2的 left outer join (or simply left join)#Left_outer_join "")
返回左表中的所有行,以及右表中带有匹配键的所有行

• df1 和df2的 right outer join#Right_outer_join "")
返回右表中的所有行,以及左表中带有匹配键的所有行

思考题:
如何执行 SQL style选择语句?

通过使用 merge 函数及其可选参数:
内部连接: merge (df1,df2)将适用于这些示例,因为 R通过常见的变量名自动连接帧,但是您很可能希望指定 merge (df1,df2,通过“ CustomerId”) ,以确保只匹配所需的字段。 如果匹配的变量在不同的数据帧中具有不同的名称,还可以使用 by.x 和 by.x 参数。

Outer join: merge(x = df1, y = df2, by = "CustomerId", all = TRUE)
Left outer: merge(x = df1, y = df2, by = "CustomerId", all.x = TRUE)
Right outer: merge(x = df1, y = df2, by = "CustomerId", all.y = TRUE)
Cross join: merge(x = df1, y = df2, by = NULL)

我认为引入要合并的标识符几乎总是最好的; 如果输入 data.frames 意外地发生变化,以后可以更容易地阅读,这样会更安全。
您可以通过向量例如by = c("CustomerId", "OrderId")来合并多个列。
如果要合并的列名不相同,可以指定,例如,by.x“ CustomerId in df1” ,by.y“ CustomerId in df2” ,其中 df1中的 CustomerId 是第一个数据帧中列的名称,df2中的 CustomerId 是第二个数据帧中列的名称。 (如果需要在多列上合并,这些也可以是向量。)

我建议您查看Gabor Grothendieck's sqldf package
,可以用SQL 表达这些操作。

library(sqldf)
## inner join
df3 <- sqldf("SELECT CustomerId, Product, State 
              FROM df1
              JOIN df2 USING(CustomerID)")
## left join (substitute 'right' for right join)
df4 <- sqldf("SELECT CustomerId, Product, State 
              FROM df1
              LEFT JOIN df2 USING(CustomerID)")

我发现 SQL 语法比它的 R对等语法更简单、更自然(但这可能只是我对 RDBMS 的偏见哈哈哈)。
看这儿Gabor's sqldf GitHub
获得更多关于joins的信息。

把data.table用于内部连接 ,非常节省时间和内存(对于一些较大的 data.frames 来说是必要的) :

library(data.table)
dt1 <- data.table(df1, key = "CustomerId") 
dt2 <- data.table(df2, key = "CustomerId")
joined.dt1.dt.2 <- dt1[dt2]

Merge 也适用于 data.tables (因为它是泛型的,并调用 merge.data.table)
merge(dt1, dt2)
另一个方法是plyr包中的join函数

library(plyr)

join(df1, df2,
     type = "inner")
#   CustomerId Product   State# 1          2 Toaster Alabama# 2          4   Radio Alabama# 3          6   Radio    Ohio

你也可以使用 Hadley Wickham 的 dplyr package来做join函数。

library(dplyr)
#make sure that CustomerId cols are both type numeric#they ARE not using the provided code in question and dplyr will complain
df1$CustomerId <- as.numeric(df1$CustomerId)
df2$CustomerId <- as.numeric(df2$CustomerId)

变异连接: 在 df2中使用匹配将列添加到 df1

#inner
inner_join(df1, df2)
#left outer
left_join(df1, df2)
#right outer
right_join(df1, df2)
#alternate right outer
left_join(df2, df1)
#full join
full_join(df1, df2)

过滤连接: 过滤掉 df1中的行,不修改列

semi_join(df1, df2) #keep only observations in df1 that match in df2.
anti_join(df1, df2) #drops all observations in df1 that match in df2.