user20050294
user20050294

Reputation:

For Loop and Appending to Vector in R

I am trying to create a For Loop in R to fill a Vector with Forecasted values, generated via the auto.arima function.

I am new to R, so I am not sure if this is done correctly.

The code I am using is the following:

library(dplyr)
library(forecast)
dfts <- ts(df$Price_REG1) 
fc=c()
for (i in 0:7) {
  modArima <- auto.arima(dfts[0+(i*24):168+(i*24)])
  forecast <- forecast(modArima, h=24)
  forecast_values <- forecast$mean
  fc <- append(fc, forecast_values)
}

I use longer sets in reality, but made it smaller here to make it more understandable.

What I am trying to achieve is to use the first week of data (168 hours in one week) to estimate the coefficients for the model. Then I want to put the generated predictions for the first 24 hours after the training set in the Vector fc. I then want to move the window one day, reestimate the coefficients and generate the forecasts for the following day and saving them into the Vector.

I am a bit unsure on the dfts[0+(i*24):168+(i*24)] part, since df <- df[0:168], doesn't work, but needs the df <- df[0:168,]. But if I put dfts[0+(i*24):168+(i*24)] I get

Error in [.default(dfts, 0 + (i * 24):874 + (i * 24), ) : incorrect number of dimensions

EDIT : Sample of Data:

structure(c(28.78, 28.45, 27.9, 27.52, 27.54, 26.55, 25.83, 25.07, 
25.65, 26.15, 26.77, 27.4, 28.08, 28.69, 29.37, 29.97, 30.46, 
30.39, 30.06, 29.38, 27.65, 27.33, 25.88, 24.81, 12.07, 13.13, 
19.07, 21.12, 24.29, 26.27, 27.74, 28.39, 29.37, 29.95, 29.91, 
29.96, 29.94, 29.94, 30.18, 30.96, 31.2, 30.98, 30.35, 29.27, 
28.17, 28.02, 27.69, 24.39, 18.93, 9.98, 1.53, 0.14, 0.85, 9.92, 
24.48, 26.68, 28.12, 28.58, 28.16, 28.78, 28.31, 28.44, 28.96, 
29.86, 30.15, 30.07, 29.54, 29.11, 27.91, 27.03, 25.7, 22.04, 
21.73, 15.95, 16.23, 6.45, 3.83, 4.03, 4.04, 19.07, 17.49, 24.18, 
24.94, 25.11, 24.94, 24.95, 25.25, 26.33, 27.36, 28.88, 29.58, 
29.42, 27.71, 27.4, 27.37, 25.77, 26.65, 27.13, 27.11, 27.42), tsp = c(1, 
5.125, 24), class = "ts")

Upvotes: 0

Views: 90

Answers (1)

Rui Barradas
Rui Barradas

Reputation: 76683

Here is an example with built-in data set AirPassengers on how to run a rolling forecast with package forecast.

The code below makes use of time series functions

  • window to subset objects of class "ts";
  • frequency and start to get those attributes.

The output vector is created beforehand, not extended in the loop with append.

library(forecast)
#> Registered S3 method overwritten by 'quantmod':
#>   method            from
#>   as.zoo.data.frame zoo
data("AirPassengers", package = "datasets")

fc <- ts(
  data = rep(NA, length(AirPassengers)), 
  start = start(AirPassengers), 
  frequency = frequency(AirPassengers)
)

start <- start(AirPassengers)[1]
freq <- frequency(AirPassengers)
i_fc <- seq_len(freq)
fc[i_fc] <- AirPassengers[i_fc]

for(i in 1:11) {
  w <- window(AirPassengers, start = start + i - 1L, end = c(start + i - 1L, freq))
  modArima <- auto.arima(w)
  y <- forecast(modArima, h = freq)$mean
  i_fc <- i_fc + freq
  fc[i_fc] <- y
}

plot(cbind(AirPassengers, fc))

Created on 2022-12-20 with reprex v2.0.2


Edit

I believe that the code below forecasts the next day given a certain initial number of days.

library(forecast)
#> Registered S3 method overwritten by 'quantmod':
#>   method            from
#>   as.zoo.data.frame zoo

fill_first_periods <- function(x, weeks = 1L, week_days) {
  if(missing(week_days)) week_days <- 7L
  fc <- ts(
    data = rep(NA, length(x)), 
    start = start(x), 
    frequency = frequency(x)
  )
  i_fc <- seq_len(frequency(x) * week_days * weeks)
  fc[i_fc] <- x[i_fc]
  fc
}

# not enough data to run an example for 1 week
# three days only
weeks <- 1L
week_days <- 3L
fc <- fill_first_periods(dfts, weeks = weeks, week_days) 
n <- length(fc)

i_last <- length(fc[!is.na(fc)])
h <- frequency(fc)
curr_start <- start(fc)
curr_end <- c(curr_start[1] + weeks*week_days - 1L, frequency(fc))
for(i in 2:(end(fc)[1] - 1L)) {
  if(n - i_last < h) {
    h <- end(fc)[2]
    i_fc <- tail(seq_len(n), h)
  } else {
    i_fc <- (i_last + 1L):(i_last + h)
    i_last <- i_last + h
  }
  w <- window(dfts, start = curr_start, end = curr_end)
  modArima <- auto.arima(w)
  fc[i_fc] <- forecast(modArima, h = h)$mean
  #
  curr_start[1] <- curr_start[1L] + 1L
  curr_end <- c(curr_end[1L] + 1L, h)
}

plot(cbind(dfts, fc))

Created on 2022-12-21 with reprex v2.0.2

Upvotes: 2

Related Questions