Для петлевых альтернатив для прогрессивных операций
Я должен постепенно применять функцию регрессии к данным временного ряда (вектор "время" и "тм", и я использую цикл For следующим образом:
top<-length(time)
for(k in 2:top){
lin.regr<-lm(tm[1:k] ~ log(time[1:k]))
slope[k]<-coef(lin.regr)[2]
}
Но для векторов длиной около 10к это становится очень медленным. Есть ли более быстрая альтернатива (возможно, с помощью функции apply)?
В более простой задаче: если у меня есть вектор типа x<-c (1:10), как я могу построить вектор y, содержащий (например) прогрессивную сумму значений x? Подобно:
x
1 2 3 4 5 6 7 8 9 10
y
1 3 6 10 15 21 28 36 45 55
2 ответа
results <- sapply(2:top,function (k) coef(lm(tm[1:k] ~ log(time[1:k])))[2])
Применение семейства функций - самый быстрый способ итерации в R.
также можно посмотреть на использование lm.fit(), чтобы немного ускорить ваше рассмотрение
cumsum(1:10)
как сделать второй вопрос
Ну, нет быстрой альтернативы цикла, если вы не можете векторизовать. В некоторых случаях такие функции, как 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]
)
как более общее решение.