Реплицируйте порядок столбцов dplyr::left_join() с помощью синтаксиса data.table x[y]

#r #dplyr #data.table

Вопрос:

Я переключаю множество своих конвейеров обработки данных с dplyr на data.table из-за повышения производительности. Мне нравится лаконичность a[b] синтаксиса соединений. dplyr::left_join(x, y) соответствует y[x] в. data.table Однако порядок столбцов в обоих случаях разный. Есть ли способ воспроизвести порядок столбцов , который вы получаете из dplyr left_join , где новые столбцы y добавляются в правую часть x , используя y[x] синтаксис data.table? Я знаю, что вы можете использовать merge(x, y, all.x = TRUE) , но мне было любопытно, может ли этот [] способ достичь того же результата.

пример

 library(dplyr)
library(data.table)

x <- iris
y <- data.frame(Species = c('setosa', 'virginica'), foo = c(100, 200))

j1 <- left_join(x, y)

setDT(x)
setDT(y)

j2 <- y[x, on = 'Species']

j3 <- merge(x, y, all.x = TRUE)
 

Как мне сделать j2 так, чтобы порядок столбцов был таким же, как j1 и и j3 ?

 > head(j1, 1)
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species foo
1:          5.1         3.5          1.4         0.2  setosa 100
> head(j2, 1)
   Species foo Sepal.Length Sepal.Width Petal.Length Petal.Width
1:  setosa 100          5.1         3.5          1.4         0.2
> head(j3, 1)
   Species Sepal.Length Sepal.Width Petal.Length Petal.Width foo
1:  setosa          5.1         3.5          1.4         0.2 100
 

Ответ №1:

Мы можем выполнить задание ( := ), которое было бы более эффективным, как это делается по ссылке

 j2 <- copy(x)
j2[y, foo := foo, on = .(Species)]
 

-тестирование

 all.equal(j1, type.convert(as.data.frame(j2), as.is = TRUE))
#[1] TRUE
 

Комментарии:

1. Если есть несколько столбцов, y отличных от столбца, к которому мы присоединяемся, не потребуется ли для этого назначить их все := ?

2. @qdread Если их больше, например, foo1, nm1 <- names(y)[3:5] foo2 и т.д. , То j2[y, (nm1) := mget(nm1), on = .(Species)]

3. Или, если это все столбцы, кроме «Видов», nm1 <- setdiff(names(y), 'Species') а затем примените тот же код

4. Это хороший ответ, но в конце концов я думаю, что код в конечном итоге будет более подробным, чем merge() способ, так что я могу просто придерживаться этого!

5. @qdread Я бы сказал := , что должно быть быстрее