Обновить соединение с несколькими строками
Вопрос
Когда вы выполняете обновление-соединение, где таблица i
имеет несколько строк на ключ, как вы можете контролировать, какая строка возвращается?
пример
В этом примере соединение update-join возвращает последнюю строку из dt2
library(data.table)
dt1 <- data.table(id = 1)
dt2 <- data.table(id = 1, letter = letters)
dt1[
dt2
, on = "id"
, letter := i.letter
]
dt1
# id letter
# 1: 1 z
Как я могу управлять им, чтобы вернуть 1-ю, 2-ю, n-ю строку, а не по умолчанию?
Рекомендации
Несколько ссылок, подобных этому пользователю @Frank
Ответы
Ответ 1
Наиболее гибкой идеей, о которой я могу думать, является только присоединение к части dt2
которая содержит dt2
вам строки. Итак, для второй строки:
dt1[
dt2[, .SD[2], by=id]
, on = "id"
, letter := i.letter
]
dt1
# id letter
#1: 1 b
С помощью наконечника шляпы на @Frank для упрощения подвыборки dt2
.
Ответ 2
Как я могу управлять им, чтобы вернуть 1-ю, 2-ю, n-ю строку, а не по умолчанию?
Не изящные, но сорт работы:
n = 3L
dt1[, v := dt2[.SD, on=.(id), x.letter[n], by=.EACHI]$V1]
Пара проблем:
-
Он не выбирает использование GForce, например, как показано здесь:
> dt2[, letter[3], by=id, verbose=TRUE]
Detected that j uses these columns: letter
Finding groups using forderv ... 0.020sec
Finding group sizes from the positions (can be avoided to save RAM) ... 0.000sec
lapply optimization is on, j unchanged as 'letter[3]'
GForce optimized j to ''g['(letter, 3)'
Making each group and running j (GForce TRUE) ... 0.000sec
id V1
1: 1 c
-
Если для некоторых объединенных групп значение n
находится за пределами 1:.N
, предупреждение не будет выдано:
n = 40L
dt1[, v := dt2[.SD, on=.(id), x.letter[n], by=.EACHI]$V1]
В качестве альтернативы, сделайте привычку проверять, что i
в присоединении к обновлению x[i]
"привязан" к столбцам соединения:
cols = "id"
stopifnot(nrow(dt2) == uniqueN(dt2, by=cols))
И затем сделайте другую таблицу i
чтобы присоединиться, если это необходимо.
mDT = dt2[, .(letter = letter[3L]), by=id]
dt1[mDT, on=cols, v := i.letter]