mutate_at非常慢

时间:2018-01-13 01:17:48

标签: r dplyr

我正在使用产生光谱的仪器产生的数据。这意味着每个数据 point 的长度为3201个元素。我想通过减去中位数或使用scale来不时地对数据进行标准化。我的数据与其他变量有关,因此我认为我会使用mutate_at中的dplyr函数,但这似乎花费了相当长的时间。

set.seed(123)
## generate some test data
ncol = 100
d_f = data.frame(color = rep('C', 5), 
                 rep = factor(1:5), 
                 matrix(rnorm(5 * ncol), nrow = 5))
d_f = as.tibble(d_f)

sc1 = function(x, scale =  c("med", "z")){
  scale = match.arg(scale)

  if(scale == 'med'){
     x = x %>% mutate_at(vars(matches("^X[0-9]+$")), funs(. - median(.)))
  }else if(scale == 'z'){
    x = x %>% mutate_at(vars(matches("^X[0-9]+$")), funs(base::scale))
  }
}

sc2 = function(x, scale = c("med", "z")){

  scale = match.arg(scale)

  y = x %>% select(matches("^X[0-9]+$")) %>% as.matrix()

  if(scale == 'med'){
    y = sweep(y, 2, apply(y, 2, median))
  }else if(scale == 'z'){
    y = base::scale(y)
  }

  y = as.tibble(y)
  names(y) = paste0("X", 1:ncol)
  x = x %>% select(matches("^[^X].*$")) %>% bind_cols(y)
  return(x)
}

microbenchmark(d_f %>% sc1, d_f %>% sc2)

以下是100列的结果:

Unit: milliseconds
        expr      min        lq      mean    median        uq       max neval cld
  d_f %>% sc1 142.1663 157.08819 188.71257 174.88702 209.38378 441.79132   100   b
  d_f %>% sc2  12.6180  15.17256  18.83863  16.90944  20.11142  45.81297   100  a 

以下是仅有10列的结果:

Unit: milliseconds
        expr       min        lq     mean   median       uq      max neval cld
 d_f %>% sc1 13.904984 15.975898 19.38772 17.34842 21.25275 40.98175   100   b
 d_f %>% sc2  8.817058  9.746072 11.74869 10.89266 12.93568 23.96279   100  a 

使用320 sc1的单次运行需要约72秒,因此测试集减少了。

1 个答案:

答案 0 :(得分:0)

我的回答是mutate_at()的开销比从{转换为matrix更大。

以下是sc1()的分析:

> summaryRprof()$by.self
                          self.time self.pct total.time total.pct
"FUN"                          0.34    19.54       0.92     52.87
"makeActiveBinding"            0.24    13.79       0.48     27.59
"lapply"                       0.20    11.49       0.88     50.57
"make_active_binding_fun"      0.20    11.49       0.24     13.79
"sort.int"                     0.14     8.05       0.14      8.05
"vapply"                       0.12     6.90       0.36     20.69
"%in%"                         0.04     2.30       0.14      8.05
"get_env"                      0.04     2.30       0.10      5.75
"rm"                           0.04     2.30       0.06      3.45
"!"                            0.04     2.30       0.04      2.30
"force"                        0.04     2.30       0.04      2.30
".Call"                        0.02     1.15       1.68     96.55
"tryCatch"                     0.02     1.15       1.66     95.40
"<Anonymous>"                  0.02     1.15       1.48     85.06
"%||%"                         0.02     1.15       0.08      4.60
"type_of"                      0.02     1.15       0.06      3.45
"is_null"                      0.02     1.15       0.04      2.30
"=="                           0.02     1.15       0.02      1.15
"all"                          0.02     1.15       0.02      1.15
"any"                          0.02     1.15       0.02      1.15
"as.character"                 0.02     1.15       0.02      1.15
"inherits"                     0.02     1.15       0.02      1.15
"is_formulaish"                0.02     1.15       0.02      1.15
"is.null"                      0.02     1.15       0.02      1.15
"names"                        0.02     1.15       0.02      1.15
"sys.call"                     0.02     1.15       0.02      1.15