优化从大型数据帧中的表达式创建列

时间:2016-07-27 18:38:10

标签: r dataframe

亲爱的StackOverflowers :),我正在尝试从使用先前列作为输入的表达式计算我的数据框中的新列。我编写了一个函数,但是在650,000行的数据帧中需要花费数小时,而完整的数据集将有330万行!

我想知道如何优化我的代码,或者我是否应该在我的部门寻找更强大的PC。 这是一个例子:

testdf99<- data.frame('V1'= c(1:10), 'V2'= c(2,3,4,5,3,2,2,3,8,8))

我的目的是创建一个Var3列:

my_calculator<- function(input_table){
table0<- input_table
colnames(table0)<- c('Coordinate', 'Var1')
table0$Var2<- table0$Coordinate+table0$Var1-1
table0$Var3<- -99 # as sanity check
#Now let's calculate Var3 at each position
for (i in 1:nrow(table0)){
  #position of i
  i_POS<- table0[i,'Coordinate']
  # Var1 covering i_POS
  table1<- table0[table0$Coordinate<= i_POS & table0$Var2>= i_POS,]
  table0[i, 'Var3']<- max(table1$Var1)}
return(table0)}

创建Var2似乎是即时的,但是当我将Var3插入到函数中时,它会持续数小时(〜650,000行)。
我将不胜感激任何有关更好的代码的建议,这些代码可以明智地加速计算。

1 个答案:

答案 0 :(得分:1)

这是我尝试将您的函数转换为应用样式循环的尝试。

f1 <- function(table0){
  for (i in 1:nrow(table0)){
    #position of i
    i_POS<- table0[i,'Coordinate']
    # Var1 covering i_POS
    table1<- table0[table0$Coordinate<= i_POS & table0$Var2>= i_POS,]
    table0[i, 'Var3']<- max(table1$Var1)
  }
  table0
}

f2 <- function(table0){
    mutate(table0, lapply(1:10, function(i){ 
      max(table0[table0$Coordinate<= i & table0$Var2>= i,]$Var1)
    }))
}


all.equal(f1(table0), f2(table0))
[1] TRUE

现在有一些时间:

library(microbenchmark)
microbenchmark(f1(table0),f2(table0))

Unit: microseconds
       expr      min        lq      mean    median       uq      max neval
 f1(table0) 1266.691 1317.8750 1693.9076 1602.0810 1872.075 2931.152   100
 f2(table0)   13.892   18.1005   33.1414   26.4715   42.242  123.525   100

编辑:你总是可以包含一些Rcpp代码,这个代码包含了很棒的c ++ Armadillo库。

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

using namespace Rcpp;
using namespace arma;

// [[Rcpp::export]]
vec f3(arma::mat table0) {

  int t0_rows = table0.n_rows;
  vec coord = table0.col(0);
  vec var1 = table0.col(1);
  vec var2 = table0.col(2);
  vec var3 = zeros<vec>(t0_rows);

  for(int i = 0; i < t0_rows; i++){
    var3(i) = max(var1(find((coord <= coord[i]) &&
      var2  >= coord[i])));
  }
  return var3;
}

table0_v3 <- f3(table0)

请注意,这只会创建一个列矩阵,即var3。