大数据框上的group_by和mutate变慢

fle*_*lee 5 r dataframe data.table tidyverse

我正在处理大型行(最少8百万行),dataframes并且希望基于几个分组变量和进行一些基本计算rmultinom。按照我的代码立场,至少需要大约1秒钟才能完成计算,这不是问题,但是我需要做数千次,所以我真的想加快速度。

我当前正在使用dataframestidyverse但我与这两个都不相关。我试图实现使用,data.table但无法弄清楚。关于如何加快速度的任何建议将不胜感激。

一个示例(实际数据可以大于或大于一个数量级):

library(tidyverse)
library(microbenchmark)

# create dummy data
df <- data.frame(fact = rep(letters, each = 312000), 
                 month = rep(month.name, 26), 
                 num = rep(sample(10000:100000, 12), 26), 
                 prob = runif(312))

# Order by month     
df <- df[order(df$month), ]

# group by two factor variables and calculate new variable 
microbenchmark({
  df2 <- df %>%
    group_by(fact, month) %>%
    mutate(res = ifelse(prob > 0, c(rmultinom(1, num[1], prob = prob)), 0))}, times = 10)


 > Unit: milliseconds
 > min      lq       mean     median   uq        max         neval
 > 816.3126 822.4083 840.7966 834.6163 855.5139  879.9345    10
Run Code Online (Sandbox Code Playgroud)

Jaa*_*aap 1

使用,你可以这样做:

dt <- copy(df)
setDT(dt)

dt[, res := 0L][prob > 0, res := c(rmultinom(1, num[1], prob = prob)), by = .(fact, month)]
Run Code Online (Sandbox Code Playgroud)

这会给你带来微小的速度提升:

microbenchmark(dp = df %>%
                 group_by(fact, month) %>%
                 mutate(res = ifelse(prob > 0, c(rmultinom(1, num[1], prob = prob)), 0)),
               dt = dt[, res := 0L][prob > 0, res := c(rmultinom(1, num[1], prob = prob)), by = .(fact, month)],
               times = 1)
Run Code Online (Sandbox Code Playgroud)
Unit: seconds
 expr      min       lq     mean   median       uq      max neval
   dp 1.356745 1.356745 1.356745 1.356745 1.356745 1.356745     1
   dt 1.063363 1.063363 1.063363 1.063363 1.063363 1.063363     1
Run Code Online (Sandbox Code Playgroud)