DATA 624 - Predictive Analystics - (Assignment 2)

INSTRUCTIONS

Do exercises 3.1, 3.2, 3.3, 3.4, 3.5, 3.7, 3.8 and 3.9 from the online Hyndman book. Please include your Rpubs link along with.pdf file of your run code

Due on Sep 15, 2024 11:59 PM

LOAD PACKAGES

The following code below loops through the list of necessary packages and checks to determine if each is installed. If the package is not found it is installed and loaded.

pkges <- c( "kableExtra", "readr", "readxl", "fpp3", "seasonal")

# Loop through the packages
for (p in pkges) {
  # Check if package is installed
  if (!requireNamespace(p, quietly = TRUE)) {
    install.packages(p) #If the package is not installed, install the package
    
    library(p, character.only = TRUE) #Load the package
  } else {
    library(p, character.only = TRUE) #If the package is already installed, load the package
  }
}
## Warning: package 'kableExtra' was built under R version 4.4.1
## Warning: package 'readr' was built under R version 4.4.1
## Warning: package 'readxl' was built under R version 4.4.1
## Warning: package 'fpp3' was built under R version 4.4.1
## Warning: package 'tibble' was built under R version 4.4.1
## Warning: package 'dplyr' was built under R version 4.4.1
## Warning: package 'tidyr' was built under R version 4.4.1
## Warning: package 'lubridate' was built under R version 4.4.1
## Warning: package 'ggplot2' was built under R version 4.4.1
## Warning: package 'tsibble' was built under R version 4.4.1
## Warning: package 'tsibbledata' was built under R version 4.4.1
## Warning: package 'feasts' was built under R version 4.4.1
## Warning: package 'fabletools' was built under R version 4.4.1
## Warning: package 'fable' was built under R version 4.4.1
## Warning: package 'seasonal' was built under R version 4.4.1

GDP DATA

gdp_data <- global_economy

head(gdp_data, 10)%>% kable() %>% 
  kable_styling(bootstrap_options = "striped", font_size = 12,) %>% 
  scroll_box(height = "100%", width = "100%", fixed_thead = T)
Country Code Year GDP Growth CPI Imports Exports Population
Afghanistan AFG 1960 537777811 NA NA 7.024793 4.132233 8996351
Afghanistan AFG 1961 548888896 NA NA 8.097166 4.453443 9166764
Afghanistan AFG 1962 546666678 NA NA 9.349593 4.878051 9345868
Afghanistan AFG 1963 751111191 NA NA 16.863910 9.171601 9533954
Afghanistan AFG 1964 800000044 NA NA 18.055555 8.888893 9731361
Afghanistan AFG 1965 1006666638 NA NA 21.412803 11.258279 9938414
Afghanistan AFG 1966 1399999967 NA NA 18.571428 8.571429 10152331
Afghanistan AFG 1967 1673333418 NA NA 14.209827 6.772908 10372630
Afghanistan AFG 1968 1373333367 NA NA 15.210356 8.899677 10604346
Afghanistan AFG 1969 1408888922 NA NA 14.984227 10.094637 10854428

EXERCISE

3.7.1

Consider the GDP information in global_economy. Plot the GDP per capita for each country over time.

gdp_data <- gdp_data %>%
  mutate(GDP_cap = GDP/Population) %>%
  filter(!is.na(GDP_cap)) %>%  # Remove rows where GDP_cap is missing
  arrange(Country, Year)  # Sort by Country and Year

gdp_data %>%
  autoplot(GDP/Population,show.legend = FALSE) +
  labs(title = "GDP per Capita by Country Over Time", 
       y = "GDP per Capita", 
       x = "Year")

#### Which country has the highest GDP per capita?

# Find the country with the highest GDP per capita
highest_gdp_country <- gdp_data %>%
  filter(GDP_cap == max(GDP_cap, na.rm=TRUE))  

# Extract the country name with the highest GDP per capita
gdp_top_country_NAME <- highest_gdp_country$Country

print(paste0('The table below shows that ',gdp_top_country_NAME,' has the highest GDP per capita.'))
## [1] "The table below shows that Monaco has the highest GDP per capita."
highest_gdp_country %>% kable() %>% 
  kable_styling(bootstrap_options = "striped", font_size = 12,) %>% 
  scroll_box(height = "100%", width = "100%", fixed_thead = T)
Country Code Year GDP Growth CPI Imports Exports Population GDP_cap
Monaco MCO 2014 7060236168 7.179637 NA NA NA 38132 185152.5

How has this changed over time?

The plot below illustrates that Monaco’s GDP per capita has generally increased over time, with occasional declines that align with trends observed in other countries.

# Filter the data for the top country to see how their GDP per capita changes over time
gdp_top_country <- gdp_data %>%
  filter(Country == gdp_top_country_NAME)

# Plot the change
gdp_top_country %>%
  autoplot(GDP_cap) +
  labs(title = paste("GDP per Capita Over Time for", gdp_top_country_NAME),
       y = "GDP per Capita",
       x = "Year")

3.7.2

For each of the following series, make a graph of the data. If transforming seems appropriate, do so and describe the effect.

* United States GDP from global_economy.

# Filter data for United States GDP
us_gdp <- global_economy %>%
  filter(Country == "United States")

# Plot United States GDP
us_gdp %>%
  autoplot(GDP) +
  labs(title = "United States GDP Over Time", 
       y = "GDP (USD)",
       x = "Year")+
  scale_y_continuous(labels = scales::dollar)

The plot above shows a significant increase over time in the U.S. GDP, with large increases in the more recent years.

Usually if the GDP shows exponential growth (i.e., the increases become larger over time in a non-linear fashion), a log transformation might be appropriate to stabilize the variance and make trends clearer as indicated below..

The log transformation will stabilize the growth and makes the data easier to interpret.

# Log transform United States GDP
us_gdp %>%
  autoplot(log(GDP)) +
  labs(title = "Log-Transformed United States GDP Over Time", 
       y = "Log GDP",
       x = "Year")

When the log transformation is applied, the log-transformation flattens the sharp increase, making it easier to observe relative changes in the GDP over time. This is because a log transformation reduces the impact of very large values, allowing you to see trends more clearly without being overwhelmed by exponential growth.

* Slaughter of Victorian “Bulls, bullocks and steers” in aus_livestock.

# Filter data for Victorian "Bulls, bullocks and steers" slaughter
vic_livestock <- aus_livestock %>%
  filter(State == "Victoria", Animal == "Bulls, bullocks and steers")

# Plot the Victorian slaughter data
vic_livestock %>%
  autoplot(Count) +
  labs(title = "Slaughter of Victorian (Bulls, Bullocks, and Steers) ", 
       y = "Number of Animals Slaughtered",
       x = "Year")+
  scale_y_continuous(labels = scales::comma)

* Victorian Electricity Demand from vic_elec.

# Plot the Victorian electricity demand
vic_elec %>%
  autoplot(Demand) +
  labs(title = "Victorian Electricity Demand Over Time", 
       y = "Electricity Demand (MW)", 
       x = "Time")

* Gas production from aus_production.

# Plot gas production
aus_production %>%
  autoplot(Gas) +
  labs(title = "Australian Gas Production Over Time", 
       y = "Gas Production", 
       x = "Year")

The Plot below shows inconsistency in the seasonal variation of Australian gas production over time, so Box-Cox transformation is used to stabilize the variance.

# Filter out rows where Gas is missing
aus_production_clean <- aus_production %>%
  filter(!is.na(Gas))

# Estimate the best lambda for Box-Cox transformation
lambda <- aus_production_clean %>%
  features(Gas, features = guerrero) %>%
  pull(lambda_guerrero)

# Apply STL decomposition with Box-Cox transformation
aus_production_clean %>%
 autoplot(box_cox(Gas, lambda)) +
  labs(title = "Box-Cox Transformed Australian Gas Production Over Time", 
       y = "Box-Cox Transformed Gas Production", 
       x = "Year")

EXercise 3.7.3

Why is a Box-Cox transformation unhelpful for the canadian_gas data?

canadian_gas_data <- canadian_gas

head(canadian_gas_data, 10)%>% kable() %>% 
  kable_styling(bootstrap_options = "striped", font_size = 12,) %>% 
  scroll_box(height = "100%", width = "100%", fixed_thead = T)
Month Volume
1960 Jan 1.4306
1960 Feb 1.3059
1960 Mar 1.4022
1960 Apr 1.1699
1960 May 1.1161
1960 Jun 1.0113
1960 Jul 0.9660
1960 Aug 0.9773
1960 Sep 1.0311
1960 Oct 1.2521
canadian_gas_data %>%
  autoplot(Volume) +
  labs(title = "Canadian Gas Prodution  Over Time", 
       y = "Gas Volume (Million Cubic Meters)", 
       x = "Year and Month")

lambda <- canadian_gas_data |>
  features(Volume, features = guerrero) |>
  pull(lambda_guerrero)

canadian_gas_data |>
  autoplot(box_cox(Volume, lambda)) +
  labs(title = "Box-Cox Transformed - Canadian Gas Prodution  Over Time" , 
       y = "Gas Volume (Million Cubic Meters)", 
       x = "Year and Month")

A Box-Cox transformation is ineffective for the canadian_gas dataset because it fails to smooth the seasonal variation in the data. This is likely due to the inconsistent change in variation, which rises in the middle and then decreases, rather than following a consistent upward trend.

EXercise 3.7.4

What Box-Cox transformation would you select for your retail data (from Exercise 7 in Section 2.10)?

set.seed(081282)

# Load the retail data 
# Filter the data to use only a specific time series for a retail category.
retail_data <- aus_retail %>%
  filter(`Series ID` == sample(aus_retail$`Series ID`,1))

head(retail_data, 10)%>% kable() %>% 
  kable_styling(bootstrap_options = "striped", font_size = 12,) %>% 
  scroll_box(height = "100%", width = "100%", fixed_thead = T)
State Industry Series ID Month Turnover
South Australia Other specialised food retailing A3349902A 1982 Apr 11.3
South Australia Other specialised food retailing A3349902A 1982 May 11.1
South Australia Other specialised food retailing A3349902A 1982 Jun 11.2
South Australia Other specialised food retailing A3349902A 1982 Jul 12.1
South Australia Other specialised food retailing A3349902A 1982 Aug 11.7
South Australia Other specialised food retailing A3349902A 1982 Sep 12.0
South Australia Other specialised food retailing A3349902A 1982 Oct 12.7
South Australia Other specialised food retailing A3349902A 1982 Nov 12.2
South Australia Other specialised food retailing A3349902A 1982 Dec 14.5
South Australia Other specialised food retailing A3349902A 1983 Jan 12.5
# Plot the original retail data to visualize the time series
retail_data %>%
  autoplot(Turnover) +
  labs(title = "Original Australian Retail Turnover", y = "Turnover", x = "Year and Month")

# Estimate the best lambda using the Guerrero method
lambda <- retail_data %>%
  features(Turnover, features = guerrero) %>%
  pull(lambda_guerrero)

# Apply the Box-Cox transformation to stabilize variance using the estimated lambda
retail_data %>%
  mutate(Turnover_BoxCox = box_cox(Turnover, lambda)) %>%
  autoplot(Turnover_BoxCox) +
  labs(title = paste0("Box-Cox Transformed Australian Retail Turnover (lambda = ", round(lambda, 2), ")"), 
       y = "Transformed Turnover", x = "Year and Month")

The Box-Cox transformation with lambda = -0.34 suggests that the turnover data has some variability that needs to be stabilized. The transformation stabilizes variance in the retail data. This helps reduce fluctuations and make the data easier to model and forecast.

EXercise 3.7.5

For the following series, find an appropriate Box-Cox transformation in order to stabilise the variance. Tobacco from aus_production, Economy class passengers between Melbourne and Sydney from ansett, and Pedestrian counts at Southern Cross Station from pedestrian.

Tobacco from aus_production

# Filter for Tobacco data from aus_production
tobacco_data <- aus_production %>%
  select(Tobacco)  %>%
  filter(!is.na(Tobacco))  # Remove missing values

# Plot original data
tobacco_data %>%
  autoplot(Tobacco) +
  labs(title = "Tobacco Production Over Time", 
       y = "Tobacco Production", x = "Year and Quarter")+
  scale_y_continuous(label = scales::comma)

# Estimate lambda using the Guerrero method
lambda_tobacco <- tobacco_data %>%
  features(Tobacco, features = guerrero) %>%
  pull(lambda_guerrero)

# Apply the Box-Cox transformation and plot transformed data
tobacco_data %>%
  mutate(Tobacco_BoxCox = box_cox(Tobacco, lambda_tobacco)) %>%
  autoplot(Tobacco_BoxCox) +
  labs(title = paste("Box-Cox Transformed Tobacco Production (Lambda =", round(lambda_tobacco, 2), ")"),
       y = "Transformed Tobacco Production", x = "Year and Quarter")+
  scale_y_continuous(label = scales::comma)

Economy class passengers between Melbourne and Sydney from ansett

# Filter for Economy class passengers between Melbourne and Sydney
ansett_data <- ansett %>%
  filter(Class == "Economy", Airports == "MEL-SYD") %>%
  select(Passengers) %>%
  filter(!is.na(Passengers))  # Remove missing values

ansett_data |>
  autoplot(Passengers)+
  labs(title = "Melbourne and Sydney Economy Passengers", y = "Passengers", x = "Year") +
  scale_y_continuous(label = scales::comma)

# Estimate lambda using the Guerrero method
lambda_ansett <- ansett_data %>%
  features(Passengers, features = guerrero) %>%
  pull(lambda_guerrero)

# Apply the Box-Cox transformation and plot transformed data
ansett_data %>%
  mutate(Passengers_BoxCox = box_cox(Passengers, lambda_ansett)) %>%
  autoplot(Passengers_BoxCox) +
  labs(title = paste("Box-Cox Transformed Melbourne and Sydney Economy Passengers (Lambda =", round(lambda_ansett, 2), ")"),
       y = "Transformed Passengers", x = "Year")+
  scale_y_continuous(labels = scales::label_number())

Pedestrian counts at Southern Cross Station

# Filter for pedestrian counts at Southern Cross Station and remove missing values
pedestrian_data <- pedestrian %>%
  filter(Sensor == "Southern Cross Station") %>%
  select(Count) %>%
  filter(!is.na(Count))  # Remove missing values

pedestrian_data |>
  autoplot(Count)+
  labs(title = "Pedestrian counts at Southern Cross Station", y = "Pedestrian", x = "Date") +
  scale_y_continuous(label = scales::comma)

# Estimate lambda using the Guerrero method
lambda_pedestrian <- pedestrian_data %>%
  features(Count, features = guerrero) %>%
  pull(lambda_guerrero)

# Apply the Box-Cox transformation and plot transformed data
pedestrian_data %>%
  mutate(Count_BoxCox = box_cox(Count, lambda_pedestrian)) %>%
  filter(!is.na(Count_BoxCox)) %>%  # Remove any resulting missing values
  autoplot(Count_BoxCox) +
  labs(title = paste("Box-Cox Transformed Pedestrian Counts at Southern Cross Station (Lambda =", round(lambda_pedestrian, 2), ")"),
       y = "Transformed Pedestrian Count", x = "Date")

EXercise 3.7.7

Consider the last five years of the Gas data from aus_production.

gas <- tail(aus_production, 5*4) |> select(Gas)
  1. Plot the time series. Can you identify seasonal fluctuations and/or a trend-cycle?
  2. Use classical_decomposition with type=multiplicative to calculate the trend-cycle and seasonal indices.
  3. Do the results support the graphical interpretation from part a?
  4. Compute and plot the seasonally adjusted data.
  5. Change one observation to be an outlier (e.g., add 300 to one observation), and recompute the seasonally adjusted data. What is the effect of the outlier?
  6. Does it make any difference if the outlier is near the end rather than in the middle of the time series?

Plot the time series. Can you identify seasonal fluctuations and/or a trend-cycle?

# Extract the last 5 years (20 quarters) of Gas data
gas <- aus_production %>%
  tail(5 * 4) %>%  # Extract the last 20 observations (5 years of quarterly data)
  select(Gas)

# Plot the time series for the last 5 years of Gas data
gas %>%
  autoplot(Gas) +
  labs(title = "Australian Gas Production For The Last 5 Years", 
       y = "Gas Production (Million Cubic Meters)", 
       x = "Year/Quarter")

gas  %>%
  gg_season(Gas) +
  labs(title = "Seasonal Decomposition of Australian Gas Production For The Last 5 Years", 
       y = "Gas Production (Million Cubic Meters)", 
       x = "Year/Quarter")

The plots above clearly depict a distinct seasonal pattern in gas production. Each year, there is a noticeable increase in production starting from the first quarter (Q1), reaching a peak by the middle of the year, typically around the second quarter (Q2). This is followed by a steady decline from the third quarter (Q3), continuing through the end of the year.

This recurring pattern suggests that gas production is strongly influenced by seasonal factors, where demand or operational capacity fluctuates within the year. For instance, production may rise during certain months due to increased energy demand or favorable production conditions, and then taper off as the demand subsides or operational constraints set in. The regularity of this cycle points to a predictable trend that can be useful for forecasting future production levels based on the time of year.

Use classical_decomposition with type=multiplicative to calculate the trend-cycle and seasonal indices.

# Apply classical decomposition with multiplicative type
decomposition <- gas %>%
  model(classical_decomposition(Gas, type = "multiplicative"))

# Extract and visualize the components
components <- decomposition %>%
  components() %>%
  filter(!is.na(trend))  # Remove rows with missing trend values

# Plot the components of the decomposition
autoplot(components) +
  labs(title = "Multiplicative Decomposition of Gas Production", 
       y = "Gas Production", 
       x = "Year")

Displlay the trend-cycle and seasonal indices

# Print out the trend-cycle and seasonal indices
components %>%
  select(trend, season_adjust) %>%
  head()
## # A tsibble: 6 x 3 [1Q]
##   trend season_adjust Quarter
##   <dbl>         <dbl>   <qtr>
## 1  200.          195. 2006 Q1
## 2  204.          209. 2006 Q2
## 3  207           207. 2006 Q3
## 4  210.          208. 2006 Q4
## 5  213           214. 2007 Q1
## 6  216.          218. 2007 Q2

Do the results support the graphical interpretation from part a?

The decomposition results support the graphical interpretation from part (a). It is eviddent that there is a clear seasonal pattern, where production increases in Q1 and Q2, and then decreases in Q3 and Q4. Additionally, the trend-cycle confirms a steady upward trend in gas production, which was also suggested by the initial plot.

Compute and plot the seasonally adjusted data.

components(decomposition) %>%
  as_tsibble() %>%
  autoplot(Gas, aes(colour = "Original Gas")) +  # Mapping colour inside aes()
  geom_line(aes(y = season_adjust, colour = "Seasonally Adjusted")) +  # Mapping seasonally adjusted colour
  geom_line(aes(y = trend, colour = "Trend"), linetype = "dashed") +  # Adding trend line with dashed style
  labs(title = "Gas Production: Original, Seasonally Adjusted, and Trend") +
  scale_colour_manual(values = c("Original Gas" = "blue", 
                                 "Seasonally Adjusted" = "green", 
                                 "Trend" = "red")) +  # Custom colors
  guides(colour = guide_legend(title = "Series"))  # Adding a legend
## Warning: Removed 4 rows containing missing values or values outside the scale range
## (`geom_line()`).

Change one observation to be an outlier (e.g., add 300 to one observation), and recompute the seasonally adjusted data.

gas$Gas[1] = gas$Gas[1] + 300


gas %>%
  model(classical_decomposition(Gas, type = "multiplicative")) %>%
  components() %>%
  as_tsibble() %>%
  autoplot(Gas, aes(colour = "Original Gas")) + 
  geom_line(aes(y = season_adjust, colour = "Seasonally Adjusted")) + 
  geom_line(aes(y = trend, colour = "Trend"), linetype = "dashed") +  
  labs(title = "Gas Production with an Outlier at the begining: Original, Seasonally Adjusted, and Trend") +
  scale_colour_manual(values = c("Original Gas" = "blue", 
                                 "Seasonally Adjusted" = "green", 
                                 "Trend" = "red")) +  # Custom colors
  guides(colour = guide_legend(title = "Series"))  # Adding a legend
## Warning: Removed 4 rows containing missing values or values outside the scale range
## (`geom_line()`).

# Select the last 20 observations and introduce an outlier in the middle
gas <- tail(aus_production, 20) %>% select(Gas)

# Find the middle index and introduce the outlier
middle_index <- round(nrow(gas) / 2)
gas$Gas[middle_index] <- gas$Gas[middle_index] + 300  # Add outlier to the middle observation

# Perform classical decomposition and plot with trend
gas %>%
  model(classical_decomposition(Gas, type = "multiplicative")) %>%
  components() %>%
  as_tsibble() %>%
  autoplot(Gas, aes(colour = "Original Gas")) + 
  geom_line(aes(y = season_adjust, colour = "Seasonally Adjusted")) + 
  geom_line(aes(y = trend, colour = "Trend"), linetype = "dashed") +  
  labs(title = "Gas Production with an Outlier in the Middle: Original, Seasonally Adjusted, and Trend") +
  scale_colour_manual(values = c("Original Gas" = "blue", 
                                 "Seasonally Adjusted" = "green", 
                                 "Trend" = "red")) + 
  guides(colour = guide_legend(title = "Series"))  # Adding a legend
## Warning: Removed 4 rows containing missing values or values outside the scale range
## (`geom_line()`).

# Select the last 20 observations and introduce an outlier at the end
gas <- tail(aus_production, 20) %>% select(Gas)
gas$Gas[20] <- gas$Gas[20] + 300  # Add outlier to the last observation

# Perform classical decomposition and plot with trend
gas %>%
  model(classical_decomposition(Gas, type = "multiplicative")) %>%
  components() %>%
  as_tsibble() %>%
  autoplot(Gas, aes(colour = "Original Gas")) + 
  geom_line(aes(y = season_adjust, colour = "Seasonally Adjusted")) + 
  geom_line(aes(y = trend, colour = "Trend"), linetype = "dashed") +  
  labs(title = "Gas Production with an Outlier at the End: Original, Seasonally Adjusted, and Trend") +
  scale_colour_manual(values = c("Original Gas" = "blue", 
                                 "Seasonally Adjusted" = "green", 
                                 "Trend" = "red")) + 
  guides(colour = guide_legend(title = "Series"))  # Adding a legend
## Warning: Removed 4 rows containing missing values or values outside the scale range
## (`geom_line()`).

What is the effect of the outlier?

The outlier causes an artificial spike or dip in the original data, which visually stands out compared to the surrounding observations.This shows that the effect of the outlier had an effect on the seasonal adjusted data.

Does it make any difference if the outlier is near the end rather than in the middle of the time series?

It makes a difference if the outlier is near the end rather than in the middle of the time series. This is because an outlier near the end of the time series will have a more localized effect, primarily impacting the final periods of the trend and seasonally adjusted data, while an outlier in the middle tends to have a broader, more pervasive effect on the trend and seasonal components across multiple periods. This can make identifying and correcting outliers easier when they occur near the end of the series compared to the middle.

EXercise 3.7.8

Recall your retail time series data (from Exercise 7 in Section 2.10). Decompose the series using X-11. Does it reveal any outliers, or unusual features that you had not noticed previously?

# Set a seed for reproducibility
set.seed(081282)

# Decompose the series using the X-11 method
decomposition_x11 <- retail_data %>%
  model(X_13ARIMA_SEATS(Turnover ~ x11()))

# Extract the components (trend, seasonal, remainder)
components_x11 <- decomposition_x11 %>%
  components()

# Plot the decomposed components to visualize
autoplot(components_x11) +
  labs(title = "X-11 Decomposition of Australian Retail Turnover", 
       y = "Turnover", 
       x = "Year and Month")

The X-11 decomposition reveals yearly seasonality in the data, offering greater detail than the original plots from Exercise 3.4. While some seasonal patterns were evident earlier, the X-11 decomposition highlights a gradual decline in the peaks of the seasonal variation. Additionally, the irregular component shows noticeable spikes, suggesting the presence of outliers. These outliers may be affecting the slightly increasing trend, an effect that would have been hard to detect in the original plots without the enhanced clarity provided by the X-11 decomposition.

EXercise 3.7.9

Figures 3.19 and 3.20 show the result of decomposing the number of persons in the civilian labour force in Australia each month from February 1978 to August 1995.

Civilian labour force in Australia Figure 3.19: Decomposition of the number of persons in the civilian labour force in Australia each month from February 1978 to August 1995.

Civilian labour force in Australia Figure 3.20: Seasonal component from the decomposition shown in the previous figure.

a. Write about 3–5 sentences describing the results of the decomposition. Pay particular attention to the scales of the graphs in making your interpretation.

Figures 3.19 and 3.20 depicts the decomposition of the Australian civilian labor force from February 1978 to August 1995. The decomposition reveals clear yearly seasonality, indicating long-term growth in the labor force. The seasonal component reflects regular yearly fluctuations, while the irregular component shows small, random variations with occasional spikes, possibly indicating outliers or unusual events. Overall, the decomposition highlights consistent seasonal patterns and a growing labor force over time.

b. Is the recession of 1991/1992 visible in the estimated components?

Yes, the recession of 1991/1992 is visible in the estimated components, particularly in the remainder component.