Dou*_*ark 115 join r data.table
这是关于data.table连接语法的一个哲学问题.我发现data.tables的用途越来越多,但仍在学习......
X[Y]
data.tables 的连接格式非常简洁,方便和高效,但据我所知,它只支持内连接和右外连接.要获得左外部或全外部连接,我需要使用merge
:
X[Y, nomatch = NA]
- Y中的所有行 - 右外连接(默认)X[Y, nomatch = 0]
- 只有在X和Y中都匹配的行 - 内连接merge(X, Y, all = TRUE)
- 来自X和Y的所有行 - 完全外部连接merge(X, Y, all.x = TRUE)
- X中的所有行 - 左外连接在我看来,如果X[Y]
连接格式支持所有4种类型的连接,那将会很方便.有没有理由只支持两种类型的连接?
对我来说,nomatch = 0
和nomatch = NA
参数值对于正在执行的操作不是非常直观.这是我更容易理解和记忆的merge
语法:all = TRUE
,all.x = TRUE
和all.y = TRUE
.由于X[Y]
操作类似于merge
远远不止match
,为什么不使用merge
的连接,而不是语法match
功能的nomatch
参数?
以下是4种连接类型的代码示例:
# sample X and Y data.tables
library(data.table)
X <- data.table(t = 1:4, a = (1:4)^2)
setkey(X, t)
X
# t a
# 1: 1 1
# 2: 2 4
# 3: 3 9
# 4: 4 16
Y <- data.table(t = 3:6, b = (3:6)^2)
setkey(Y, t)
Y
# t b
# 1: 3 9
# 2: 4 16
# 3: 5 25
# 4: 6 36
# all rows from Y - right outer join
X[Y] # default
# t a b
# 1: 3 9 9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36
X[Y, nomatch = NA] # same as above
# t a b
# 1: 3 9 9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36
merge(X, Y, by = "t", all.y = TRUE) # same as above
# t a b
# 1: 3 9 9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36
identical(X[Y], merge(X, Y, by = "t", all.y = TRUE))
# [1] TRUE
# only rows in both X and Y - inner join
X[Y, nomatch = 0]
# t a b
# 1: 3 9 9
# 2: 4 16 16
merge(X, Y, by = "t") # same as above
# t a b
# 1: 3 9 9
# 2: 4 16 16
merge(X, Y, by = "t", all = FALSE) # same as above
# t a b
# 1: 3 9 9
# 2: 4 16 16
identical( X[Y, nomatch = 0], merge(X, Y, by = "t", all = FALSE) )
# [1] TRUE
# all rows from X - left outer join
merge(X, Y, by = "t", all.x = TRUE)
# t a b
# 1: 1 1 NA
# 2: 2 4 NA
# 3: 3 9 9
# 4: 4 16 16
# all rows from both X and Y - full outer join
merge(X, Y, by = "t", all = TRUE)
# t a b
# 1: 1 1 NA
# 2: 2 4 NA
# 3: 3 9 9
# 4: 4 16 16
# 5: 5 NA 25
# 6: 6 NA 36
Run Code Online (Sandbox Code Playgroud)
更新:data.table v1.9.6引入了on=
语法,该语法允许在主键以外的字段上进行临时连接.jangorecki对问题如何连接(合并)数据框(内部,外部,左侧,右侧)的回答?提供了data.table可以处理的其他连接类型的一些示例.
mne*_*nel 70
引用data.table
FAQ 1.11 X[Y]
和merge(X, Y)
?之间的区别是什么?
X[Y]
是一个连接,使用Y(或Y的键,如果有的话)作为索引查找X的行.
Y[X]
是一个连接,使用X查找Y的行(如果有X,则查找X的键)
merge(X,Y)
同时做两种方式.行数X[Y]
和Y[X]
通常不同,而返回的行数merge(X,Y)
和merge(Y,X)
相同.但是错过了重点.大多数任务需要在连接或合并后对数据执行某些操作.为什么要合并所有数据列,之后只使用它们中的一小部分?您可能会建议
merge(X[,ColsNeeded1],Y[,ColsNeeded2])
,但这需要程序员确定需要哪些列.X[Y,j
]在data.table中为您完成所有这一切.编写时X[Y,sum(foo*bar)]
,data.table会自动检查j
表达式以查看它使用的列.它只会仅对这些列进行子集化; 其他人被忽略了.仅为j
使用的列创建内存,并且Y
列在每个组的上下文中享有标准R回收规则.假设foo
是X
,并且bar在Y
(以及其他20列Y
)中.是不是X[Y,sum(foo*bar)]
更快的编程和快于一切的合并浪费后跟一个子集运行?
如果你想要一个左外连接 X[Y]
le <- Y[X]
mallx <- merge(X, Y, all.x = T)
# the column order is different so change to be the same as `merge`
setcolorder(le, names(mallx))
identical(le, mallx)
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)
如果你想要一个完整的外部联接
# the unique values for the keys over both data sets
unique_keys <- unique(c(X[,t], Y[,t]))
Y[X[J(unique_keys)]]
## t b a
## 1: 1 NA 1
## 2: 2 NA 4
## 3: 3 9 9
## 4: 4 16 16
## 5: 5 25 NA
## 6: 6 36 NA
# The following will give the same with the column order X,Y
X[Y[J(unique_keys)]]
Run Code Online (Sandbox Code Playgroud)
Mat*_*wle 22
@ mnel的答案是现场,所以接受这个答案.这只是跟进,对于评论来说太长了.
作为MNEL说,左/右外连接是通过交换获得Y
和X
:Y[X]
航班吗X[Y]
.因此,在该语法中支持4种连接类型中的3种,而不是2,iiuc.
添加第4个似乎是一个好主意.假设我们添加full=TRUE
或者(both=TRUE
或者merge=TRUE
不确定最佳参数名称?)然后在我之前没有想到它X[Y,j,merge=TRUE]
对于在FAQ 1.12中的BUT之后的原因有用.新功能请求现已添加并链接回此处,谢谢:
FR#2301:像merge()一样为X [Y]和Y [X]连接添加merge = TRUE参数.
最近的版本已经加速merge.data.table
(例如,通过在内部采用浅拷贝来更有效地设置密钥).因此,我们正试图把merge()
和X[Y]
密切,并提供给用户的所有选项充分的灵活性.两者都有利弊.另一项出色的功能要求是:
FR#2033:将by.x和by.y添加到merge.data.table
如果还有其他人,请保持他们的到来.
通过这部分问题:
为什么不使用合并语法进行连接而不是匹配函数的nomatch参数?
如果你喜欢merge()
的语法和它的3个参数all
,all.x
并且all.y
然后就用这个来代替X[Y]
.认为它应涵盖所有情况.或者你的意思是为什么这个论点是单一nomatch
的[.data.table
?如果是这样的话,这就是常见问题解答2.14:"你能进一步解释为什么data.table受到基础中A [B]语法的启发吗?".而且,nomatch
只需要目前两个值0
和NA
.这可以延长,以便负值意味着某些东西,或者12意味着使用第12行的值来填充NA,例如,或者nomatch
将来可能是向量甚至是自身a data.table
.
嗯.by-without-by如何与merge = TRUE交互?也许我们应该把这个转到datatable-help.
Dou*_*ark 16
这个"答案"是一个讨论的提议:如我的评论中所示,我建议join
在[.data.table()中添加一个参数以启用其他类型的连接,即:X[Y,j,join=string]
.除了4种类型的普通连接外,我还建议支持3种类型的独占连接和交叉连接.
join
建议各种连接类型的字符串值(和别名)为:
"all.y"
和"right"
- 右连接,当前data.table默认值(nomatch = NA) - 所有Y行与没有X匹配的NA;"both"
和"inner"
- 内连接(nomatch = 0) - 只有X和Y匹配的行;
"all.x"
和"left"
- 左连接 - 来自X,NAs的所有行,其中没有Y匹配:
"outer"
和"full"
- 完全外连接 - 来自X和Y的所有行,NAs不匹配
"only.x"
和"not.y"
-非连接或反连接返回X行里没有ÿ匹配
"only.y"
和"not.x"
-非连接或反连接返回y行不存在X匹配"not.both"
- 独占连接返回X和Y行,其中与另一个表不匹配,即异或(XOR)"cross"
- 交叉连接或笛卡尔积,每行X与Y的每一行匹配默认值join="all.y"
对应于当前默认值.
"all","all.x"和"all.y"字符串值对应于merge()
参数."右","左","内"和"外"字符串可能更适合SQL用户.
"both"和"not.both"字符串是我目前最好的建议 - 但有人可能对内连接和独占连接有更好的字符串建议.(我不确定"独占"是否是正确的术语,如果有"XOR"连接的正确术语,请纠正我.)
使用join="not.y"
是一种替代 X[-Y,j]
或X[!Y,j]
无连接语法,也许更清楚(我),虽然我不知道他们是相同的(在data.table版本1.8.3的新功能).
交叉连接有时候很方便,但它可能不适合data.table范例.