【问题标题】:Is it possible to make data.table code faster?是否可以使 data.table 代码更快?
【发布时间】:2019-07-25 15:32:43
【问题描述】:

我决定将我的代码从 dplyr 重写为 data.table,因为我听说它更快。

令人惊讶的是,我设法在执行时间上只获得了微不足道的加速。是我的数据太小还是我写的 data.table 风格很糟糕?

除了输出的类之外,结果是相同的。

我没有故意使用 setDT(),因为它是主观的。

编辑:我做了一个类似的可重现的例子。

pacman::p_load(gapminder, data.table, dplyr, stringr, microbenchmark)

gapminder -> gapminder
as_tibble(gapminder) -> gapminder_tibble
as.data.table(gapminder) -> gapminder_data.table

microbenchmark(
  dplyr = {
    gapminder_tibble %>% 
      filter(year > 1900, year < 1990) %>% 
      mutate(country = str_sub(str_to_lower(country), 5)) %>% 
      count(country)
  },

  data.table = {
    gapminder_data.table[year > 1900 & year < 1990][, country := str_sub(str_to_lower(country), 5)][, .(n = .N), by = country]
  },

  times = 1000
)

Data.table 代码更慢...

Unit: milliseconds
       expr      min       lq     mean   median       uq     max neval cld
      dplyr 2.441601 2.756801 3.165089 2.965350 3.181802 29.1171  1000  a 
 data.table 2.646601 3.101201 3.548372 3.383252 3.661500 11.9474  1000   b

这是为什么呢?如何让它更快?有什么建议吗?在data.table中最快的写法是什么?

【问题讨论】:

  • 你可以setkey让它运行得更快一点
  • 很大程度上取决于您执行此操作的行数。我通常使用超过 100.000 行的 data.table。当处理 1.000.000 及更多时,差异非常显着。在您的情况下,尤其是 mutate 和 group_by (在计数内)应该在 data.table 中表现更好。
  • 当您执行基准测试时,请确保您将苹果与苹果进行比较。目前,您在每次迭代中都使用as.data.table,这会导致一些(轻微但可能不是微不足道的)开销。比较应该只是核心问题,在微基准测试之前完成了任何up front and only once 工作。
  • 如果您制作了一个可重现的示例,将会很有用。
  • 3 毫秒已经如此之快,以至于此示例无法说明需要提高速度的情况。不过,通常使用较大的数据和某些操作会有一些好处。

标签: r performance dplyr data.table


【解决方案1】:

您可以通过避免(不必要的)链接和切换str_to_lower()str_sub() 的操作顺序来简化一点(无需转换为我们要丢弃的小写字母)

gapminder_data.table[year > 1900 & year < 1990, 
                     .(n = .N), 
                     by = .(country = str_to_lower(str_sub(country, 5)))]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    相关资源
    最近更新 更多