Вставка кода data.table из dtplyr приводит к более медленному коду - PullRequest
2 голосов
/ 13 февраля 2020

Сегодня я начал переносить часть своего кода из dplyr в dtplyr, и когда я понял, мне будет относительно просто скопировать и вставить код data.table из объекта "dtplyr_step_mutate", "dtplyr_step", полученного из вызова lazy_dt () без вызова as_tibble (). Отсюда я мог бы закомментировать код dtplyr, чтобы сохранить читабельность dplyr при получении скорости data.table.

Однако, когда я сделал это, я заметил, что dtplyr будет выводить код data.table, который иногда медленнее, чем его аналог dtplyr. Кажется, это go против интуиции, что dtplyr всегда должен быть медленнее, чем data.table из-за затрат на перевод. Любые идеи, почему это может иметь место? В документации отмечается, что перевод dplyr :: mutate в терминологию data.table не идеален. Возможно, в этом причина?

представ:

library(tibble)
library(data.table)
library(dplyr,warn.conflicts = F)
library(dtplyr)
library(stringr)
library(magrittr)
library(microbenchmark)

test <- data.table(id= 1:2600000,a = rnorm(2600000),b = letters %>% rep(100000),.name_repair = 'universal') 
test2 <- data.table(id= 1:2600000,c = rnorm(2600000),.name_repair = 'universal') 


#copy call to data.table and paste into test4
test3 <- test %>% lazy_dt() %>% 
filter(str_detect(b,'[a-d]')) %>%  distinct(b,.keep_all = T) %>% 
inner_join(test2,by = 'id') %>%  mutate(.,x = rnorm(nrow(.))) #%>%  as_tibble() 

#change names of temporary tables to actual table names
test4 <- merge(unique(test[str_detect(b, "[a-d]")], by = "b"), test2, 
               all = FALSE, by.x = "id", by.y = "id", allow.cartesian = TRUE)[, `:=`(x = rnorm(nrow(.SD)))]

microbenchmark(dtplyr = test %>% lazy_dt() %>% 
                 filter(str_detect(b,'[a-d]')) %>%  distinct(b,.keep_all = T) %>% 
                 inner_join(test2,by = 'id') %>%  mutate(.,x = rnorm(nrow(.))) %>%  as_tibble() ,
                data.table = merge(unique(test[str_detect(b, "[a-d]")], by = "b"), test2, 
                      all = FALSE, by.x = "id", by.y = "id", allow.cartesian = TRUE)[, `:=`(x = rnorm(nrow(.SD)))])


Unit: milliseconds
       expr      min       lq     mean   median       uq      max neval
     dtplyr 465.2541 482.8849 502.2006 491.0723 503.6764 784.2746   100
 data.table 463.0258 480.6790 504.4545 494.1416 520.1842 588.5371   100

Интересно отметить, что dtplyr не всегда был медленнее, чем data.table здесь. Я не совсем уверен, почему я вижу то, что вижу здесь.

РЕДАКТИРОВАТЬ: Перефразируя вопрос, чтобы быть более ясным. Мой мыслительный процесс заключается в том, что если мне никогда не придется никому показывать свой код, то я всегда должен использовать data.table, поскольку он работает быстрее, чем dtplyr. Однако, основываясь на моем опыте сравнительного анализа, кажется, что бывают случаи, когда dtplyr работает быстрее, чем data.table. Почему? Кажется, интуиция подсказывает, что этого никогда не должно происходить. Я неправильно понимаю, что делает dtplyr?

...