FPP3 discusses how adjusting data (calendar, population, inflation) and applying transformations (log/Box-Cox) can simplify patterns and improve modeling.
global_economy |>
filter(Country == "Australia") |>
autoplot(GDP / Population) +
labs(
title = "Australian GDP per capita",
y = "USD (GDP / Population)",
x = "Year"
)
We’ll use a quarterly production series (Gas) and show how to choose a Box-Cox lambda using the Guerrero method.
gas <- aus_production |>
filter_index("1956 Q1" ~ "2010 Q4") |>
select(Gas)
gas |>
autoplot(Gas) +
labs(title = "Australian Gas Production (Quarterly)", y = "Gas", x = "Quarter")
# Estimate lambda for Box-Cox using Guerrero method
lambda_tbl <- gas |>
features(Gas, guerrero)
lambda_tbl
## # A tibble: 1 × 1
## lambda_guerrero
## <dbl>
## 1 0.110
lambda <- lambda_tbl$lambda_guerrero
gas |>
mutate(Gas_boxcox = box_cox(Gas, lambda)) |>
autoplot(Gas_boxcox) +
labs(
title = paste0("Gas after Box-Cox Transformation (lambda = ", round(lambda, 3), ")"),
y = "Box-Cox(Gas)",
x = "Quarter"
)
A time series can be thought of as having: - Trend-cycle - Seasonality - Remainder
We’ll use the US retail employment example and decompose it with STL to visualize components.
us_retail_employment <- us_employment |>
filter(Title == "Retail Trade") |>
select(Month, Employed)
us_retail_employment |>
autoplot(Employed) +
labs(
title = "US Employment: Retail Trade",
y = "Employed (thousands)",
x = "Month"
)
fit_stl <- us_retail_employment |>
model(STL(Employed))
components(fit_stl) |>
autoplot() +
labs(title = "STL Decomposition: US Retail Employment")
Moving averages smooth a series to estimate the trend-cycle.
We’ll compute a centered moving average on a monthly series using
slider.
retail_short <- us_retail_employment |>
filter_index("2010 Jan" ~ "2020 Dec")
retail_short |>
autoplot(Employed) +
labs(title = "US Retail Employment (2010–2020)", y = "Employed (thousands)")
retail_ma <- retail_short |>
mutate(
MA13 = slide_dbl(Employed, mean, .before = 6, .after = 6, .complete = TRUE)
)
retail_ma |>
autoplot(Employed) +
geom_line(aes(y = MA13), linewidth = 1) +
labs(
title = "US Retail Employment with 13-term Centered Moving Average",
y = "Employed (thousands)",
x = "Month"
)
Classical decomposition estimates: - Trend-cycle via moving averages - Seasonal component from detrended series - Remainder as leftover noise
We’ll use classical_decomposition() from
feasts (included via fpp3).
classical_fit <- us_retail_employment |>
model(
classical_decomposition(Employed, type = "multiplicative")
)
components(classical_fit) |>
autoplot() +
labs(title = "Classical Decomposition (Multiplicative): US Retail Employment")
Fix for your error: when joining components back, we
only keep Month and season_adjust to avoid
creating Employed.x / Employed.y.
sa <- components(classical_fit) |>
as_tibble() |>
select(Month, season_adjust)
sa_ts <- us_retail_employment |>
left_join(sa, by = "Month")
sa_ts |>
autoplot(Employed) +
geom_line(aes(y = season_adjust), linewidth = 1) +
labs(
title = "Original vs Seasonally Adjusted (Classical Decomposition)",
y = "Employed (thousands)",
x = "Month"
)
sessionInfo()
## R version 4.5.2 (2025-10-31)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.3 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so; LAPACK version 3.12.0
##
## locale:
## [1] LC_CTYPE=C.UTF-8 LC_NUMERIC=C LC_TIME=C.UTF-8
## [4] LC_COLLATE=C.UTF-8 LC_MONETARY=C.UTF-8 LC_MESSAGES=C.UTF-8
## [7] LC_PAPER=C.UTF-8 LC_NAME=C LC_ADDRESS=C
## [10] LC_TELEPHONE=C LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C
##
## time zone: UTC
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] slider_0.3.3 fable_0.4.1 feasts_0.4.2 fabletools_0.5.1
## [5] tsibbledata_0.4.1 tsibble_1.1.6 ggplot2_4.0.1 lubridate_1.9.4
## [9] tidyr_1.3.2 dplyr_1.1.4 tibble_3.3.0 fpp3_1.0.2
##
## loaded via a namespace (and not attached):
## [1] rappdirs_0.3.3 sass_0.4.10 generics_0.1.4
## [4] anytime_0.3.12 digest_0.6.39 magrittr_2.0.4
## [7] evaluate_1.0.5 grid_4.5.2 timechange_0.3.0
## [10] RColorBrewer_1.1-3 fastmap_1.2.0 jsonlite_2.0.0
## [13] purrr_1.2.0 scales_1.4.0 jquerylib_0.1.4
## [16] cli_3.6.5 rlang_1.1.6 crayon_1.5.3
## [19] ellipsis_0.3.2 withr_3.0.2 cachem_1.1.0
## [22] yaml_2.3.12 tools_4.5.2 vctrs_0.6.5
## [25] R6_2.6.1 lifecycle_1.0.4 pkgconfig_2.0.3
## [28] warp_0.2.2 progressr_0.18.0 pillar_1.11.1
## [31] bslib_0.9.0 gtable_0.3.6 glue_1.8.0
## [34] Rcpp_1.1.0 xfun_0.55 tidyselect_1.2.1
## [37] rstudioapi_0.17.1 knitr_1.51 farver_2.1.2
## [40] htmltools_0.5.9 rmarkdown_2.30 labeling_0.4.3
## [43] compiler_4.5.2 S7_0.2.1 distributional_0.5.0