【问题标题】:How to optimize code to calculate rolling calculations in a dataframe fast?如何优化代码以快速计算数据框中的滚动计算?
【发布时间】:2021-05-08 07:38:28
【问题描述】:

此代码读取fnoStocks 数据帧中的每个值,并为每个文件读取文件并计算一些指标。

i 的每次迭代都需要 3 多分钟,而我有大约 156 次 i 迭代

是否可以优化内部j循环代码以减少执行时间?

i 范围是从 1 到 156

j 范围是从 1 到 259

WeeklyData中,我根据lookbackPeriod和holdPeriod做两个滚动计算。

for(lookbackPeriod in 1:10){
  
  for(holdPeriod in 1:8){

  for (i in 1:nrow(fnoStocks)){
  
        out <- read.csv(paste("Returns\\", fnoStocks[i,1] , ".csv", sep="") )
        
        #Delete first row
        out <- out[-1,]
        
        for (j in 1:( nrow(out)-(lookbackPeriod + holdPeriod) ) ){
      
            WeeklyData <- rbind(WeeklyData,
                 data.frame(
                   StockName = fnoStocks[i,1],
                   WeekNum = j,
                   MScore = sum(out$Ret[j:(j+lookbackPeriod-1)]),
                   NWeekRet =round( 
                                  (out$Adj.Close[j+lookbackPeriod+holdPeriod-1] -
                                 out$Adj.Close[j+lookbackPeriod-1] ) / out$Adj.Close[j+lookbackPeriod-1] ,
                                 3)
                   
                 )
                )
        }
        ## j ends here
 
    }
    ## i ends here
   }}

我想做的是这个

我在outout$Ret 列中有雅虎股票价格数据,与上一时期相比有百分比变化。

现在在WeeklyData 数据帧中,我正在计算current period + lookbackPeriod - 1 内的返回值总和 - 当前周期为 j 我还计算了out$Adj.Close 价格相对于j+lookbackPeriod+holdPeriod-1j+lookbackPeriod-1 的百分比变化。

基本上我可以使用 rollsum 函数计算 MScore,但使用 Delt 计算滚动百分比有点棘手,因为存在行偏移。

【问题讨论】:

  • 您可以创建一个小例子来说明您正在尝试做的事情,而不是直接发布您的代码,以便可以轻松理解事情或建议快速的替代方案。这里有四个嵌套的 for 循环,这很复杂。
  • @AnilGoyal 我已经添加了我想要做什么的解释。如果有帮助,请告诉我。
  • @AnilGoyal 有四个嵌套循环,但只有 j 内部循环需要很多时间,我通过部分运行每个部分来测量它。
  • 您能否也包含一些可重现的示例。没有一个,太难理解了。实际上,我认为您可以使用runnerrollapply 有点功能,而不是使循环复杂化。
  • @AnilGoyal 是的,我正在尝试制作一个最小的示例。

标签: r for-loop optimization


【解决方案1】:

您可以尝试将lapply 用于内部循环。内循环慢的主要原因是rbind(WeeklyData,data.frame(....))部分。

total_data <- vector('list', 10 * 8 * nrow(fnoStocks))
inds <- 1

for(lookbackPeriod in 1:10){
  
  for(holdPeriod in 1:8){
    
    for (i in 1:nrow(fnoStocks)){
      
      out <- read.csv(paste("Returns\\", fnoStocks[i,1] , ".csv", sep=""))
      
      #Delete first row
      out <- out[-1,]
      val <- 1:(nrow(out)-(lookbackPeriod + holdPeriod))
      do.call(rbind, lapply(val, function(j) {
        data.frame(
          StockName = fnoStocks[i,1],
          WeekNum = j,
          MScore = sum(out$Ret[j:(j+lookbackPeriod-1)]),
          NWeekRet =round( 
            (out$Adj.Close[j+lookbackPeriod+holdPeriod-1] -
               out$Adj.Close[j+lookbackPeriod-1] ) / out$Adj.Close[j+lookbackPeriod-1] ,
            3)
          
        )
      })) -> total_data[[inds]]
      inds <- inds + 1
    }
  }
}

result <- do.call(rbind, total_data)

【讨论】:

  • 你认为我们可以使用 rollsum 和 Delt 函数来代替索引和计算总和和百分比变化,即 MScore 和 NWeekRet 吗?
  • 如果您正在执行滚动计算,是的,我们可以使用它。
  • 它们正在滚动,但是当我们计算导致问题的百分比变化时存在偏移
猜你喜欢
  • 2022-11-23
  • 1970-01-01
  • 1970-01-01
  • 2011-08-31
  • 2019-02-05
  • 1970-01-01
  • 2016-02-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多