Это немного философский вопрос о синтаксисе соединения 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.
источник
Y[X]
если вы хотите, чтобы левое внешнее соединение изX[Y]
иrbind(Y[X],X[Y])
если вы хотите полное внешнее соединениеunique()
подход, описанный ниже, для полного соединения предпочтительнееrbind(Y[X],X[Y])
, поскольку rbind будет включать копирование таблицы. Это правильно?unique(c(unique(X[,t]), unique(Y[,t]))
это должно быть более эффективным с точки зрения памяти, поскольку оно объединяет только два списка, которые будут меньше или равны количеству строк в X и Y .Ответы:
Цитата из
data.table
FAQ 1.11 В чем разница междуX[Y]
иmerge(X, Y)
?Если вам нужно левое внешнее соединение
X[Y]
Если вам нужно полное внешнее соединение
источник
X[Y,all=T]
что это элегантный способ указать полное внешнее соединение в синтаксисе data.table X [Y]. ИлиX[Y,all.x=T]
для левого соединения. Я задавался вопросом, почему это не так. Просто мысль.X[Y[J(unique_keys)]]
?Ответ @mnel верен, так что примите этот ответ. Это просто продолжение, слишком длинное для комментариев.
Как говорит mnel, левое / правое внешнее соединение получается заменой
Y
иX
:Y[X]
-vs-X[Y]
. Таким образом, в этом синтаксисе поддерживаются 3 из 4 типов соединения, а не 2, iiuc.Добавление 4-го кажется хорошей идеей. Допустим, мы добавляем
full=TRUE
илиboth=TRUE
илиmerge=TRUE
(не уверены, какое имя является лучшим аргументом?), Тогда мне не приходило в голову, чтоX[Y,j,merge=TRUE]
это будет полезно по причинам, указанным после НО в FAQ 1.12. Запрос на новую функцию теперь добавлен и связан здесь, спасибо:FR # 2301: Добавить аргумент merge = TRUE для объединения X [Y] и Y [X], как это делает merge ().
Последние версии ускорились
merge.data.table
(например, за счет создания внутренней копии для более эффективной установки ключей). Таким образом , мы пытаемся принестиmerge()
иX[Y]
ближе, и предоставить все возможности для пользователя , для полной гибкости. У обоих есть плюсы и минусы. Еще один выдающийся запрос функции:FR # 2033: Добавить by.x и by.y в таблицу merge.data.table
Если есть другие, пожалуйста, продолжайте их приходить.
По этой части вопроса:
Если вы предпочитаете
merge()
синтаксис и его 3 -х аргументовall
,all.x
аall.y
затем просто использовать , что вместоX[Y]
. Думаю, он должен охватывать все случаи. Или вы имеете в виду , почему это аргумент одинnomatch
в[.data.table
? Если так, то это казалось естественным, учитывая FAQ 2.14: «Не могли бы вы объяснить, почему data.table вдохновлен синтаксисом A [B] в base?». Но также вnomatch
настоящее время принимает только два значения0
иNA
. Это можно было бы расширить так, чтобы отрицательное значение что-то означало, или 12 означало бы использование значений 12-й строки для заполнения, например, NA, илиnomatch
в будущем могло бы быть вектором или даже самим adata.table
.Гектометр Как бы by-without-by взаимодействовал с merge = TRUE? Возможно, нам следует передать это в справку по данным .
источник
join="all", join="all.x", join="all.y" and join="x.and.y"
пометки на полях своих заметок. Не уверен, что это лучше.join
так, хорошая идея. Я отправил в справку по данным, так что давайте посмотрим. Может бытьdata.table
, тоже дадим немного времени, чтобы осесть. Вы, например, уже успели перейти в режим by-without-by и присоединиться к унаследованной области ?join
ключевое слово к, когда я это DataTable:X[Y,j,join=string]
. Предлагаются следующие возможные строковые значения для соединения: 1) "all.y" и "right" -Это «ответ» это предложение для обсуждения: Как указано в моем комментарии, я предлагаю добавить
join
параметр [.data.table () , чтобы включить дополнительные типы соединений, то есть:X[Y,j,join=string]
. В дополнение к 4 типам обычных объединений я также предлагаю поддерживать 3 типа эксклюзивных объединений и перекрестное соединение.Предлагаются следующие
join
строковые значения (и псевдонимы) для различных типов соединений:"all.y"
и"right"
- правое соединение, настоящее значение data.table default (nomatch = NA) - все Y строк с NA, где нет совпадений X;"both"
и"inner"
- внутреннее соединение (nomatch = 0) - только строки, в которых совпадают X и Y;"all.x"
и"left"
- левое соединение - все строки из X, NA, где нет совпадений Y:"outer"
и"full"
- полное внешнее соединение - все строки из X и Y, NA, где нет совпадений"only.x"
и"not.y"
- несоединение или антисоединение, возвращающее X строк, где нет соответствия Y"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.
источник
join
но если он не попадет на трекер, он забудется.