2

我今天开始将我的一些代码从 dplyr 迁移到 dtplyr,当我意识到从调用 lazy_dt()无需调用 as_tibble()。从这里我可以注释掉 dtplyr 代码以保持 dplyr 的可读性,同时获得 data.table 的速度。

然而,当我这样做时,我注意到 dtplyr 会输出有时比它的 dtplyr 对应物慢的 data.table 代码。由于翻译成本,这似乎违背了 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 的作用吗?

4

0 回答 0