Weekly forecasts with holidays - r
I use Hyndman's forecast package to produce a somewhat accurate tbats forecast at the weekly level, but I have significant errors on holidays. How can I include holidays in the model? Also, Arima has been shown to fit my weekly data poorly. So holidays would have to be added in a non-arima way.
I have seen two solutions. One https://robjhyndman.com/hyndsight/dailydata/ shows how to add holidays as dummy variables with fourier terms. The problem is dummy variables take the form of 1 or 0. I know that different holidays have different effects that a 1 or 0 would not capture. Black Friday, for example, is very different from Chinese New Year.
Another solution is have seen is here https://robjhyndman.com/hyndsight/forecast7-part-2/ where covariate nnetr change is used as an alternative to auto.arima with seasonal dummy variables. The problem is I don't see how to write the R code to input my holidays. An example would be useful.
The benchmark for time series modeling for use by official statistics agencies is x13-arima-seats by the US Census bureau. It deals with seasonal effects as well as with "parametric" holidays including, say, the Chinese New Year as well as Easter.
The functionality is available in R via the seasonal package which installs and uses the underlying x13-arima-seats binary.
And there is also a full-feature interactive website giving access to most-if-not-all features.
Have you read about Facebook's prophet package?
Haven't used it but from reading the documentation, it seems like a quick implementation that also accounts for holidays:
https://cran.r-project.org/web/packages/prophet/prophet.pdf
Implements a procedure for forecasting time series data based on
an additive model where non-linear trends are fit with yearly and weekly
seasonality, plus holidays [...]
https://cran.r-project.org/web/packages/prophet/vignettes/quick_start.html
The following did everything I needed it to do.
k=23
#forecast holidays
#bool list of future holidays
holidayf <- c(0,0,0,0,0,1,0,0,0,1,1,1,1,1,0,0,0)
h <- length(holidayf)
#given holidays
holiday <- df[,2]
y <- ts(df[,1],start = 2011,frequency = 52)
z <- fourier(y, K=k)
zf <- fourier(y, K=k, h=h)
fit <- auto.arima(y, xreg=cbind(z,holiday), seasonal=FALSE)
fc <- forecast(fit, xreg=cbind(zf,holidayf), h=h)
fc %>% autoplot()
summary(fit)
To solve the problem of different holidays having different effect, I simply added additional holiday dummy variables. For example, you can make a vector of good holidays and a vector of bad holidays and cbind them then put them in xreg. I did not show this in the above code, but it is straight forward.
Related
Time Series Forecasting using Support Vector Machine (SVM) in R
I've tried searching but couldn't find a specific answer to this question. So far I'm able to realize that Time Series Forecasting is possible using SVM. I've gone through a few papers/articles who've performed the same but didn't mention any code, instead explained the algorithm (which I didn't quite understand). And some have done it using python. My problem here is that: I have a company data(say univariate) of sales from 2010 to 2017. And I need to forecast the sales value for 2018 using SVM in R. Would you be kind enough to simply present and explain the R code to perform the same using a small example? I really do appreciate your inputs and efforts! Thanks!!!
let's assume you have monthly data, for example derived from Air Passengers data set. You don't need the timeseries-type data, just a data frame containing time steps and values. Let's name them x and y. Next you develop an svm model, and specify the time steps you need to forecast. Use the predict function to compute the forecast for given time steps. That's it. However, support vector machine is not commonly regarded as the best method for time series forecasting, especially for long series of data. It can perform good for few observations ahead, but I wouldn't expect good results for forecasting eg. daily data for a whole next year (but it obviously depends on data). Simple R code for SVM-based forecast: # prepare sample data in the form of data frame with cols of timesteps (x) and values (y) data(AirPassengers) monthly_data <- unclass(AirPassengers) months <- 1:144 DF <- data.frame(months,monthly_data) colnames(DF)<-c("x","y") # train an svm model, consider further tuning parameters for lower MSE svmodel <- svm(y ~ x,data=DF, type="eps-regression",kernel="radial",cost=10000, gamma=10) #specify timesteps for forecast, eg for all series + 12 months ahead nd <- 1:156 #compute forecast for all the 156 months prognoza <- predict(svmodel, newdata=data.frame(x=nd)) #plot the results ylim <- c(min(DF$y), max(DF$y)) xlim <- c(min(nd),max(nd)) plot(DF$y, col="blue", ylim=ylim, xlim=xlim, type="l") par(new=TRUE) plot(prognoza, col="red", ylim=ylim, xlim=xlim)
Result of nnetar is strangely flat
I'm new to R but have some experience with ARIMA models. Now I wanted to learn a bit about neural networks for forecasting. I tried to repeat the procedure from Rob's post. It worked great for the data set he used. It also worked great for imaginary datasets I created. But then I tried to use real-life data (revenue data for 7 years monthly) and the resulting forecasts are strangely flat. My code: read.csv("Revenue.csv",header=TRUE) x <-read.csv("Revenue.csv",header=TRUE) y<-ts(x,freq=12,start=c(2011,1)) (fit<-nnetar(y)) fcast <- forecast(fit, PI=TRUE, h=20, bootstrap=TRUE) autoplot(fcast) The result is an almost straight line (attached as picture 1). That strikes me as odd, because the trend has been positive so far: there was a revenue growth of more than 100% every year. Still the result of nnetar is that the revenue will stabilise. How is that possible? As a comparison I used Auto.arima for the same data set (picture 2). It shows a clear upward trend.
One suggestion, even if its hard to help without the data sample. It appears than nnetar is not capturing very well the trend in your data. Probably you could try to use a trend as external regressors ( xreg argument) For example for a deterministic trend. Trend=seq(from=start, to=end, by=1) (fit <- nnetar(y, xreg=Trend)) (f <- forecast(fit,h=h, xreg=seq(from=end, to=end+h, by=1)) An alternative would be to use more lag or seasonal lags (p and P argument in your nnetar model)
Time series forecasting, dealing with known big orders
I have many data sets with known outliers (big orders) data <- matrix(c("08Q1","08Q2","08Q3","08Q4","09Q1","09Q2","09Q3","09Q4","10Q1","10Q2","10Q3","10Q4","11Q1","11Q2","11Q3","11Q4","12Q1","12Q2","12Q3","12Q4","13Q1","13Q2","13Q3","13Q4","14Q1","14Q2","14Q3","14Q4","15Q1", 155782698, 159463653.4, 172741125.6, 204547180, 126049319.8, 138648461.5, 135678842.1, 242568446.1, 177019289.3, 200397120.6, 182516217.1, 306143365.6, 222890269.2, 239062450.2, 229124263.2, 370575384.7, 257757410.5, 256125841.6, 231879306.6, 419580274, 268211059, 276378232.1, 261739468.7, 429127062.8, 254776725.6, 329429882.8, 264012891.6, 496745973.9, 284484362.55),ncol=2,byrow=FALSE) The top 11 outliers of this specific series are: outliers <- matrix(c("14Q4","14Q2","12Q1","13Q1","14Q2","11Q1","11Q4","14Q2","13Q4","14Q4","13Q1",20193525.68, 18319234.7, 12896323.62, 12718744.01, 12353002.09, 11936190.13, 11356476.28, 11351192.31, 10101527.85, 9723641.25, 9643214.018),ncol=2,byrow=FALSE) What methods are there that i can forecast the time series taking these outliers into consideration? I have already tried replacing the next biggest outlier (so running the data set 10 times replacing the outliers with the next biggest until the 10th data set has all the outliers replaced). I have also tried simply removing the outliers (so again running the data set 10 times removing an outlier each time until all 10 are removed in the 10th data set) I just want to point out that removing these big orders does not delete the data point completely as there are other deals that happen in that quarter My code tests the data through multiple forecasting models (ARIMA weighted on the out sample, ARIMA weighted on the in sample, ARIMA weighted, ARIMA, Additive Holt-winters weighted and Multiplcative Holt-winters weighted) so it needs to be something that can be adapted to these multiple models. Here are a couple more data sets that i used, i do not have the outliers for these series yet though data <- matrix(c("08Q1","08Q2","08Q3","08Q4","09Q1","09Q2","09Q3","09Q4","10Q1","10Q2","10Q3","10Q4","11Q1","11Q2","11Q3","11Q4","12Q1","12Q2","12Q3","12Q4","13Q1","13Q2","13Q3","13Q4","14Q1","14Q2","14Q3", 26393.99306, 13820.5037, 23115.82432, 25894.41036, 14926.12574, 15855.8857, 21565.19002, 49373.89675, 27629.10141, 43248.9778, 34231.73851, 83379.26027, 54883.33752, 62863.47728, 47215.92508, 107819.9903, 53239.10602, 71853.5, 59912.7624, 168416.2995, 64565.6211, 94698.38748, 80229.9716, 169205.0023, 70485.55409, 133196.032, 78106.02227), ncol=2,byrow=FALSE) data <- matrix(c("08Q1","08Q2","08Q3","08Q4","09Q1","09Q2","09Q3","09Q4","10Q1","10Q2","10Q3","10Q4","11Q1","11Q2","11Q3","11Q4","12Q1","12Q2","12Q3","12Q4","13Q1","13Q2","13Q3","13Q4","14Q1","14Q2","14Q3",3311.5124, 3459.15634, 2721.486863, 3286.51708, 3087.234059, 2873.810071, 2803.969394, 4336.4792, 4722.894582, 4382.349583, 3668.105825, 4410.45429, 4249.507839, 3861.148928, 3842.57616, 5223.671347, 5969.066896, 4814.551389, 3907.677816, 4944.283864, 4750.734617, 4440.221993, 3580.866991, 3942.253996, 3409.597269, 3615.729974, 3174.395507),ncol=2,byrow=FALSE) If this is too complicated then an explanation of how, in R, once outliers are detected using certain commands, the data is dealt with to forecast. e.g smoothing etc and how i can approach that writing a code myself (not using the commands that detect outliers)
Your outliers appear to be seasonal variations with the largest orders appearing in the 4-th quarter. Many of the forecasting models you mentioned include the capability for seasonal adjustments. As an example, the simplest model could have a linear dependence on year with corrections for all seasons. Code would look like: df <- data.frame(period= c("08Q1","08Q2","08Q3","08Q4","09Q1","09Q2","09Q3","09Q4","10Q1","10Q2","10Q3", "10Q4","11Q1","11Q2","11Q3","11Q4","12Q1","12Q2","12Q3","12Q4","13Q1","13Q2", "13Q3","13Q4","14Q1","14Q2","14Q3","14Q4","15Q1"), order= c(155782698, 159463653.4, 172741125.6, 204547180, 126049319.8, 138648461.5, 135678842.1, 242568446.1, 177019289.3, 200397120.6, 182516217.1, 306143365.6, 222890269.2, 239062450.2, 229124263.2, 370575384.7, 257757410.5, 256125841.6, 231879306.6, 419580274, 268211059, 276378232.1, 261739468.7, 429127062.8, 254776725.6, 329429882.8, 264012891.6, 496745973.9, 42748656.73)) seasonal <- data.frame(year=as.numeric(substr(df$period, 1,2)), qtr=substr(df$period, 3,4), data=df$order) ord_model <- lm(data ~ year + qtr, data=seasonal) seasonal <- cbind(seasonal, fitted=ord_model$fitted) library(reshape2) library(ggplot2) plot_fit <- melt(seasonal,id.vars=c("year", "qtr"), variable.name = "Source", value.name="Order" ) ggplot(plot_fit, aes(x=year, y = Order, colour = qtr, shape=Source)) + geom_point(size=3) which gives the results shown in the chart below: Models with a seasonal adjustment but nonlinear dependence upon year may give better fits.
You already said you tried different Arima-models, but as mentioned by WaltS, your series don't seem to contain big outliers, but a seasonal-component, which is nicely captured by auto.arima() in the forecast package: myTs <- ts(as.numeric(data[,2]), start=c(2008, 1), frequency=4) myArima <- auto.arima(myTs, lambda=0) myForecast <- forecast(myArima) plot(myForecast) where the lambda=0 argument to auto.arima() forces a transformation (or you could take log) of the data by boxcox to take the increasing amplitude of the seasonal-component into account.
The approach you are trying to use to cleanse your data of outliers is not going to be robust enough to identify them. I should add that there is a free outlier package in R called tsoutliers, but it won't do the things I am about to show you.... You have an interesting time series here. The trend changes over time with the upward trend weakening a bit. If you bring in two time trend variables with the first beginning at 1 and another beginning at period 14 and forward you will capture this change. As for seasonality, you can capture the high 4th quarter with a dummy variable. The model is parsimonios as the other 3 quarters are not different from the average plus no need for an AR12, seasonal differencing or 3 seasonal dummies. You can also capture the impact of the last two observations being outliers with two dummy variables. Ignore the 49 above the word trend as that is just the name of the series being modeled.
Negative values in timeseries when removing seasonal values with HoltWinters (R)
i'm new to R, so I'm having trouble with this time series data For example (the real data is way larger) data <- c(7,5,3,2,5,2,4,11,5,4,7,22,5,14,18,20,14,22,23,20,23,16,21,23,42,64,39,34,39,43,49,59,30,15,10,12,4,2,4,6,7) ts <- ts(data,frequency = 12, start = c(2010,1)) So if I try to decompose the data to adjust it ts.decompose <- decompose(ts) ts.adjust <- ts - ts.decompose$seasonal ts.hw <- HoltWinters(ts.adjust) ts.forecast <- forecast.HoltWinters(ts.hw, h = 10) plot.forecast(ts.forecast) But for the first values I got negative values, why this is happening?
Well, you are forecasting the seasonally adjusted time series, and of course the deseasonalized series ts.adjust can already contain negative values by itself, and in fact, it actually does. In addition, even if the original series contained only positive values, Holt-Winters can yield negative forecasts. It is not constrained. I would suggest trying to model your original (not seasonally adjusted) time series directly using ets() in the forecast package. It usually does a good job in detecting seasonality. (And it can also yield negative forecasts or prediction intervals.) I very much recommend this free online forecasting textbook. Given your specific question, this may also be helpful.
r holtwinters predict
I am using R for sometime now and some days ago I found a very interesting function which made a prediction on a given time series. It just took the data from the known time series and applied it on a given period, but it kept the pattern. The problem is that I lost it. I am sure it was a sort of HoltWinters. I am trying two days to find something, but till now without success. Could someone please give me a hand on this!
Just use predict: # Assuming you have some timeseries data in myts hw <- HoltWinters(myts) predict(hw, 10) # predict 10 periods ahead
You can use forecast.HoltWinters #Model creation fit <- HoltWinters(ts.data,gamma=FALSE) #Load forecast package require(forecast) #Apply model into forecast forecast(fit)