Ну, нет быстрой альтернативы цикла, если вы не можете векторизовать. В некоторых случаях такие функции, как ave, aggregate, ddply, tapply, ...
, могут дать вам существенный выигрыш, но часто хитрость заключается в использовании более быстрых функций, таких как cumsum (см. Ответ пользователя 615147)
Для иллюстрации:
top <- 1000
tm <- rnorm(top,10)
time <- rnorm(top,10)
> system.time(
+ results <- sapply(2:top,function (k) coef(lm(tm[1:k] ~ log(time[1:k])))[2])
+ )
user system elapsed
4.26 0.00 4.27
> system.time(
+ results <- lapply(2:top,function (k) coef(lm(tm[1:k] ~ log(time[1:k])))[2])
+ )
user system elapsed
4.25 0.00 4.25
> system.time(
+ results <- for(k in 2:top) coef(lm(tm[1:k] ~ log(time[1:k])))[2]
+ )
user system elapsed
4.25 0.00 4.25
> system.time(
+ results <- for(k in 2:top) lm.fit(matrix(log(time[1:k]),ncol=1),
+ tm[1:k])$coefficients[2]
+ )
user system elapsed
0.43 0.00 0.42
Единственное более быстрое решение - lm.fit()
. Не заблуждайтесь, временные интервалы немного различаются при каждом запуске анализа, поэтому разница в 0,02 незначительна в R. sapply, for
и lapply
здесь все так же быстро. Хитрость заключается в том, чтобы использовать lm.fit
.
Если у вас есть фрейм данных с именем Data, вы можете использовать что-то вроде:
Data <- data.frame(Y=rnorm(top),X1=rnorm(top),X2=rnorm(top))
mf <- model.matrix(Y~X1+X2,data=Data)
results <- sapply(2:top, function(k)
lm.fit(mf[1:k,],Data$Y[1:k])$coefficients[2]
)
как более общее решение.