Search code examples
rforecasting

How to create a sliding window in R to divide data into test and train samples to test accuracy of forecasts?


We are using the forecast package in R to read 3 weeks worth of hourly data (3*7*24 data points) and make predictions for the next 24 hours. It's a time-series with multiple seasonality.

We have the forecast model running just fine and it seems to be doing well. Now, we wish to quantify the accuracy of our approach / forecasting algorithm for our data. We wish to use the accuracy function in forecast package for this purpose. We understand that the accuracy function works so that it f is the forecast and x is the actual observation vector then accuracy(f,x) would give us the several accuracy measurements for this forecast.

We have data from the past several months and we wish to write a sliding window algorithm that picks (3*7*24) hour values and then predicts the next 24 hours. Then, compares these values against actual data for the next day / 24 hours, displays the accuracy, then slides the window by (24 points / hours) / next day and repeats.

The sample data is generated as follows:

library("forecast")

time <- 1:(12*168)
set.seed(1)
ds <- msts(sin(2*pi*time/24)+c(1,1,1.2,0.8,1,0,0)[((time-1)%/%24)%%7+1]+ time/400+rnorm(length(time),0,0.2),seasonal.periods=c(24,168))
plot(ds)
head(ds)
tail(ds)
length(ds)
length(time)

Forecasting procedure is as follows:

model <- tbats(ds[1:504])
fcst <- forecast(model,h=24,level=90)
accuracy(fcst,ds[505:528])     ##Test accuracy of forecast against next/actual 24 values

Now, we wish to slide the "window" by 24 and repeat the same procedure, that is, the next set of values used to build the model will be ds[25:528] and their accuracy will be tested against ds[529:552] ... and so on. How can we implement this?

Also, is there a better way to test overall accuracy of this forecasting algorithm for our scenario?


Solution

  • I would do this by creating a vector of times representing the front edge of the sliding windows, then using lapply to iterate the forecasting and scoring process over the windows those edges imply. Like...

    # set a couple of parameters we'll use to slice the series into chunks:
    # window width (w) and the time step at which you want to end the first
    # training set
    w = 24 ; start = 504
    
    # now use those parameters to make a vector of the time steps at which each
    # window will end
    steps <- seq(start + w, length(ds), by = w)
    
    # using lapply, iterate the forecasting-and-scoring process over the
    # windows that created
    cv_list <- lapply(steps, function(x) {
    
        train <- ds[1:(x - w)] 
        test <- ds[(x - w + 1):x]
    
        model <- tbats(train)
        fcst <- forecast(model, h = w, level = 90)
        accuracy(fcst, test)
    
    })
    

    Example output for the first window:

    > cv_list[[1]]
                           ME      RMSE       MAE        MPE     MAPE      MASE
    Training set 0.0001587681 0.3442898 0.2689754 34.3957362 84.30841 0.9560206
    Test set     0.2619029897 0.8961109 0.7868256 -0.6832273 36.64301 2.7966186
                       ACF1
    Training set 0.02588145
    Test set             NA
    

    If you want summaries of the scores for the whole list, you can do something like...

    rmse <- mean(unlist(lapply(cv_list, '[[', "Test set","RMSE")))
    

    ...which produces this:

    [1] 1.011177