【问题标题】:R - Running time by line of code in dplyrR - dplyr 中的代码行运行时间
【发布时间】:2019-08-27 18:52:54
【问题描述】:

当我想估计 R 代码的运行时间时,我使用函数system.time()

library(dplyr)

system.time({
    Titanic %>%
        as.data.frame() %>%
        mutate(Dataset = 1) %>%
        bind_rows(as.data.frame(Titanic)) %>%
        mutate_all(funs(replace_na(., NA))) %>% 
        filter(Dataset != 1)
})

# utilisateur     système      écoulé 
#        0.02        0.00        0.02

问题: 有没有办法知道每个操作的运行时间,每个管道之间的操作(mutate,然后是bind_rows,然后是filter,等等)而不需要逐个运行或不写几个@987654329 @?

在这个例子中它没有用,但有时我收到一个很长的脚本,运行时间很长,我想确定哪些操作是最低的。

我做了一些研究,但没有发现有用的东西。

【问题讨论】:

标签: r performance time dplyr


【解决方案1】:

这是对我有用的一个选项(编辑您的 NA 替换,因为 funs 已被软弃用)...诚然,它很长:

library(dplyr)
library(magrittr)
library(tictoc)

Titanic %T>%
  {tic("as.data.frame")} %>%
  as.data.frame() %T>%
  {toc(); tic("mutate")} %>%
  mutate(Dataset = 1) %T>%
  {toc(); tic("bind.rows")} %>%
  bind_rows(as.data.frame(Titanic)) %T>%
  {toc(); tic("replace.na")} %>%
  replace(is.na(.), 0) %T>% 
  {toc(); tic("filter")} %>%
  filter(Dataset != 1) %T>%
  {toc(); tic("head")} %>%
  head() %T>%
  {toc()}

as.data.frame: 0 sec elapsed
mutate: 0 sec elapsed
bind.rows: 0 sec elapsed
replace.na: 0 sec elapsed
filter: 0 sec elapsed
head: 0 sec elapsed
  Class    Sex   Age Survived Freq Dataset
1   1st   Male Child       No    0       0
2   2nd   Male Child       No    0       0
3   3rd   Male Child       No   35       0
4  Crew   Male Child       No    0       0
5   1st Female Child       No    0       0
6   2nd Female Child       No    0       0

【讨论】:

    【解决方案2】:

    您可能对我的包 pipes 中的 %L>% 管道感兴趣:

    # devtools::install_github("moodymudskipper/pipes")
    library(pipes)
    Titanic %L>%
      as.data.frame() %L>%
      mutate(Dataset = 1) %L>%
      bind_rows(as.data.frame(Titanic)) %L>%
      mutate_all(list(~replace_na(., NA))) %L>% 
      filter(Dataset != 1)
    
    # as.data.frame(.)   ~  0.03 sec
    # mutate(., Dataset = 1)   ~  0 sec
    # bind_rows(., as.data.frame(Titanic))   ~  0 sec
    # mutate_all(., list(~replace_na(., NA)))   ~  0 sec
    # filter(., Dataset != 1)   ~  0.03 sec
    # [1] Class    Sex      Age      Survived Freq     Dataset 
    # <0 rows> (or 0-length row.names)
    

    【讨论】:

    • 太棒了!关于%L&gt;% 的一个问题:它增加了代码的运行时间(通过计算不同的时间并打印结果)还是没有太多?假设我有一个很长的管道代码,我运行了好几次。我可以用%L&gt;%一次看看这段代码哪部分贵,然后把%L&gt;%去掉,或者我可以保留,每次运行,不会有这样的影响?
    • 你可以打印%L&gt;%(被反引号包围),你会看到使用了哪些额外的代码,它是一些基本的字符串操作和对system.time的调用,所以它不应该有显着影响,当然不会比昂贵的电话更重要。
    【解决方案3】:

    你可以使用包profvis:

    library(tidyverse)    
    library(profvis)
    
    profvis({
      Titanic %>%
        as.data.frame() %>%
        mutate(Dataset = 1) %>%
        bind_rows(as.data.frame(Titanic)) %>%
        mutate_all(funs(replace_na(., NA))) %>% 
        filter(Dataset != 1)
    })
    

    【讨论】:

    • 也许我错过了一些东西,但我不确定profvis 函数是否完全满足我的需要,它没有给我每行管道代码的运行时间。使用%L&gt;% 似乎更合适。
    猜你喜欢
    • 2011-11-11
    • 2012-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多