多个嵌套for循环的并行处理

时间:2016-02-03 14:12:44

标签: r foreach

我正在尝试运行模拟场景,这反过来应该为我提供给定日期的最佳场景,经过几个月的测试。特定场景的输入有4个输入变量,每个变量可以处于5个状态(625个排列)。模型的流程如下:

  1. 模拟625个场景以获得每个利润
  2. 根据利润对每个方案进行排名
  3. 从2015年12月1日开始的最后2个月,通过为期1天的展开窗口重复此过程 - 为625个场景中的每一个创建时间序列
  4. 不幸的结果是5个嵌套for循环,这可能需要很长时间才能运行。我查看了foreach包,但我担心输出的组合在我的场景中是如何工作的。

    我正在使用的当前代码如下工作,首先我创建每个输入的可能状态以及窗口

    a<-seq(as.Date("2015-12-01", "%Y-%m-%d"),as.Date(Sys.Date()-1, "%Y-%m-%d"),by="day")
    #input variables
    b<-seq(1,5,1)
    c<-seq(1,5,1)
    d<-seq(1,5,1)
    e<-seq(1,5,1)
    
    set.seed(3142)
    
    tot_results<-NULL
    

    接下来,嵌套的for循环继续为我运行模拟。

    for(i in 1:length(a))
    {
    cat(paste0("\n","Current estimation date: ", a[i]),";itteration:",i," \n")
    #subset data for backtesting
    dataset_calc<-dataset[which(dataset$Date<=a[i]),]
    p=1
    results<-data.frame(rep(NA,625))
        for(j in 1:length(b))
        {
            for(k in 1:length(c))
            {
                for(l in 1:length(d))
                {
                    for(m in 1:length(e))
                    {
                    if(i==1)
                    {
                        #create a unique ID to merge onto later
                        unique_ID<-paste0(replicate(1, paste(sample(LETTERS, 5, replace=TRUE), collapse="")),round(runif(n=1,min=1,max=1000000)))
                    }
                    #Run profit calculation
                    post_sim_results<-profit_calc(dataset_calc, param1=e[m],param2=d[l],param3=c[k],param4=b[j])
                    #Exctract the final profit amount
                    profit<-round(post_sim_results[nrow(post_sim_results),],2)
    
                    results[p,]<-data.frame(unique_ID,profit)
                    p=p+1
                    }
                }
            }
        }
        #extract the ranks for all scenarios
        rank<-rank(results$profit)
    
        #bind the ranks for the expanding window
        if(i==1)
            {
                tot_results<-data.frame(ID=results[,1],rank)
            }else{
                tot_results<-cbind(tot_results,rank)
            }
        suppressMessages(gc())
    }
    

    我最关心的是结果的绑定,因为外部循环的动作取决于内部循环的输出。

    关于如何继续的任何建议将非常感激。

1 个答案:

答案 0 :(得分:1)

所以我认为你可以对大部分内容进行矢量化,这样可以大大缩短运行时间。

目前,您使用for - 循环(确切地说是5)来创建值的每个组合,然后通过profit_calc(未指定的函数)逐个运行值。理想情况下,您只需一次性采用所有可能的组合,并通过一次操作将其推送到profit_calc

- 基本原理 -

a <- 1:10
b <- 1:10
d <- rep(NA,10)
for (i in seq(a)) d[i] <- a[i] * b[i]
d 

# [1]   1   4   9  16  25  36  49  64  81 100

由于*也适用于矢量,我们可以将其重写为:

a <- 1:10
b <- 1:10
d <- a*b
d

# [1]   1   4   9  16  25  36  49  64  81 100

虽然它可能只为我们节省了一行代码,但它实际上将问题从10步减少到1步。

- 申请

那么这对你的代码有何影响?好吧,鉴于我们可以对profit_calc进行矢量化,您基本上可以生成一个数据框,其中每一行都是您参数的每种可能组合。我们可以使用expand.grid

执行此操作
foo <- expand.grid(b,c,d,e)
head(foo)

#   Var1 Var2 Var3 Var4
# 1    1    1    1    1
# 2    2    1    1    1
# 3    3    1    1    1
# 4    4    1    1    1
# 5    5    1    1    1
# 6    1    2    1    1

让我们说我们有一个公式... (a - b) / (c + d) ...然后就像:

bar <- (foo[,1] - foo[,2]) * (foo[,3] + foo[,4])
head(bar)

# [1]  0  2  4  6  8 -2

所以基本上,尝试找到一种方法来替换for - 循环与矢量化选项。如果您无法对某些内容进行矢量化,请尝试查看apply,因为在大多数情况下这也可以节省您一些时间。如果您的代码运行速度太慢,那么您最好首先看看是否可以编写更高效的脚本。另外,您可能对microbenchmark库或?system.time感兴趣。