join - R( 内部,外部, 左, 右) 如何联接数据帧?

  显示原文与译文双语对照的内容

给定两个数据帧


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样式,连接? 也就是说,我如何获得:

  • df1和df1的内部联接
  • df1和df2的外部联接
  • 一个df1和 df2 LEFT OUTER 联接,
  • df1和df2的右外部联接

P.S 。IKT-JARQ ( 我知道这一点- 只是添加 R 问题)

额外的信用:

如何执行sql样式选择语句?

时间:

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

的内部连接:merge(df1, df2) 将为这些示例工作,因为 R 会自动将这些框架加入到框架中,但是你很可能希望指定 merge(df1, df2, by="CustomerId"),以确保你只在需要的字段上进行匹配。 如果匹配变量在不同的数据帧中具有不同的名称,也可以使用 by.x 和 by.y 参数。

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

LEFT OUTER: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 意外更改,并且以后更容易阅读,则会更安全。

投入sql,我会推荐你去伽伯 sqldf Grothendieck包,它允许你表述这些操作组成


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偏见) 更简单更自然。

于更多information,请参阅相关 sqldf的伽柏 Google Code 页

对于一个内部联接,有英镑的data.table 方法,它是时间和内存高效的( 对于某些较大的数据,也需要。框架):


 if(!require(data.table)){install.packages("data.table")}

 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)))

 dt1<-data.table(df1, key="CustomerId") 
 dt2<-data.table(df2, key="CustomerId")

 joined.dt1.dt.2<-dt1[dt2]

合并也适用于 data.tables:

 
merge(dt1, dt2)

 

data.table 上文档的:
R: 如何执行 data.table 合并操作
将外键上的SQL联接转换为 R data.table 语法
于较大 data.frames 相关 R, 高效替代方案合并
如何做一个基本的与 data.table LEFT OUTER 联接

另一个选项是在 plyr 软件包中找到的join() 函数


library(plyr)

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

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

类型的选项

  • 内部
  • 左边
  • 右边
  • 已满

R Wiki页面中有一些不错的例子。 我在这里偷一对:

合并方法

由于你的密钥被命名为相同的,所以执行内部联接的短方法是 merge():

 
merge(df1,df2)

 

随着"全部"keyword,一个完整的内部联接( 来自两个表中的所有记录) 可以 created:


merge(df1,df2, all=TRUE)

一个的df1 LEFT OUTER 联接和 df2:


merge(df1,df2, all.x=TRUE)

df1和df2的右外部联接:


merge(df1,df2, all.y=TRUE)

你可以翻转'em,slap'并将它们擦下,以获得你所询问的其他两个外部连接:)

下标方法

在左边使用下标的方法将be,一个与 LEFT OUTER 加入


df1[,"State"]<-df2[df1[,"Product"],"State"]

外部联接的其他组合可以由mungling创建 LEFT OUTER 联接下标示例。 ( 是的,我知道这相当于"我将把它留给读者练习。")

你也可以使用Hadley的新的dplyr 软件包来进行加入。

你可以使用dplyr在原始问题中完成大多数连接


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)


#inner
inner_join(df1, df2)

#left outer
left_join(df1, df2)

#right outer (just reverse argument order)
left_join(df2, df1)

在 2014中新建:

特别是如果你也有兴趣在数据操作一般情况下( 包括排序,筛选,子集化和摘要),你绝对应该看一下 dplyr,它自带了多种功能它们都可用来促进你的工作特别是使用数据帧和一些其他的数据库类型。 它甚至提供了相当复杂的SQL接口,甚至是一个将( 大多数) SQL代码直接转换为 R的函数。

在dplyr包比较四个 joining-related functions:

  • inner_join(x, y, by = NULL, copy = FALSE,.. .) :返回中的所有行,其中有匹配的值,以及来自x 和y的所有列
  • left_join(x, y, by = NULL, copy = FALSE,.. .) :返回来自x的所有行,以及来自x 和y的所有列
  • semi_join(x, y, by = NULL, copy = FALSE,.. .) :从中返回匹配值的所有行,只保留来自x的列。
  • anti_join(x, y, by = NULL, copy = FALSE,.. .) :返回中没有匹配值的所有行,只保留来自x的列

这里所有的都是

选择列可以由 select(df,"column") 完成。 如果不是SQL-ish讲到这你,然后会有但 as-is sql() 功能方面,用户可以输入SQL代码,并且它将完成你指定的操作就像你在编写 R 业务工作中( 有关更多信息,请参考 dplyr/数据库小插图 。 例如如果应用正确, sql("SELECT * FROM hflights") 将从"hflights"dplyr表( 一个"中选择所有列。

dplyr非常好和高性能。 除了上面的其他答案,这里的状态是/

v0.1.3 ( 4/2014 )

在这里问题中,每个hadley的评论:

  • right_join ( x,y ) 与 left_join(y,x) 相同,只是列的顺序不同。 使用 select(new_column_order ) 轻松变通
  • outer_join 基本上是 union(left_join(x, y), right_join(x, y)) - 换句话说,保留两个数据帧中的所有行。

在与 ~1 百万行每个连接两个数据帧,一个与 2栏目和另一个用 ~20, 我曾令人惊讶的是发现 merge(..., all.x = TRUE, all.y = TRUE) 要比 dplyr::full_join() 更快。 这是 dplyr v0.4

合并需要 ~17 秒,full_join需要 ~65 秒。

因为我通常默认为dplyr操作任务的一些食物。

...