给定两个数据帧:
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.