我想知道是否存在更简单(可能更有效)的方式来编写以下循环
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或其变体)可能会更快。
答案 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倍!