【问题标题】:Loop of regressions on input range - How can I avoid the for loop and improve performance?输入范围的回归循环 - 如何避免 for 循环并提高性能?
【发布时间】:2015-09-11 13:10:48
【问题描述】:

我目前正在回测一个涉及lm() 回归和概率glm() 回归的策略。我有一个名为 forBacktest 的数据框,有 200 行(每天 1 行用于回测)和 9 列:前 8 个(x1x8)是解释变量,最后一个(x9)是真正的价值(我试图在回归中解释)。为了进行回归,我有另一个名为 temp 的数据框,它有 1000 行(每天一个)和很多列,其中一些是 x1x8 值以及 x9价值。

但棘手的部分是我不只是为predict 生成一个回归模型,然后是一个循环,因为我根据x1 的值选择数据框temp 的一部分,我分成 8 个不同的范围,然后根据数据框 forBacktest 的值 x1,我对给定范围内的 tempx1 的一部分进行回归。

所以我所做的是,对于 200 行中的每一行,我采用 x1,如果 x1 介于 0 和 1 之间(例如),那么我创建 temp 的一部分,其中所有 @987654341 @ 介于 0 和 1 之间,然后我做一个回归来解释 x9x1x2,...x9(只是x1+x2+...,没有x1:x2x1^2,。 ..) 然后我将predict 函数与数据框forBacketst 一起使用。如果我预测一个正值并且如果x9 是正值,那么我将计数器success 加一(如果两者都是负值,则同上),但如果一个是正值而另一个是负值,那么success 保持不变。然后我拿下一行,依此类推。在 200 行的末尾,我现在有我返回的成功的平均值。事实上,我有两个平均值:一个用于lm 回归,另一个用于glm 回归(相同的方法,我只是用sign(x9) 来解释变量)。

所以我的问题是:我怎样才能在 R 中有效地做到这一点,如果可能的话,没有一个有 200 次迭代的大 for 循环,对于每次迭代,它会创建数据框的一部分,进行回归,预测这两个值,将它们添加到计数器等等?(这是我目前的解决方案,但我发现它太慢而且不太像 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
}            

【问题讨论】:

  • 您想将数据框中的列除以特定范围,然后对与这些范围之一对应的值执行 lm() 吗?
  • 是的,就是这样
  • 您明白这样做还会从所有其他列(即从 x2 到 x9)中删除行,对吧?
  • 是的,我只想要 x1 在给定范围内时的回归,因此只有 x1 在给定范围内的行中的 x2...x9 值。但我不想破坏数据框,所以我使用 temp2
  • 代码有很多变化..我会稍后发布编辑的代码

标签: r performance loops regression cross-validation


【解决方案1】:

您编写的代码非常复杂。事情可能要简单得多..

使用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()regtemp 数据框。它将返回八个范围的预测值

要记住的几件事:

  • 上面建议的方法更简单,更容易阅读。这将是 比你的 for 循环快,但随着数据框大小的增加, 它可能会变慢。
  • by 函数接受一个数据帧,并将指定的函数 (data.frame()) 应用于 INDICES 指定的子集数据帧并返回一个列表。因此创建了新的数据帧,如果数据帧的大小可能会占用大量空间很大。
  • *apply() 比 for 循环快得多。请参阅here 了解更多信息。 apply 系列对于此类操作非常方便

【讨论】:

  • 但是我会在哪里写 x1,...x9 ?像 lm(x9~x1+x2) 或 lm,x9~x1+x2 因为所有这些都返回错误
  • 我收到错误“无法将类“lm”强制转换为 data.frame”
  • 代码有很多变化..我会在一段时间内发布正确的代码
  • 我认为你改变了 forBacktest 和 temp 因为回归应该在 temp 上进行。但改名后效果很好。另一方面,对于我使用 lapply(c(1:8),function(x){predict(reg[[x]],forBacktest}) 的预测,它返回 8 组 200 个预测(forBacktest 的大小),并且它不会“拆分”forBacktest。我怎样才能只返回 200 个预测(而不是 8*200),这将是 forBacktest 值 x1 的正确预测?
  • 没关系,我只需要像 temp 一样拆分 forBacktest。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多