R 为什么data.tables的X[Y]联接不允许完全外部联接或左联接?
这是一个关于data.table连接语法的哲学问题。我发现data.tables的用途越来越多,但仍在学习 data.tables的联接格式R 为什么data.tables的X[Y]联接不允许完全外部联接或左联接?,r,join,data.table,R,Join,Data.table,这是一个关于data.table连接语法的哲学问题。我发现data.tables的用途越来越多,但仍在学习 data.tables的联接格式X[Y]非常简洁、方便和高效,但据我所知,它只支持内部联接和右外部联接。要获得左连接或完全外部连接,我需要使用合并: X[Y,nomatch=NA]--Y中的所有行--右外部联接(默认) X[Y,nomatch=0]--仅在X和Y中都匹配的行--内部联接 merge(X,Y,all=TRUE)--来自X和Y的所有行--完全外部联接 merge(X,Y,al
X[Y]
非常简洁、方便和高效,但据我所知,它只支持内部联接和右外部联接。要获得左连接或完全外部连接,我需要使用合并:
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]
join格式支持所有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
#示例X和Y数据表
库(数据表)
从数据表中引用X
X[Y]
是一个连接,使用Y(或Y的键,如果有)作为索引查找X的行
Y[X]
是一个连接,使用X(或X的键,如果有)查找Y的行
merge(X,Y)
同时执行两种方式。X[Y]
和Y[X]
的行数通常不同,而merge(X,Y)
和merge(Y,X)
返回的行数相同
但这没有抓住要点。大多数任务都需要在计算机上完成
连接或合并后的数据。为什么要合并所有数据列,只合并到
之后使用它们的一小部分?你可以建议
merge(X[,ColsNeeded1],Y[,ColsNeeded2])
,但这需要程序员确定需要哪些列X[Y,j
]在一个步骤中为
你。当您写入X[Y,sum(foo*bar)]
时,data.table会自动检查j
表达式以查看它使用的列。它只会将这些列子集化;其他的都被忽略了。仅为j
使用的列创建内存,Y
列在每个组的上下文中使用标准的R循环规则。假设foo
在X
中,bar在Y
中(以及Y
中的其他20列)。难道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
le@mnel的答案是正确的,所以一定要接受这个答案。这只是跟进,评论太长了
正如mnel所说,左/右外部联接是通过交换Y
和X
:Y[X]
-vs-X[Y]
获得的。因此,该语法支持4种连接类型中的3种,而不是2种,iiuc
添加第四个似乎是个好主意。假设我们添加full=TRUE
或both=TRUE
或merge=TRUE
(不确定最佳参数名称?),那么我以前从未想到X[Y,j,merge=TRUE]
会对FAQ 1.12中的原因有用。新功能请求现已添加并链接回此处,谢谢:
最近的版本加快了merge.data.table
(例如,通过在内部进行浅拷贝来更有效地设置键)。因此,我们正试图使merge()
和X[Y]
更接近,并为用户提供所有选项,以实现完全的灵活性。两者都有利弊。另一个突出的功能要求是:
如果还有其他人,请让他们来
在问题的这部分:
为什么不为联接使用合并语法而不是match函数的nomatch参数
如果您更喜欢merge()
语法及其3个参数all
、all.x
和all.y
,那么只需使用它而不是x[y]
。我认为它应该涵盖所有的案例。或者你的意思是为什么在[.data.table
中,参数是单一的nomatch
?如果是这样的话,这就是FAQ 2.14中看起来很自然的方式:“你能进一步解释为什么data.table受base中[B]语法的启发吗?”但是,nomatch
目前只接受两个值0
和NA
。这两个值可以扩展为负值,或者12意味着使用第12行的值来填充NAs,例如,nomatch
将来可能是一个向量,甚至本身就是一个数据。表
嗯。如果没有merge=TRUE,我们将如何进行交互?也许我们应该把这个问题交给。这个“答案”是一个供讨论的建议:如我的评论所示,我建议在[.data.table()中添加一个join
参数,以启用其他类型的联接,即:X[Y,j,join=string]
。除了4种普通联接之外,我还建议支持3种独占联接和交叉联接
各种连接类型的join
字符串值(和别名)建议为:
“all.y”
和“right”
——右连接,当前数据表默认值(nomatch=NA)——
全Y罗
# 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)]]