简化和改进循环

时间:2016-04-21 10:40:51

标签: r

我想知道是否存在更简单(可能更有效)的方式来编写以下循环

l = leg(u[1],k)
for (i in 2:length(u)){l=rbind(l,leg(u[i],k))}

其中leg是用户定义的函数,它返回大小为k的向量。基本上,我想返回一个length(u) x k矩阵。

我的问题是length(u)很大时计算速度非常慢,因此使用一些更智能的函数(如apply或其变体)可能会更快。

1 个答案:

答案 0 :(得分:1)

与普遍看法相反,sapply不一定比for循环更快

让我们使用microbenchmark

测试一些不同的方法
library(microbenchmark)
u<-1:10
k<-3

为了测试,我在这里发明了一个函数:

leg<-function(u,k){u**(1:k)}

让我们测试不同的方法:

 method1<-function(u,k){
   l = leg(u[1],k)
   for (i in 2:length(u)){l=rbind(l,leg(u[i],k))}
 }
 method2<-function(u,k){
  l<-matrix(nrow = length(u),ncol = k) 
  for (i in 1:length(u)){l[i,]<-leg(u[i],k)}
 }
 method3<-function(u,k){
   l <- do.call(rbind,lapply(1:length(u),function(i)leg(u[i],k)))
 }

现在:

microbenchmark(times = 100, method1(u,k),method2(u,k),method3(u,k))
           expr    min      lq     mean  median      uq    max neval
method1(u, k) 30.031 32.6920 36.88837 34.2125 41.4350 53.219   100
method2(u, k) 21.668 25.8490 29.60131 27.1800 32.6915 70.705   100
method3(u, k) 21.667 26.2295 29.42637 27.3700 33.0715 51.699   100

如果我们对我们的函数进行矢量化:

leg2<-function(u,k){
  result<-matrix(nrow = length(u),ncol = k); 
  for(i in 1:k){result[,i]<-u**i}
}
microbenchmark(times = 100, method1(u,k),method2(u,k),method3(u,k),leg2(u,k))

Unit: microseconds
        expr    min      lq     mean median      uq    max neval
method1(u, k) 28.891 31.1710 34.79391 32.692 37.8235 64.243   100
method2(u, k) 20.527 24.7085 29.20205 26.229 31.3610 79.068   100
method3(u, k) 22.428 24.7090 28.49507 26.610 31.1710 71.465   100
leg2(u, k)  6.462  7.6030  9.03213  8.363  8.7430 19.768   100

所以快3倍!