Более эффективное объединение совпадающего столбца с дубликатами в data.table

У меня есть два data.table s, оба из которых разделяют одну переменную; Я пытаюсь добавить переменную, которая отсутствует во второй, но привязана одна к одной к общей переменной.

Это, очевидно, слияние, но поскольку общая переменная имеет несколько экземпляров, мне нужно использовать то, что кажется обходным путем для слияния новой переменной.

Позвольте получить конкретный.

x <- data.table(let = rep(letters[1:3], 2:4),
                num = rep(1:3, 2:4), other = rnorm(9))
y <- data.table(let = rep(c("a", "c"), c(10, 6)))

x:
   let num       other
1:   a   1 -0.41695882
2:   a   1 -0.59875888
3:   b   2 -0.19433915
4:   b   2  0.58406046
5:   b   2 -0.33922321
6:   c   3 -0.63076561
7:   c   3  1.06987710
8:   c   3  0.08869372
9:   c   3 -1.31196123

y:
    let
 1:   a
 2:   a
 3:   a
 4:   a
 5:   a
 6:   a
 7:   a
 8:   a
 9:   a
10:   a
11:   c
12:   c
13:   c
14:   c
15:   c
16:   c

Я просто хочу добавить столбец num в y; поскольку num соответствует 1-1 с let, на самом деле не имеет значения, что дублируется.

Здесь работает подход; Я просто почувствовал, что там что-то проще.

setkey(x, let)
setkey(y, let)

y <- x[!duplicated(let), c("let", "num"), with = FALSE][y]

Ответ 1

Единственные улучшения, о которых я мог думать, это то, что

  • Вы можете пропустить setkey(x, let) часть

  • Вы также можете обновить y по ссылке (вместо создания копии с помощью <-, а затем вернуть обратно к y)

Если вы используете текущую стабильную версию версии data.table (v <= 1.9.4), вам нужно будет использовать allow.cartesian = TRUE

setkey(y,let)
y[x[!duplicated(let)], num := i.num, allow.cartesian = TRUE][]

В качестве альтернативы вы можете использовать unique вместо duplicated (оба они имеют методы data.table)

y[unique(x, by = "let"), num := i.num, allow.cartesian = TRUE]

Здесь другая возможность с использованием нового метода .EACHI, хотя здесь нет необходимости использовать by=.EACHI. Я показал вам просто, чтобы выставить эту функцию для вас. Посмотрите этот пост для подробного объяснения того, что это делает и когда это полезно.

y[x, num := unique(i.num), by = .EACHI, allow.cartesian = TRUE]

Изменить: (Спасибо @Arun за это указание)

Нам не нужен аргумент allow.cartesian здесь, так как в i дубликатов нет. Фактически, это ошибка, # 742, которая была исправлена ​​в текущая версия разработки (1.9.5). Поэтому вам просто нужно сделать:

y[x[!duplicated(let)], num := i.num]
# or
y[unique(x, by = "let"), num := i.num]
# or (though not recommended in this specific case)
y[x, num := unique(i.num), by = .EACHI]

Ответ 2

Ну, я бы использовал merge следующим образом, но я не уверен, что он проще, чем то, что вы уже сделали.

merge(y,unique(x[,c('let','num'), with=FALSE]), all.x=TRUE, by='let')

Ответ 3

Согласитесь с @David, сложно получить намного проще. Но ниже обрезать несколько нажатий клавиш: -)

setkey(x,let)
y<-x[!duplicated(let),.(let,num)][y]