协慌网

登录 贡献 社区

如何连接(合并)数据框(内部,外部,左侧,右侧)

给出两个数据框:

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 风格,加入 ?也就是说,我该怎么做:

  • df1df2内连接
    仅返回左表在右表中具有匹配键的行。
  • df1df2外连接
    返回两个表中的所有行,从左侧连接具有右表中匹配键的记录。
  • df1df2 左外连接(或简称左连接)
    返回左表中的所有行,以及右表中具有匹配键的所有行。
  • df1df2 右外连接
    返回右表中的所有行,以及左表中具有匹配键的所有行。

额外信用:

如何进行 SQL 样式选择语句?

答案

通过使用merge函数及其可选参数:

内部联接 merge(df1, df2)将适用于这些示例,因为 R 通过公共变量名称自动加入帧,但您很可能希望指定merge(df1, df2, by = "CustomerId")以确保您只匹配你想要的字段。如果匹配变量在不同数据框中具有不同的名称,也可以使用by.xby.y参数。

外连接: merge(x = df1, y = df2, by = "CustomerId", all = TRUE)

左外: merge(x = df1, y = df2, by = "CustomerId", all.x = TRUE)

右外: merge(x = df1, y = df2, by = "CustomerId", all.y = TRUE)

交叉连接: merge(x = df1, y = df2, by = NULL)

与内连接一样,您可能希望将 “CustomerId” 显式传递给 R 作为匹配变量。我认为最好明确说明要合并的标识符; 如果输入 data.frames 意外更改并且稍后更容易阅读,则更安全。

您可以by向量给by合并多个列,例如, by = c("CustomerId", "OrderId")

如果要合并的列名不相同,则可以指定例如by.x = "CustomerId_in_df1", by.y = "CustomerId_in_df2" ,其中CustomerId_in_df1是第一个数据框中列的名称, CustomerId_in_df2是第二个数据框中列的名称。 (如果需要在多个列上合并,这些也可以是向量。)

我建议查看Gabor Grothendieck 的 sqldf 包 ,它允许您在 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 的 sqldf GitHub

内连接有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)

stackoverflow 上记录的 data.table:
如何进行 data.table 合并操作
将外键上的 SQL 连接转换为 R data.table 语法
合并更大数据的有效替代方案。框架 R
如何在 R 中使用 data.table 进行基本的左外连接?

另一个选项是plyr包中的join函数

library(plyr)

join(df1, df2,
     type = "inner")

#   CustomerId Product   State
# 1          2 Toaster Alabama
# 2          4   Radio Alabama
# 3          6   Radio    Ohio

type选项: innerleftrightfull

来自?join :与merge不同,无论使用何种连接类型,[ join ] 都会保留 x 的顺序。