This post focuses primarily on forecasting the monthly unemployment rate in the Netherlands beyond the sample period. Predicting the unemployment rate is pivotal for the economic and financial planning of a country and presents a significant challenge for policymakers. Traditional stochastic time series models, including seasonal adjustments, ARIMA, and ETS models, are employed for this purpose.
You should use this chunk for renew memory.
if(!is.null(dev.list())) dev.off()
## null device
## 1
cat("\014")
rm(list=ls(all=TRUE))
Below, you need to install the packages.
# Install require packages:
# install.packages("readxl")
# install.packages("forecast")
# install.packages("seastests")
# install.packages("xts")
# install.packages("zoo")
# install.packages("stats")
# install.packages("graphics")
# install.packages("utils")
# install.packages("RJDemetra")
# install.packages("fpp2")
library(readxl)
library(forecast)
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library(seastests)
library(xts)
## Loading required package: zoo
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
library(zoo)
library(stats)
library(graphics)
library(utils)
library(RJDemetra)
library(fpp2)
## ── Attaching packages ────────────────────────────────────────────── fpp2 2.5 ──
## ✔ ggplot2 3.4.4 ✔ expsmooth 2.3
## ✔ fma 2.5
##
From this IMF data source, you can get data which you would like to analysis. In this experiment, I am searching Netherlands unseasonal monthly unemployment rate from 1983-2023. I am going to look the labour market situation of the Netherlands for this period. Firstly, I extract data from IMF web page:
https://data.imf.org/?sk=4c514d48-b6ba-49ed-8ab9-52b0c1a0179b&sid=1390030341854
I also add raw data into my github page that you can easily take.
Secondly, I use read_excel function for import data from excel to R:
# Read the Excel file into R
data <- read_excel("unemp.xlsx", sheet = "Sheet1")
# View the imported data
print(data)
## # A tibble: 492 × 2
## date unem
## <dttm> <dbl>
## 1 1983-01-01 00:00:00 10
## 2 1983-02-01 00:00:00 10.2
## 3 1983-03-01 00:00:00 10.3
## 4 1983-04-01 00:00:00 9.7
## 5 1983-05-01 00:00:00 9.4
## 6 1983-06-01 00:00:00 9.7
## 7 1983-07-01 00:00:00 8.8
## 8 1983-08-01 00:00:00 8.8
## 9 1983-09-01 00:00:00 9.4
## 10 1983-10-01 00:00:00 9.5
## # ℹ 482 more rows
unemp <- data$unem
unemp <- ts(unemp,
start = c(1983,1),
frequency = 12)
plot(unemp)
The unemployment rate appears to demonstrate pronounced seasonality and a discernible downward trend over time. Additionally, notable fluctuations, marked by significant increases and decreases, are evident in various periods. Specifically, during the mid-1990s and 2010s, the unemployment rate experienced upward trajectories. Conversely, at the onset of the 2000s, there were discernible downturns in the unemployment rate. Notably, periods of stability seem to be lacking within the observed data. Let’s we start looking for seasonal effects with statistical tools.
Initially, I am employing a dummy variable approach to identify seasonality. This method draws from the teachings of the Basic Econometrics book by Gujarati, which I extensively studied during my undergraduate education at the University. The process involves generating seasonal dummies followed by the application of a linear regression model. To illustrate, I am presenting a simplified example focusing solely on a dummy variable representing January, assigned a value of 1 for each year.
Let \(D_t\) be the dummy variable representing a particular month \(t\), such that:
\[ D_t = \begin{cases} 1 & \text{if month \( t \) satisfies a certain condition (e.g., January)} \\ 0 & \text{otherwise} \end{cases} \]
Where the dummy variable, is defined is defined as 1 if a specific condition (such as being January) is met for month t, and 0 otherwise. You can customize the condition based on your specific context and requirements.
To do this, I use a for loop:
# Initialize an empty matrix to store dummy variables
dummy <- matrix(0, nrow = 492, ncol = 11)
# Create dummy variables using a for loop
for (i in 1:11) {
dummy[, i] <- ifelse(seq_along(dummy[, i]) %% 11 == (i - 1), 1, 0)
}
# Convert the matrix to a data frame
dummy <- as.data.frame(dummy)
# Rename columns
colnames(dummy) <- paste0("d", 1:11)
# You can print the dummy variables:
# print(dummy)
The next step is that I am removing seasonality with a regression model. So, first I convert my seasonal dummies to time-series format and regress unemployment rate this dummies as follows:
\[ unemp_{t}=X\beta+\varepsilon_{t} \] where \(X\) data matrix includes dummy variables. One more important thing is I have to remove constant since I do not want to be caught dummy variable trap.
# Convert dummy dataframe to a time series object
dummy_ts <- ts(dummy)
# Fit a linear regression model and remove constant term via -1
model <- lm(unemp ~ dummy_ts-1)
# Print the summary of the model
summary(model)
##
## Call:
## lm(formula = unemp ~ dummy_ts - 1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.5600 -1.2544 -0.0318 1.2150 4.0400
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## dummy_tsd1 6.1477 0.2556 24.05 <2e-16 ***
## dummy_tsd2 6.1956 0.2528 24.51 <2e-16 ***
## dummy_tsd3 6.2311 0.2528 24.65 <2e-16 ***
## dummy_tsd4 6.2600 0.2528 24.77 <2e-16 ***
## dummy_tsd5 6.2422 0.2528 24.69 <2e-16 ***
## dummy_tsd6 6.1911 0.2528 24.49 <2e-16 ***
## dummy_tsd7 6.1511 0.2528 24.33 <2e-16 ***
## dummy_tsd8 6.0933 0.2528 24.11 <2e-16 ***
## dummy_tsd9 6.0644 0.2528 23.99 <2e-16 ***
## dummy_tsd10 6.1068 0.2556 23.89 <2e-16 ***
## dummy_tsd11 6.1318 0.2556 23.99 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.696 on 481 degrees of freedom
## Multiple R-squared: 0.9311, Adjusted R-squared: 0.9296
## F-statistic: 591.3 on 11 and 481 DF, p-value: < 2.2e-16
Overall, the regression model using dummy variables appears to be highly significant and explains a substantial portion of the variability in the unemployment rate. The coefficients of the dummy variables provide insights into the seasonality patterns observed in the data.
The next step is that I am going to look seasonal patterns of the data.
ggseasonplot(unemp)
What I am looking in here, on this seasonal plot what it is doing that each year gets its own line so I look at one year at a time across each month. It looks like the change from January to March the unemployment rate is clearly growing. In contrast, from March to June, it seems that there is usually drop. I also look another format of graph for detecting seasonality.
ggsubseriesplot(unemp)
What this plot is doing look for the averages. The average change in each months is different than each other.So, the mean of the data and the different months is very different depending on what month I am looking. However, these plots say something about seasonality, I need to do statistical perspective such as some tests that detect seasonality.
After looking graphically, while there are very pronounced seasonal effects, I observed a somewhat less distinct but still suspicious impression of seasonality. So I am looking for statistical evidences. Therefore, I use Webel-Ollech (2019) study to compiled tests related to seasonality, named after the initials of their own names. To do this:
sa_test <- combined_test(unemp, freq = 12)
summary(sa_test)
## Test used: WO
##
## Test statistic: 1
## P-value: 0 0 0
##
## The WO - test identifies seasonality
Test identifies seasonality.
In this case, it is necessary to perform deseasonalization. Since a series containing seasonal effects will yield a sinusoidal graph, it is not possible to detect the effects here.
You can get more information with chunk as follows:
?tramoseats
## starting httpd help server ... done
To perform automatic deseasonalization, level determination within seasonality, outlier detection, calendar effects, and the ARIMA method altogether, the argument “RSAfull” should be entered. If you prefer to specify these yourself, you can consult the help menu within tramoseats.
unemp_tramo <- tramoseats(unemp, spec = "RSAfull")
# You can see four different components of the series via this function:
# unemp_tramo$decomposition$components
Let’s looking plot of the components:
plot(unemp_tramo$decomposition$components)
Graphs are
y_cmp means input data sa_cmp means seasonally adjusted data t_cmp means trend component s_cmp means seasonal component i_cmp means irregular component.
I am looking for seasonal adjusted part of the data. To do this,
unemp_sa <- unemp_tramo$decomposition$components[,2]
plot(unemp_sa)
Here is the the graph of the seasonally adjusted part of the series. I test again is there any seasonality remains:
summary(combined_test(unemp_sa, freq = 12))
## Test used: WO
##
## Test statistic: 0
## P-value: 1 1 0.9999503
##
## The WO - test does not identify seasonality
The results show that there is not any seasonality of the new data. Last but not least, I am looking for forecasting seasonal adjusted unemployment rate for Netherlands.
fit_unemp_sa <- auto.arima(unemp_sa,d <- 1,D <- 0, stepwise = FALSE, approximation = FALSE, trace = TRUE)
##
## ARIMA(0,1,0) : -912.8945
## ARIMA(0,1,0) with drift : -927.3722
## ARIMA(0,1,0)(0,0,1)[12] : -923.2109
## ARIMA(0,1,0)(0,0,1)[12] with drift : -933.904
## ARIMA(0,1,0)(0,0,2)[12] : -921.1943
## ARIMA(0,1,0)(0,0,2)[12] with drift : -932.2798
## ARIMA(0,1,0)(1,0,0)[12] : -922.8133
## ARIMA(0,1,0)(1,0,0)[12] with drift : -933.1795
## ARIMA(0,1,0)(1,0,1)[12] : -921.1905
## ARIMA(0,1,0)(1,0,1)[12] with drift : -932.0485
## ARIMA(0,1,0)(1,0,2)[12] : Inf
## ARIMA(0,1,0)(1,0,2)[12] with drift : Inf
## ARIMA(0,1,0)(2,0,0)[12] : -921.5177
## ARIMA(0,1,0)(2,0,0)[12] with drift : -933.0739
## ARIMA(0,1,0)(2,0,1)[12] : -933.7669
## ARIMA(0,1,0)(2,0,1)[12] with drift : Inf
## ARIMA(0,1,0)(2,0,2)[12] : Inf
## ARIMA(0,1,0)(2,0,2)[12] with drift : Inf
## ARIMA(0,1,1) : -949.0465
## ARIMA(0,1,1) with drift : -959.2135
## ARIMA(0,1,1)(0,0,1)[12] : -949.0999
## ARIMA(0,1,1)(0,0,1)[12] with drift : -958.149
## ARIMA(0,1,1)(0,0,2)[12] : -948.9792
## ARIMA(0,1,1)(0,0,2)[12] with drift : -960.6989
## ARIMA(0,1,1)(1,0,0)[12] : -948.8332
## ARIMA(0,1,1)(1,0,0)[12] with drift : -957.9774
## ARIMA(0,1,1)(1,0,1)[12] : Inf
## ARIMA(0,1,1)(1,0,1)[12] with drift : Inf
## ARIMA(0,1,1)(1,0,2)[12] : -960.3917
## ARIMA(0,1,1)(1,0,2)[12] with drift : Inf
## ARIMA(0,1,1)(2,0,0)[12] : -948.8518
## ARIMA(0,1,1)(2,0,0)[12] with drift : -959.5901
## ARIMA(0,1,1)(2,0,1)[12] : -962.0203
## ARIMA(0,1,1)(2,0,1)[12] with drift : Inf
## ARIMA(0,1,1)(2,0,2)[12] : -965.125
## ARIMA(0,1,1)(2,0,2)[12] with drift : Inf
## ARIMA(0,1,2) : -1006.09
## ARIMA(0,1,2) with drift : -1013.547
## ARIMA(0,1,2)(0,0,1)[12] : -1004.197
## ARIMA(0,1,2)(0,0,1)[12] with drift : -1012.092
## ARIMA(0,1,2)(0,0,2)[12] : -1006.998
## ARIMA(0,1,2)(0,0,2)[12] with drift : -1019.098
## ARIMA(0,1,2)(1,0,0)[12] : -1004.17
## ARIMA(0,1,2)(1,0,0)[12] with drift : -1011.952
## ARIMA(0,1,2)(1,0,1)[12] : -1018.493
## ARIMA(0,1,2)(1,0,1)[12] with drift : Inf
## ARIMA(0,1,2)(1,0,2)[12] : -1020.055
## ARIMA(0,1,2)(1,0,2)[12] with drift : Inf
## ARIMA(0,1,2)(2,0,0)[12] : -1005.407
## ARIMA(0,1,2)(2,0,0)[12] with drift : -1014.897
## ARIMA(0,1,2)(2,0,1)[12] : -1020.562
## ARIMA(0,1,2)(2,0,1)[12] with drift : Inf
## ARIMA(0,1,3) : -1033.262
## ARIMA(0,1,3) with drift : -1039.241
## ARIMA(0,1,3)(0,0,1)[12] : -1032.041
## ARIMA(0,1,3)(0,0,1)[12] with drift : -1038.803
## ARIMA(0,1,3)(0,0,2)[12] : -1042.774
## ARIMA(0,1,3)(0,0,2)[12] with drift : -1056.739
## ARIMA(0,1,3)(1,0,0)[12] : -1031.802
## ARIMA(0,1,3)(1,0,0)[12] with drift : -1038.275
## ARIMA(0,1,3)(1,0,1)[12] : -1052.803
## ARIMA(0,1,3)(1,0,1)[12] with drift : Inf
## ARIMA(0,1,3)(2,0,0)[12] : -1038.367
## ARIMA(0,1,3)(2,0,0)[12] with drift : -1047.09
## ARIMA(0,1,4) : -1066.246
## ARIMA(0,1,4) with drift : -1070.769
## ARIMA(0,1,4)(0,0,1)[12] : -1067.604
## ARIMA(0,1,4)(0,0,1)[12] with drift : -1073.631
## ARIMA(0,1,4)(1,0,0)[12] : -1066.476
## ARIMA(0,1,4)(1,0,0)[12] with drift : -1071.843
## ARIMA(0,1,5) : -1080.169
## ARIMA(0,1,5) with drift : -1083.458
## ARIMA(1,1,0) : -980.8902
## ARIMA(1,1,0) with drift : -986.758
## ARIMA(1,1,0)(0,0,1)[12] : -980.9204
## ARIMA(1,1,0)(0,0,1)[12] with drift : -987.315
## ARIMA(1,1,0)(0,0,2)[12] : -997.3862
## ARIMA(1,1,0)(0,0,2)[12] with drift : -1013.343
## ARIMA(1,1,0)(1,0,0)[12] : -980.2145
## ARIMA(1,1,0)(1,0,0)[12] with drift : -986.3686
## ARIMA(1,1,0)(1,0,1)[12] : Inf
## ARIMA(1,1,0)(1,0,1)[12] with drift : Inf
## ARIMA(1,1,0)(1,0,2)[12] : -1008.341
## ARIMA(1,1,0)(1,0,2)[12] with drift : Inf
## ARIMA(1,1,0)(2,0,0)[12] : -986.5868
## ARIMA(1,1,0)(2,0,0)[12] with drift : -993.9983
## ARIMA(1,1,0)(2,0,1)[12] : -1008.298
## ARIMA(1,1,0)(2,0,1)[12] with drift : Inf
## ARIMA(1,1,0)(2,0,2)[12] : Inf
## ARIMA(1,1,0)(2,0,2)[12] with drift : Inf
## ARIMA(1,1,1) : -1116.2
## ARIMA(1,1,1) with drift : -1114.9
## ARIMA(1,1,1)(0,0,1)[12] : -1159.791
## ARIMA(1,1,1)(0,0,1)[12] with drift : -1158.658
## ARIMA(1,1,1)(0,0,2)[12] : Inf
## ARIMA(1,1,1)(0,0,2)[12] with drift : Inf
## ARIMA(1,1,1)(1,0,0)[12] : -1136.201
## ARIMA(1,1,1)(1,0,0)[12] with drift : -1134.844
## ARIMA(1,1,1)(1,0,1)[12] : Inf
## ARIMA(1,1,1)(1,0,1)[12] with drift : Inf
## ARIMA(1,1,1)(1,0,2)[12] : Inf
## ARIMA(1,1,1)(1,0,2)[12] with drift : Inf
## ARIMA(1,1,1)(2,0,0)[12] : -1160.623
## ARIMA(1,1,1)(2,0,0)[12] with drift : -1159.377
## ARIMA(1,1,1)(2,0,1)[12] : Inf
## ARIMA(1,1,1)(2,0,1)[12] with drift : Inf
## ARIMA(1,1,2) : -1144.25
## ARIMA(1,1,2) with drift : -1143.06
## ARIMA(1,1,2)(0,0,1)[12] : -1190.859
## ARIMA(1,1,2)(0,0,1)[12] with drift : -1189.832
## ARIMA(1,1,2)(0,0,2)[12] : Inf
## ARIMA(1,1,2)(0,0,2)[12] with drift : Inf
## ARIMA(1,1,2)(1,0,0)[12] : -1165.718
## ARIMA(1,1,2)(1,0,0)[12] with drift : -1164.438
## ARIMA(1,1,2)(1,0,1)[12] : Inf
## ARIMA(1,1,2)(1,0,1)[12] with drift : Inf
## ARIMA(1,1,2)(2,0,0)[12] : -1190.558
## ARIMA(1,1,2)(2,0,0)[12] with drift : -1189.417
## ARIMA(1,1,3) : -1142.265
## ARIMA(1,1,3) with drift : -1141.075
## ARIMA(1,1,3)(0,0,1)[12] : -1188.816
## ARIMA(1,1,3)(0,0,1)[12] with drift : -1187.779
## ARIMA(1,1,3)(1,0,0)[12] : -1163.71
## ARIMA(1,1,3)(1,0,0)[12] with drift : -1162.429
## ARIMA(1,1,4) : -1141.891
## ARIMA(1,1,4) with drift : -1140.739
## ARIMA(2,1,0) : -1078.269
## ARIMA(2,1,0) with drift : -1079.423
## ARIMA(2,1,0)(0,0,1)[12] : -1108.561
## ARIMA(2,1,0)(0,0,1)[12] with drift : -1109.915
## ARIMA(2,1,0)(0,0,2)[12] : Inf
## ARIMA(2,1,0)(0,0,2)[12] with drift : Inf
## ARIMA(2,1,0)(1,0,0)[12] : -1091.705
## ARIMA(2,1,0)(1,0,0)[12] with drift : -1092.806
## ARIMA(2,1,0)(1,0,1)[12] : Inf
## ARIMA(2,1,0)(1,0,1)[12] with drift : Inf
## ARIMA(2,1,0)(1,0,2)[12] : Inf
## ARIMA(2,1,0)(1,0,2)[12] with drift : Inf
## ARIMA(2,1,0)(2,0,0)[12] : -1112.459
## ARIMA(2,1,0)(2,0,0)[12] with drift : -1113.719
## ARIMA(2,1,0)(2,0,1)[12] : Inf
## ARIMA(2,1,0)(2,0,1)[12] with drift : Inf
## ARIMA(2,1,1) : -1141.708
## ARIMA(2,1,1) with drift : -1140.451
## ARIMA(2,1,1)(0,0,1)[12] : -1188.912
## ARIMA(2,1,1)(0,0,1)[12] with drift : -1187.838
## ARIMA(2,1,1)(0,0,2)[12] : Inf
## ARIMA(2,1,1)(0,0,2)[12] with drift : Inf
## ARIMA(2,1,1)(1,0,0)[12] : -1163.348
## ARIMA(2,1,1)(1,0,0)[12] with drift : -1162.014
## ARIMA(2,1,1)(1,0,1)[12] : Inf
## ARIMA(2,1,1)(1,0,1)[12] with drift : Inf
## ARIMA(2,1,1)(2,0,0)[12] : -1188.217
## ARIMA(2,1,1)(2,0,0)[12] with drift : -1187.005
## ARIMA(2,1,2) : -1142.307
## ARIMA(2,1,2) with drift : -1141.125
## ARIMA(2,1,2)(0,0,1)[12] : -1188.819
## ARIMA(2,1,2)(0,0,1)[12] with drift : -1187.782
## ARIMA(2,1,2)(1,0,0)[12] : -1163.747
## ARIMA(2,1,2)(1,0,0)[12] with drift : -1162.471
## ARIMA(2,1,3) : -1140.258
## ARIMA(2,1,3) with drift : -1139.051
## ARIMA(3,1,0) : -1115.112
## ARIMA(3,1,0) with drift : -1114.905
## ARIMA(3,1,0)(0,0,1)[12] : -1154.022
## ARIMA(3,1,0)(0,0,1)[12] with drift : -1153.963
## ARIMA(3,1,0)(0,0,2)[12] : Inf
## ARIMA(3,1,0)(0,0,2)[12] with drift : Inf
## ARIMA(3,1,0)(1,0,0)[12] : -1131.071
## ARIMA(3,1,0)(1,0,0)[12] with drift : -1130.804
## ARIMA(3,1,0)(1,0,1)[12] : Inf
## ARIMA(3,1,0)(1,0,1)[12] with drift : Inf
## ARIMA(3,1,0)(2,0,0)[12] : -1160.085
## ARIMA(3,1,0)(2,0,0)[12] with drift : -1159.849
## ARIMA(3,1,1) : -1141.049
## ARIMA(3,1,1) with drift : -1139.812
## ARIMA(3,1,1)(0,0,1)[12] : -1187.816
## ARIMA(3,1,1)(0,0,1)[12] with drift : -1186.749
## ARIMA(3,1,1)(1,0,0)[12] : -1162.363
## ARIMA(3,1,1)(1,0,0)[12] with drift : -1161.04
## ARIMA(3,1,2) : -1145.856
## ARIMA(3,1,2) with drift : -1145.192
## ARIMA(4,1,0) : -1134.843
## ARIMA(4,1,0) with drift : -1134.03
## ARIMA(4,1,0)(0,0,1)[12] : -1180.344
## ARIMA(4,1,0)(0,0,1)[12] with drift : -1179.709
## ARIMA(4,1,0)(1,0,0)[12] : -1154.252
## ARIMA(4,1,0)(1,0,0)[12] with drift : -1153.368
## ARIMA(4,1,1) : -1140.51
## ARIMA(4,1,1) with drift : -1139.296
## ARIMA(5,1,0) : -1138.508
## ARIMA(5,1,0) with drift : -1137.466
##
##
##
## Best model: ARIMA(1,1,2)(0,0,1)[12]
After running the ARIMA models, I take the summary results:
print(summary(fit_unemp_sa))
## Series: unemp_sa
## ARIMA(1,1,2)(0,0,1)[12]
##
## Coefficients:
## ar1 ma1 ma2 sma1
## 0.9776 -0.9587 0.2495 -0.5100
## s.e. 0.0106 0.0448 0.0410 0.0841
##
## sigma^2 = 0.005069: log likelihood = 600.49
## AIC=-1190.98 AICc=-1190.86 BIC=-1170
##
## Training set error measures:
## ME RMSE MAE MPE MAPE
## Training set -0.002868487 0.07083754 0.05416599 -0.02389498 0.7635837
## MASE ACF1
## Training set 0.07840791 -0.003407759
Statistical analysis shows that ARIMA(1,1,2)(0,0,1)[12] model is the best according to AIC criteria. I, then, look for residuals that show me the model robustness check:
checkresiduals(fit_unemp_sa)
##
## Ljung-Box test
##
## data: Residuals from ARIMA(1,1,2)(0,0,1)[12]
## Q* = 64.088, df = 20, p-value = 1.629e-06
##
## Model df: 4. Total lags used: 24
Residuals seems to follow normal distribution and more stability ACF values. So, I can keep going forecast the series. But, I am wondering ETS calculation:
fit_ets <- ets(unemp_sa)
print(summary(fit_ets))
## ETS(A,Ad,N)
##
## Call:
## ets(y = unemp_sa)
##
## Smoothing parameters:
## alpha = 0.7386
## beta = 0.2715
## phi = 0.9507
##
## Initial states:
## l = 12.0182
## b = -0.017
##
## sigma: 0.0751
##
## AIC AICc BIC
## 508.6542 508.8274 533.8451
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE
## Training set -0.002822835 0.0746825 0.05664773 -0.02241016 0.809953 0.08200035
## ACF1
## Training set 0.001264234
checkresiduals(fit_ets)
##
## Ljung-Box test
##
## data: Residuals from ETS(A,Ad,N)
## Q* = 68.914, df = 24, p-value = 3.189e-06
##
## Model df: 0. Total lags used: 24
After comparing ACF values, ARIMA model estimation seems more relevant for forecasting of unemployment rate.
To do this, I use forecast function. I prefer that I need to forecast 2024 January, February and March seasonal adjusted unemployment rate of Netherlands. And also, I put last 10 observation for easily show the graph:
unemp_sa_forecast <- forecast(fit_unemp_sa,h=3)
autoplot(unemp_sa_forecast,include = 20)
Let’s get the point, 80% and 95% interval forecasts of the series:
print(summary(unemp_sa_forecast))
##
## Forecast method: ARIMA(1,1,2)(0,0,1)[12]
##
## Model Information:
## Series: unemp_sa
## ARIMA(1,1,2)(0,0,1)[12]
##
## Coefficients:
## ar1 ma1 ma2 sma1
## 0.9776 -0.9587 0.2495 -0.5100
## s.e. 0.0106 0.0448 0.0410 0.0841
##
## sigma^2 = 0.005069: log likelihood = 600.49
## AIC=-1190.98 AICc=-1190.86 BIC=-1170
##
## Error measures:
## ME RMSE MAE MPE MAPE
## Training set -0.002868487 0.07083754 0.05416599 -0.02389498 0.7635837
## MASE ACF1
## Training set 0.07840791 -0.003407759
##
## Forecasts:
## Point Forecast Lo 80 Hi 80 Lo 95 Hi 95
## Jan 2024 3.477566 3.386319 3.568813 3.338016 3.617116
## Feb 2024 3.457027 3.326760 3.587294 3.257800 3.656254
## Mar 2024 3.455141 3.279763 3.630518 3.186924 3.723357
Let’s discuss the results. I predict that first month point estimation is 3.47% and when %5 error rate is used, lower and higher interval predictions are 3.33% and 3.61%, respectively. When I compare this result with the actual observation of January unemployment rate, it is in the interval band that I provide. You can check the result from this web site: