Это немного философский вопрос о синтаксисе соединения 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
Обновление: data.table v1.9.6 представил on=
синтаксис, который позволяет ad hoc соединения для полей, отличных от первичного ключа. Ответ jangorecki на вопрос Как объединить (объединить) фреймы данных (внутренние, внешние, левые, правые)? предоставляет несколько примеров дополнительных типов соединений, которые может обрабатывать data.table.
unique()
подход, описанный ниже, для полного соединения предпочтительнее rbind(Y[X],X[Y])
, поскольку rbind будет включать копирование таблицы. Это правильно?
unique(c(unique(X[,t]), unique(Y[,t]))
это должно быть более эффективным с точки зрения памяти, поскольку оно объединяет только два списка, которые будут меньше или равны количеству строк в X и Y .
Y[X]
если вы хотите, чтобы левое внешнее соединение изX[Y]
иrbind(Y[X],X[Y])
если вы хотите полное внешнее соединение