0
votes

I am trying to run a forecasting function hw() in R with below parameters: hw(TS, initial = 'simple', alpha = a,beta= b ,gamma=g,h=future_num) where alpha, beta, and gamma vary from 0 to 1 with an increment of 0.1.

I want to run this function for all the combination of alpha, beta, and gamma on one go and so have written below code:

  volume = 'UpdatedVol1'
  TS <- ts(Data_summary[volume],start = c(sy,sm),frequency = freq) 
  model_out = data.frame()
  for(i in 1:length(alpha)){
    for(j in 1:length(beta)){
       for(k in 1:length(gama)){
          ### Model Output ###
          #alpha = 0.2
          fore_hw <- hw(TS, initial = 'simple', alpha = 
                     alpha[i],beta=beta[j],gamma=gama[k],h=future_num)
          hw <- data.frame(ForecastVol =as.numeric(round(fore_hw$mean)))
          hw$ModelName <- "Ex HW"
          hw$Alpha <- alpha[i]
          hw$Beta <- beta[j]
          hw$Gama <- gama[k]
          model_out <- rbind(model_out,hw)    
       }
     }
   }

where Data_summary is data frame with 150 rows, freq = 7 and future_num = 300

Is there any possibility to run the hw() function with all alpha, beta, and gamma values at once? or any option to optimise this code as it is taking more than 8 mins to run this code

1
You're rbinding within each iteration of the loop. That's inefficient. So an obvious improvement would be to rbind (or dplyr::bind_rows()) only once, at the end of the loops. One way to do this would be to use (nested) lapplys instead of for loops. lapply returns a list, which can conveniently be passed directly to bind_rows. But if TS is large and hw() performs a complex analysis, you're always going to wait a while. - Limey

1 Answers

0
votes

rbind() inside a loop is notoriously inefficient. See The Second Circle of R Hell in the R Inferno for a detailed explanation.

A quick fix is to put all the model results in a list and then use rbind once at the end:

# create a list and counter
results <- list()
counter <- 1

volume = 'UpdatedVol1'
  TS <- ts(Data_summary[volume],start = c(sy,sm),frequency = freq) 
  model_out = data.frame() ## this seems to be unused??
  for(i in 1:length(alpha)){
    for(j in 1:length(beta)){
       for(k in 1:length(gama)){
          ### Model Output ###
          #alpha = 0.2
          fore_hw <- hw(TS, initial = 'simple', alpha = 
                     alpha[i],beta=beta[j],gamma=gama[k],h=future_num)
          hw <- data.frame(ForecastVol =as.numeric(round(fore_hw$mean)))
          hw$ModelName <- "Ex HW"
          hw$Alpha <- alpha[i]
          hw$Beta <- beta[j]
          hw$Gama <- gama[k]
          # add to the list and increment the counter
          results[[counter]] <- hw
          counter <- counter + 1
       }
     }
   }
   results <- do.call(rbind, results) # one rbind at the end
   # (you can use `dplyr::bind_rows` or `data.table::rbindlist` to do this faster)

You could certainly do better than this too, but this will be a vast improvement with minimal changes.