1
$\begingroup$

I have an example of call center data for 2013. There are 261 days of data (excluding weekends).
For 2013, I have included a holiday dummy variable (holiday) for the days where there were no stats.
For 2014, I have also included a future holiday dummy variable (holidayf).
My objective is to assess how accurate this code is in making predictions for 2014.

I tried this code below but when looking at fc$fitted, the forecasts don't seem to be correct. For the first 8 days of January 2014, it forecasts the exact number of calls that were received in the first 8 days of January 2013, which seems wrong. Also, where there is a public holiday in 2014, the future forecast for that day predicts a normal to high volume of calls, so it seems that the forecast is using the holiday variable and not the holidayf variable.

library(forecast)
y <- ts(calls,frequency=5)
z <- fourier(ts(calls,frequency=261),K=12)
zf <- fourier(ts(calls,frequency=261),K=12,h=261)
fit <- auto.arima(y,xreg=cbind(z,holiday))
fc <- forecast(fit,xreg=cbind(zf,holidayf),h=261)
plot(fc)

Data:

calls <- 
  c(0,145,175,129,266,219,156,184,167,241,218,194,192,162,236,219,212,191,162,216,
  235, 218,180,150,245,209,210,211,151,236,197,217,140,164,200,156,152,153,141,224,178,
  159,153,137,207,173,197,213,206,305,284,248,289,269,359,333,257,0,244,325,292,267,
  206,0,0,360,261,327,284,385,377,317,327,271,372,191,320,268,261,376,320,280,251,200,
  200,200,0,236,161,259,200,190,166,174,225,228,202,201,155,241,207,199,179,178,249,
  243,230,177,181,264,250,219,204,178,244,249,185,184,164,0,253,216,217,165,170,185,
  175,160,148,231,223,196,162,149,228,213,190,177,139,212,205,221,190,170,196,210,
  198,192,131,220,185,199,153,166,240,176,200,145,0,255,202,220,220,181,250,171,164,
  142,118,179,197,167,130,124,180,214,203,153,140,161,200,191,159,141,227,170,166,
  166,106,131,0,176,156,109,196,175,175,174,161,230,191,159,150,91,180,188,173,157,
  107,193,172,172,172,116,195,183,169,146,125,208,160,160,177,128,191,176,149,175,
  136,217,162,178,130,99,158,154,135,146,106,155,148,119,137,96,161,106,114,139,84,
  0,97,95,82,65,59,23,0,0,48,83,48)



holiday <- c(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
             0,0,0,0,0,0,0,0,0,0,0,0 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
             0,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
             0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
             0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,
             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
             0,0,0,1,1,1,0,0,0)

 holidayf <- c(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
             0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,
             0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
             0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,
             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
             0,0,0,0,1,1,0,0,0)
$\endgroup$
3
$\begingroup$

Read ?forecast.Arima closely. fc$fitted does not give the forecast, it gives the in-sample fits. These are identical to the history at the beginning, because the rather complex ARIMA(2,0,2)(1,0,2)[5] model that auto.arima() finds needs an amount of differencing to fit the seasonality.

Use fc$mean to extract the point forecasts. Note that the graph also shows forecasts that are appreciably different from the history. Notably, you get negative values. Given that all historical values are nonnegative, you may want to think about constraining your forecasts in some way.

enter image description here

$\endgroup$
  • $\begingroup$ Hi Stephan, thanks for such a quick response. Thank you for the clarity on fc$fitted. How would I go about constraining it? I thought the negative values were a consequence of the public holiday. $\endgroup$ – user3497385 Apr 6 '14 at 19:57
  • $\begingroup$ Yes, the negative values are due to the holiday effect. But do negative values make sense for the call center data you are forecasting? You can simply truncate forecasts at zero if they are negative. In principle, you could work on the log scale, but the zeros in your history make that problematic (unless you first add a small number and subtract it out afterwards). $\endgroup$ – Stephan Kolassa Apr 6 '14 at 20:03
  • $\begingroup$ I agree with you on all those points. I think your suggestion to truncate to zero is the easiest. Lastly, what would I do if there was no stats for a day, like an NA. How would the code change? I think putting a zero is not advisable? $\endgroup$ – user3497385 Apr 6 '14 at 20:09
  • $\begingroup$ ARIMA has major conceptual difficulties with missing data. I actually don't know whether and how auto.arima() deals with that. You have so much data here that perhaps you can deal with (few) missings very simply, by taking the average of seasonally neighboring points (i.e., points +/- 5 steps away) before modeling. $\endgroup$ – Stephan Kolassa Apr 7 '14 at 5:15
  • 1
    $\begingroup$ auto.arima() handles missing values seamlessly. The estimation is done in state space so that missing values are handled via the Kalman filter algorithm. $\endgroup$ – Rob Hyndman Apr 7 '14 at 10:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.