Exercise 3.1

Consider the GDP information in global_economy. Plot the GDP per capita for each country over time. Which country has the highest GDP per capita? How has this changed over time?

global_economy |>
  mutate(GDP_per_capita = GDP / Population) |>
  ggplot(aes(x = Year, y = GDP_per_capita, group = Country)) +
  geom_line(alpha = 0.5) +
  scale_y_log10() +
  labs(
    title = "GDP per Capita by Country",
    x = "Year",
    y = "GDP per Capita (log scale)"
  )

highest_gdp_per_capita <- global_economy |>
  mutate(GDP_per_capita = GDP / Population) |>
  as_tibble() |>
  group_by(Year) |>
  slice_max(GDP_per_capita, n = 1, with_ties = FALSE) |>
  select(Year, Country, GDP_per_capita)

highest_gdp_per_capita |>
  group_by(Country) |>
  summarise(
    First_year = min(Year),
    Last_year = max(Year),
    Years_highest = n(),
    .groups = "drop"
  ) |>
  arrange(First_year)
## # A tibble: 6 × 4
##   Country              First_year Last_year Years_highest
##   <fct>                     <dbl>     <dbl>         <int>
## 1 United States              1960      1969             8
## 2 Kuwait                     1965      1966             2
## 3 Monaco                     1970      2016            43
## 4 United Arab Emirates       1976      1977             2
## 5 Liechtenstein              2013      2015             2
## 6 Luxembourg                 2017      2017             1

GDP per capita generally increased over time, although the rates of growth differed across countries. The country with the highest GDP per capita also changed over time. The United States was highest during eight early years, while Kuwait was highest in 1965 and 1966. Monaco was the most frequent leader, recording the highest GDP per capita in 43 years between 1970 and 2016, although the United Arab Emirates and Liechtenstein led during some years within that period. Luxembourg had the highest GDP per capita in 2017.

Exercise 3.2

For each series, make a graph of the data. If transforming seems appropriate, apply a transformation and describe its effect.

United States GDP

us_gdp <- global_economy |>
  filter(Country == "United States")

us_gdp |>
  autoplot(GDP) +
  labs(
    title = "United States GDP",
    x = "Year",
    y = "GDP"
  )

us_gdp |>
  autoplot(log(GDP)) +
  labs(
    title = "Log-Transformed United States GDP",
    x = "Year",
    y = "log(GDP)"
  )

The original series has a strong upward trend, and its changes become larger as the level of GDP increases. The logarithmic transformation compresses the larger values, stabilizes the variation, and makes the long-term growth pattern more nearly linear.

Victorian Bulls, Bullocks and Steers

victorian_bulls <- aus_livestock |>
  filter(
    State == "Victoria",
    Animal == "Bulls, bullocks and steers"
  )

victorian_bulls |>
  autoplot(Count) +
  labs(
    title = "Slaughter of Bulls, Bullocks and Steers in Victoria",
    x = "Year",
    y = "Number slaughtered"
  )

lambda_bulls <- victorian_bulls |>
  features(Count, features = guerrero) |>
  pull(lambda_guerrero)

lambda_bulls
## [1] -0.04461887
victorian_bulls |>
  autoplot(box_cox(Count, lambda_bulls)) +
  labs(
    title = "Box-Cox Transformed Victorian Livestock Slaughter",
    subtitle = paste("Lambda =", round(lambda_bulls, 2)),
    x = "Year",
    y = "Transformed count"
  )

The original livestock series contains strong fluctuations, with larger variation occurring when the number slaughtered is higher. The Guerrero method selected a Box-Cox parameter of -0.04. The transformation reduces the influence of the largest peaks and makes the variation more stable over time.

Victorian Electricity Demand

vic_elec |>
  autoplot(Demand) +
  labs(
    title = "Victorian Electricity Demand",
    x = "Time",
    y = "Demand (MW)"
  )

Electricity demand shows strong repeating seasonal patterns and several large demand peaks. However, the overall level and spread remain reasonably stable across the observed period. Therefore, a transformation is not essential for this series, and keeping the data on its original megawatt scale makes the graph easier to interpret.

Australian Gas Production

aus_production |>
  autoplot(Gas) +
  labs(
    title = "Australian Quarterly Gas Production",
    x = "Year",
    y = "Gas production"
  )

lambda_gas <- aus_production |>
  features(Gas, features = guerrero) |>
  pull(lambda_guerrero)

lambda_gas
## [1] 0.1095171
aus_production |>
  autoplot(box_cox(Gas, lambda_gas)) +
  labs(
    title = "Box-Cox Transformed Australian Gas Production",
    subtitle = paste("Lambda =", round(lambda_gas, 2)),
    x = "Year",
    y = "Transformed gas production"
  )

The original gas production series has a strong upward trend, and the size of its seasonal fluctuations increases as production rises. The Guerrero method selected a Box-Cox parameter of 0.11. The transformation reduces the increasing variation and makes the seasonal fluctuations more consistent across time.

Exercise 3.3

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

canadian_gas |>
  autoplot(Volume) +
  labs(
    title = "Monthly Canadian Gas Production",
    x = "Year",
    y = "Gas production (billions of cubic metres)"
  )

A Box-Cox transformation is unhelpful for the Canadian gas data because the changing variation is not caused only by changes in the level of the series. The size and shape of the seasonal pattern change over time. A Box-Cox transformation rescales all observations using one fixed parameter, so it cannot correct an evolving seasonal pattern. A decomposition method that permits seasonality to change over time, such as STL, is more appropriate.

Exercise 3.4

What Box-Cox transformation would you select for your retail data?

set.seed(624)

myseries <- aus_retail |>
  filter(`Series ID` == sample(aus_retail$`Series ID`, 1))

myseries |>
  distinct(State, Industry, `Series ID`)
## # A tibble: 1 × 3
##   State           Industry               `Series ID`
##   <chr>           <chr>                  <chr>      
## 1 New South Wales Takeaway food services A3349792X
lambda_retail <- myseries |>
  features(Turnover, features = guerrero) |>
  pull(lambda_guerrero)

lambda_retail
## [1] 0.002144737
myseries |>
  autoplot(Turnover) +
  labs(
    title = "New South Wales Takeaway Food Services",
    x = "Year",
    y = "Turnover"
  )

myseries |>
  autoplot(box_cox(Turnover, lambda_retail)) +
  labs(
    title = "Box-Cox Transformed Retail Turnover",
    subtitle = paste("Lambda =", round(lambda_retail, 2)),
    x = "Year",
    y = "Transformed turnover"
  )

The Guerrero method selected a Box-Cox parameter of 0. Because lambda is approximately zero, the appropriate transformation is the natural logarithm of turnover. The log transformation reduces the increasing seasonal variation and makes the size of the fluctuations more consistent across time.

Exercise 3.5

Find an appropriate Box-Cox transformation for each series in order to stabilize its variance.

Tobacco from aus_production

lambda_tobacco <- aus_production |>
  features(Tobacco, features = guerrero) |>
  pull(lambda_guerrero)

lambda_tobacco
## [1] 0.9264636
aus_production |>
  autoplot(Tobacco) +
  labs(
    title = "Australian Tobacco Production",
    x = "Year",
    y = "Tobacco production"
  )

aus_production |>
  autoplot(box_cox(Tobacco, lambda_tobacco)) +
  labs(
    title = "Box-Cox Transformed Tobacco Production",
    subtitle = paste("Lambda =", round(lambda_tobacco, 2)),
    x = "Year",
    y = "Transformed tobacco production"
  )

The Guerrero method selected a Box-Cox parameter of 0.93. Because this value is close to 1, the transformed series is very similar to the original series. Therefore, little or no transformation is required to stabilize the variance of Tobacco production.

Melbourne-Sydney Economy Passengers

melsyd_economy <- ansett |>
  filter(Airports == "MEL-SYD", Class == "Economy") |>
  mutate(Passengers = Passengers / 1000)

lambda_ansett <- melsyd_economy |>
  features(Passengers, features = guerrero) |>
  pull(lambda_guerrero)

lambda_ansett
## [1] 1.999927
melsyd_economy |>
  autoplot(Passengers) +
  labs(
    title = "Ansett Airlines Economy Class",
    subtitle = "Melbourne-Sydney",
    x = "Week",
    y = "Passengers ('000)"
  )

melsyd_economy |>
  autoplot(box_cox(Passengers, lambda_ansett)) +
  labs(
    title = "Box-Cox Transformed Ansett Passengers",
    subtitle = paste("Lambda =", round(lambda_ansett, 2)),
    x = "Week",
    y = "Transformed passengers"
  )

The Guerrero method selected a Box-Cox parameter of 2. A value near 2 corresponds to a square-type transformation. This transformation expands the higher passenger values relative to the lower values and helps stabilize the variation. The observations with zero passengers remain unusual because they resulted from the 1989 industrial dispute.

Pedestrian Counts at Southern Cross Station

southern_cross <- pedestrian |>
  filter(Sensor == "Southern Cross Station")

lambda_pedestrian <- southern_cross |>
  features(Count, features = guerrero) |>
  pull(lambda_guerrero)

lambda_pedestrian
## [1] -0.2501616
southern_cross |>
  autoplot(Count) +
  labs(
    title = "Pedestrian Counts at Southern Cross Station",
    x = "Time",
    y = "Pedestrian count"
  )

southern_cross |>
  autoplot(box_cox(Count, lambda_pedestrian)) +
  labs(
    title = "Box-Cox Transformed Pedestrian Counts",
    subtitle = paste("Lambda =", round(lambda_pedestrian, 2)),
    x = "Time",
    y = "Transformed pedestrian count"
  )

The Guerrero method selected a Box-Cox parameter of -0.25. The negative lambda applies an inverse-power transformation that strongly compresses the largest pedestrian counts. This reduces the increasing variation associated with busy periods and makes the spread more stable over time.

Exercise 3.7

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

gas <- tail(aus_production, 5 * 4) |>
  select(Gas)

gas |>
  autoplot(Gas) +
  labs(
    title = "Australian Gas Production: Last Five Years",
    x = "Year",
    y = "Gas production"
  )

The series shows clear quarterly seasonal fluctuations, with a similar pattern of peaks and troughs repeating each year. The overall level generally increases across the five-year period, indicating an upward trend-cycle in addition to the seasonality.

Multiplicative Classical Decomposition

gas_decomposition <- gas |>
  model(
    classical_decomposition(Gas, type = "multiplicative")
  )

gas_components <- components(gas_decomposition)

gas_components |>
  autoplot() +
  labs(
    title = "Multiplicative Classical Decomposition of Gas Production"
  )

The decomposition supports the original graphical interpretation. The trend component generally rises over the five-year period, confirming an upward trend-cycle. The seasonal component shows a stable quarterly pattern that repeats each year. The remainder contains the irregular variation that is not explained by the trend-cycle or seasonal components.

Seasonally Adjusted Gas Production

gas_components |>
  as_tsibble() |>
  autoplot(season_adjust) +
  labs(
    title = "Seasonally Adjusted Australian Gas Production",
    x = "Year",
    y = "Seasonally adjusted gas production"
  )

Effect of an Outlier in the Middle

gas_middle_outlier <- gas |>
  mutate(
    Gas = if_else(row_number() == 10, Gas + 300, Gas)
  )

middle_outlier_components <- gas_middle_outlier |>
  model(
    classical_decomposition(Gas, type = "multiplicative")
  ) |>
  components()

middle_outlier_components |>
  as_tsibble() |>
  autoplot(season_adjust) +
  labs(
    title = "Seasonally Adjusted Gas Production with a Middle Outlier",
    x = "Year",
    y = "Seasonally adjusted gas production"
  )

Adding 300 to an observation in the middle creates a large spike in the seasonally adjusted series. The outlier also influences the estimated trend-cycle and seasonal indices, so its effect is spread to nearby observations rather than remaining completely isolated. This shows that classical decomposition is sensitive to unusual observations.

Effect of an Outlier Near the End

gas_end_outlier <- gas |>
  mutate(
    Gas = if_else(row_number() == 19, Gas + 300, Gas)
  )

end_outlier_components <- gas_end_outlier |>
  model(
    classical_decomposition(Gas, type = "multiplicative")
  ) |>
  components()

end_outlier_components |>
  as_tsibble() |>
  autoplot(season_adjust) +
  labs(
    title = "Seasonally Adjusted Gas Production with an End Outlier",
    x = "Year",
    y = "Seasonally adjusted gas production"
  )

The outlier near the end still creates a large spike in the seasonally adjusted series. However, its effect differs from the middle outlier because classical decomposition uses centered moving averages and cannot estimate the trend-cycle reliably at the endpoints. Therefore, the influence of the end outlier is less evenly distributed across surrounding observations, and decomposition estimates near the boundary are less reliable.

Exercise 3.8

Recall the retail time series selected in Exercise 3.4. Decompose the series using X-11. Does it reveal any outliers or unusual features that were not noticed previously?

retail_x11 <- myseries |>
  model(
    x11 = X_13ARIMA_SEATS(Turnover ~ x11())
  ) |>
  components()

retail_x11 |>
  autoplot() +
  labs(
    title = "X-11 Decomposition of New South Wales Takeaway Food Services"
  )

retail_x11 |>
  as_tsibble() |>
  as_tibble() |>
  mutate(irregular_distance = abs(irregular - 1)) |>
  arrange(desc(irregular_distance)) |>
  select(Month, Turnover, irregular) |>
  slice_head(n = 8)
## # A tibble: 8 × 3
##      Month Turnover irregular
##      <mth>    <dbl>     <dbl>
## 1 1993 Mar    122.      0.893
## 2 2002 Jan    229.      1.09 
## 3 1983 Dec     89.6     0.914
## 4 1990 Sep    135.      0.914
## 5 1983 Oct     80.1     0.917
## 6 1999 Nov    165.      1.07 
## 7 1986 Dec    136.      1.07 
## 8 2003 Mar    202.      0.930

The X-11 decomposition separates the long-term trend, seasonal pattern, and irregular movements in retail turnover. The trend generally increases over time, while the seasonal component shows a recurring monthly pattern. The irregular component reveals several isolated observations with unusually large movements that are not explained by the trend or seasonality. These observations are possible outliers that were less obvious in the original time plot.

Exercise 3.9

Figures 3.19 and 3.20 show the decomposition of the number of persons in the Australian civilian labour force from February 1978 to August 1995.

Figure 3.19: STL decomposition of the Australian civilian labour force.
Figure 3.19: STL decomposition of the Australian civilian labour force.
Figure 3.20: Seasonal component of the decomposition.
Figure 3.20: Seasonal component of the decomposition.

Description of the decomposition

The trend component shows that the civilian labour force generally increased from approximately 6,400 thousand people in 1978 to approximately 9,000 thousand in 1995. The seasonal component is comparatively small, generally ranging from about -100 to 110 thousand, so seasonal movements are only a small proportion of the total labour force. The seasonal pattern also changes over time, particularly for March, August, November, and December. Most remainder values are relatively close to zero, although several exceptionally large negative values appear around 1991–1992.

Recession of 1991–1992

Yes, the 1991–1992 recession is visible in the estimated components. The trend-cycle temporarily becomes flatter during this period, indicating slower labour-force growth. The recession is especially noticeable in the remainder component, which contains unusually large negative values around 1991 and 1992.