给定两个数据帧:
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和df2的内部连接:仅返回左表在右表中具有匹配键的行。df1和df2的外部连接:返回两个表中的所有行,连接左侧表中具有匹配键的记录。df1和df2的左外联接(或简单的左联接)返回左表中的所有行,以及右表中具有匹配键的所有行。df1和df2的右外部连接返回右表中的所有行,以及左表中具有匹配键的所有行。
额外学分:
如何执行SQL样式的选择语句?
内部连接有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函数。【2022年注意:plyr现已退役,并已被dplyr取代。dplyr中的连接操作在本答案中描述。】
library(plyr)
join(df1, df2,
type = "inner")
# CustomerId Product State
# 1 2 Toaster Alabama
# 2 4 Radio Alabama
# 3 6 Radio Ohio
类型选项:内部、左侧、右侧、完整。
从…起join:与merge不同,[join]保留x的顺序,无论使用何种连接类型。
对于所有列上的内部联接,还可以使用data.table-package中的finteract或dplyr包中的intersect作为合并的替代方法,而不指定by列。这将给出两个数据帧之间相等的行:
merge(df1, df2)
# V1 V2
# 1 B 2
# 2 C 3
dplyr::intersect(df1, df2)
# V1 V2
# 1 B 2
# 2 C 3
data.table::fintersect(setDT(df1), setDT(df2))
# V1 V2
# 1: B 2
# 2: C 3
示例数据:
df1 <- data.frame(V1 = LETTERS[1:4], V2 = 1:4)
df2 <- data.frame(V1 = LETTERS[2:3], V2 = 2:3)
dplyr从0.4开始实现了包括outer_join在内的所有连接,但值得注意的是,在0.4之前的前几个版本中,因此,在之后的相当长一段时间里,有很多非常糟糕的黑客解决方法用户代码(你仍然可以在那个时期的SO、Kaggle answers和github中找到这样的代码。因此,这个答案仍然有用。)
加入相关发布亮点:
版本0.5(2016年6月)
POSIXct类型、时区、重复项、不同因素级别的处理。更好的错误和警告。新后缀参数,用于控制重复变量名称接收的后缀(#1296)
版本0.4.0(2015年1月)
实施右联接和外联接(#96)可变联接,它从另一个表中的匹配行向一个表添加新变量。过滤联接,根据观察值是否与另一个表中的观察值匹配来过滤一个表的观察值。
版本0.3(2014年10月)
现在可以通过每个表中的不同变量进行left_join:df1%>%left_join(df2,c(“var1”=“var2”))
0.2版(2014年5月)
*_join()不再重新排序列名(#324)
版本0.1.3(2014年4月)
具有inner_join、left_join、semi_join、anti_joinouter_join尚未实现,回退是使用base::merge()(或plyr::join())尚未实现right_join和outer_join哈德利在这里提到了其他优势目前,dplyr所没有的一个小特性是,可以像Python panda那样,通过.x和.y列进行分隔。
根据哈德利在该问题中的评论采取的解决方法:
就行而言,rightjoin(x,y)与leftjoin(y,x)相同,只是列的顺序不同。轻松使用select(new_column_order)outer_join基本上是并集(leftjoin(x,y),rightjoin(y,x)),即保留两个数据帧中的所有行。
通过使用merge函数及其可选参数:
内部连接:merge(df1,df2)将适用于这些示例,因为R会通过公共变量名自动连接帧,但您很可能希望指定merge(df1,df1,by=“CustomerId”),以确保仅在所需字段上匹配。如果匹配变量在不同的数据帧中具有不同的名称,也可以使用by.x和by.y参数。
外部联接:合并(x=df1,y=df2,by=“CustomerId”,all=TRUE)
左外部:合并(x=df1,y=df2,by=“CustomerId”,all.x=TRUE)
右外部:合并(x=df1,y=df2,by=“CustomerId”,all.y=TRUE)
交叉联接:合并(x=df1,y=df2,by=NULL)
与内部联接一样,您可能希望将“CustomerId”显式传递给R作为匹配变量。我认为几乎总是最好明确说明要合并的标识符;如果输入data.frames发生意外变化,则会更安全,并且以后更容易阅读。
您可以通过给定向量(例如,by=c(“CustomerId”,“OrderId”))合并多个列。
如果要合并的列名不相同,则可以指定,例如,by.x=“CustomerId_in_df1”,by.y=“CustomerId.in_df2”,其中CustomerId_in_df1是第一个数据帧中的列名,CustomerId_in-df2是第二个数据帧的列名。(如果需要合并多个列,这些也可以是向量。)