Essa é uma pergunta filosófica sobre a sintaxe de junção data.table. Estou encontrando mais e mais usos para data.tables, mas ainda estou aprendendo ...
O formato de junção X[Y]
para data.tables é muito conciso, prático e eficiente, mas, tanto quanto posso dizer, ele suporta apenas junções internas e externas. Para obter uma junção externa esquerda ou total, preciso usar merge
:
X[Y, nomatch = NA]
- todas as linhas em Y - junção externa direita (padrão)X[Y, nomatch = 0]
- apenas linhas com correspondências em X e Y - junção internamerge(X, Y, all = TRUE)
- todas as linhas de X e Y - junção externa completamerge(X, Y, all.x = TRUE)
- todas as linhas em X - junção externa esquerda
Parece-me que seria útil se o X[Y]
formato de junção suportasse todos os 4 tipos de junções. Existe uma razão para apenas dois tipos de junções serem suportados?
Para mim, os valores de parâmetro nomatch = 0
e nomatch = NA
não são muito intuitivos para as ações que estão sendo executadas. É mais fácil para mim compreender e lembrar a merge
sintaxe: all = TRUE
, all.x = TRUE
e all.y = TRUE
. Como a X[Y]
operação se assemelha a merge
muito mais do que match
, por que não usar a merge
sintaxe para junções em vez match
do nomatch
parâmetro da função ?
Aqui estão exemplos de código dos 4 tipos de junção:
# 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
Atualização: data.table v1.9.6 introduziu a on=
sintaxe, que permite junções ad hoc em outros campos que não a chave primária. resposta de jangorecki à pergunta Como unir (mesclar) quadros de dados (interno, externo, esquerdo, direito)? fornece alguns exemplos de tipos de junção adicionais que o data.table pode manipular.
unique()
abordagem abaixo para a junção completa seja preferível rbind(Y[X],X[Y])
, uma vez que o rbind envolveria a cópia da tabela. Isso está certo?
unique(c(unique(X[,t]), unique(Y[,t]))
- isso deve ser mais eficiente em termos de memória, pois combina apenas duas listas que serão menores ou iguais ao número de linhas em X e Y .
Y[X]
se quiser que a junção externa esquerda doX[Y]
erbind(Y[X],X[Y])
se você quiser uma junção externa completa