输入范围的回归循环 - 如何避免 for 循环并提高性能?
Loop of regressions on input range - How can I avoid the for loop and improve performance?
我目前正在回测涉及 lm()
回归和概率 glm()
回归的策略。我有一个名为 forBacktest
的数据框,其中包含 200 行(每天回测 1 行)和 9 列:前 8 个(x1
到 x8
)是解释变量,最后一个( x9
) 是实际值(我试图在回归中解释)。为了进行回归,我有另一个名为 temp
的数据框,它有大约 1000 行(每天一行)和很多列,其中一些是 x1
到 x8
值还有 x9
值。
但棘手的部分是我不只是生成一个回归模型,然后为 predict
生成一个循环,因为 我 select 数据框的一部分 temp
基于 x1
的值,我将其分为 8 个不同的范围,然后根据数据框 forBacktest
的值 x1
,我对 [=] 的一部分进行回归17=] 与 x1
在给定范围内。
所以我所做的是,对于 200 行中的每一行,我取 x1
,如果 x1
介于 0 和 1 之间(例如),那么我创建 temp
其中所有 x1
都在 0 和 1 之间,然后我进行回归以用 x1
、x2
、... x9
来解释 x9
(只有 x1+x2+...
,没有 x1:x2
,x1^2
,...)然后我将 predict
函数与数据框 forBacketst
一起使用。如果我预测一个正值并且 x9
为正,那么我将计数器 success
递增 1(如果两者均为负,同上),但如果一个为正,另一个为负,则 success
保持不变。然后我坐下一行,依此类推。在 200 行的末尾,我现在得到了成功的平均值 return。事实上,我有两个平均值:一个用于 lm
回归,另一个用于 glm
回归(相同的方法,我只是用 sign(x9)
作为变量来解释)。
所以我的问题是:我怎样才能在 R 中有效地做到这一点,如果可能的话,没有一个大的 for 循环和 200 次迭代,其中对于每次迭代,它创建数据框的一部分,进行回归,预测这两个值,将它们添加到计数器等等?(这是目前我的解决方案,但我发现它太慢而且不太像 R)
我的代码是这样的:
backtest<-function() {
for (i in 1:dim(forBacktest)[1]) {
x1 <- forBacktest[i,1]: x2 <- forBacktest[i,2] ... x9 <- forBacktest[i,9]
a <- ifelse(x1>1.5,1.45,ifelse(x1>1,0.95,....
b <- ifelse(x1>1.5,100,ifelse(x1>1,1.55,....
temp2 <- temp[(temp$x1>=a/100)&(temp$x1<=b/100),]
df <- dataframe(temp$x1,temp$x2,...temp$x9)
reg <- lm(temp$x9~.,data=df)
df2 <- data.frame(x1,x2,...x9)
rReg <- predict(reg,df2)
trueOrFalse <- ifelse(sign(rReg*x9)>0,1,0)
success <- success+trueOrFalse
}
success
}
你写的代码太复杂了。事情可以简单得多..
使用 cut()
和 by()
函数。
breaks <- 0:8 #this is the range by which you want to divide your data
divider <- cut(forBackTest$x1,breaks)
subsetDat <- by(forBackTest,INDICES = divider,data.frame) # this creates 8 dataframes
reg <- lapply(subsetDat,lm,formula=x9~.)
'reg' 现在将包含对应于 8 个范围的所有 8 个 lm 对象。要预测所有这些范围,请使用 lapply()
和 reg
以及 temp
数据框。它将 return 为您提供八个范围的预测值
需要记住的几点:
- 上面建议的方法更简单易读。这将是
比你的 for 循环更快,但随着数据框大小的增加,
它可能会变慢。
- by 函数接受一个数据帧,并将指定的函数(
data.frame())
应用于由 INDICES 指定的子集数据帧和 returns 一个列表。因此创建了新的数据帧,这可能会占用一个很多 space 如果数据帧的大小很大。
*apply()
比 for 循环快得多。请参阅 here 了解更多信息。 apply 系列可以方便地进行此类操作
我目前正在回测涉及 lm()
回归和概率 glm()
回归的策略。我有一个名为 forBacktest
的数据框,其中包含 200 行(每天回测 1 行)和 9 列:前 8 个(x1
到 x8
)是解释变量,最后一个( x9
) 是实际值(我试图在回归中解释)。为了进行回归,我有另一个名为 temp
的数据框,它有大约 1000 行(每天一行)和很多列,其中一些是 x1
到 x8
值还有 x9
值。
但棘手的部分是我不只是生成一个回归模型,然后为 predict
生成一个循环,因为 我 select 数据框的一部分 temp
基于 x1
的值,我将其分为 8 个不同的范围,然后根据数据框 forBacktest
的值 x1
,我对 [=] 的一部分进行回归17=] 与 x1
在给定范围内。
所以我所做的是,对于 200 行中的每一行,我取 x1
,如果 x1
介于 0 和 1 之间(例如),那么我创建 temp
其中所有 x1
都在 0 和 1 之间,然后我进行回归以用 x1
、x2
、... x9
来解释 x9
(只有 x1+x2+...
,没有 x1:x2
,x1^2
,...)然后我将 predict
函数与数据框 forBacketst
一起使用。如果我预测一个正值并且 x9
为正,那么我将计数器 success
递增 1(如果两者均为负,同上),但如果一个为正,另一个为负,则 success
保持不变。然后我坐下一行,依此类推。在 200 行的末尾,我现在得到了成功的平均值 return。事实上,我有两个平均值:一个用于 lm
回归,另一个用于 glm
回归(相同的方法,我只是用 sign(x9)
作为变量来解释)。
所以我的问题是:我怎样才能在 R 中有效地做到这一点,如果可能的话,没有一个大的 for 循环和 200 次迭代,其中对于每次迭代,它创建数据框的一部分,进行回归,预测这两个值,将它们添加到计数器等等?(这是目前我的解决方案,但我发现它太慢而且不太像 R)
我的代码是这样的:
backtest<-function() {
for (i in 1:dim(forBacktest)[1]) {
x1 <- forBacktest[i,1]: x2 <- forBacktest[i,2] ... x9 <- forBacktest[i,9]
a <- ifelse(x1>1.5,1.45,ifelse(x1>1,0.95,....
b <- ifelse(x1>1.5,100,ifelse(x1>1,1.55,....
temp2 <- temp[(temp$x1>=a/100)&(temp$x1<=b/100),]
df <- dataframe(temp$x1,temp$x2,...temp$x9)
reg <- lm(temp$x9~.,data=df)
df2 <- data.frame(x1,x2,...x9)
rReg <- predict(reg,df2)
trueOrFalse <- ifelse(sign(rReg*x9)>0,1,0)
success <- success+trueOrFalse
}
success
}
你写的代码太复杂了。事情可以简单得多..
使用 cut()
和 by()
函数。
breaks <- 0:8 #this is the range by which you want to divide your data
divider <- cut(forBackTest$x1,breaks)
subsetDat <- by(forBackTest,INDICES = divider,data.frame) # this creates 8 dataframes
reg <- lapply(subsetDat,lm,formula=x9~.)
'reg' 现在将包含对应于 8 个范围的所有 8 个 lm 对象。要预测所有这些范围,请使用 lapply()
和 reg
以及 temp
数据框。它将 return 为您提供八个范围的预测值
需要记住的几点:
- 上面建议的方法更简单易读。这将是 比你的 for 循环更快,但随着数据框大小的增加, 它可能会变慢。
- by 函数接受一个数据帧,并将指定的函数(
data.frame())
应用于由 INDICES 指定的子集数据帧和 returns 一个列表。因此创建了新的数据帧,这可能会占用一个很多 space 如果数据帧的大小很大。 *apply()
比 for 循环快得多。请参阅 here 了解更多信息。 apply 系列可以方便地进行此类操作