R 为什么data.tables的X[Y]联接不允许完全外部联接或左联接?

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

这是一个关于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,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)]]