
Getting started with seasight
Source:vignettes/seasight-getting-started.Rmd
seasight-getting-started.Rmdseasight provides tools to see seasonal
adjustment more clearly. It wraps the seasonal
interface to X-13ARIMA-SEATS with:
- summary diagnostics,
- automatic model selection, and
- reproducible HTML reports.
The main target audience are applied economists and official statisticians who need stable, well-documented seasonal adjustment workflows, e.g. in National Accounts or short-term indicators.
The design follows the recommendations in Eurostat’s ESS Guidelines on Seasonal Adjustment and the Handbook on Seasonal Adjustment.(European Commission)
How this package differs from alternatives
seasight is designed to complement the core seasonal
API.
- Keep using
seasonal::seas()when you need direct hand-crafted X-13 calls. - Use
seasightwhen you need a standardized and auditable workflow around those calls (candidate grids, diagnostics, ranking, and reporting artifacts).
In other words, seasight focuses on decision
support and reproducibility in institutional workflows, while
the decomposition engine remains X-13 via seasonal.
Setup
We assume that X-13ARIMA-SEATS is available via the
seasonal package (see ?seasonal::seas for
installation details).
A first seasonal adjustment with seasonal
In production you typically start from a manually maintained X-13 specification. Here we use the very simple default call:
m_current is a regular seasonal::seas
object. seasight does not replace
seasonal – it sits on top and helps you:
- assess the quality of a given model,
- explore alternative specifications, and
- document the decision in a consistent way.
Low-level diagnostics: sa_tests_model()
The basic diagnostic building block is sa_tests_model().
It computes a set of standard tests for a single
seas model:
tests_current <- sa_tests_model(m_current)
tests_currentFor the 0.1.x pre-submission cycle, the core user-facing outputs are frozen; typical fields include:
- Residual seasonality (QS on SA) X-11/SEATS QS statistics on the seasonally adjusted series.
- Seasonality in the original series (QSori) QS statistics on the unadjusted series.
- M7 X-11 M-statistics for residual seasonality (M7 is the main one used by Eurostat).(European Commission)
- IDS The “identifiable seasonality” indicator used in Eurostat practice.
- Residual autocorrelation (Ljung–Box) A basic check that the ARIMA model is absorbing the dynamics.
- Volatility reduction How much the standard deviation of growth rates falls when moving from raw to seasonally adjusted data.
- Seasonal amplitude Size of the seasonal component relative to the series level.
These metrics are the raw ingredients for the higher-level decisions discussed below.
Automatic model search: auto_seasonal_analysis()
auto_seasonal_analysis() searches over a grid of
candidate X-13 specs and ranks them according to a composite score:
res <- auto_seasonal_analysis(
y = x,
use_fivebest = TRUE,
include_easter = "auto",
td_usertype = "td",
engine = "auto" # let seasight choose between SEATS / X-11
)
names(res)The most important components are:
res$bestThe bestseasmodel (a regularseasonal::seasobject).-
res$tableA tibble with one row per candidate, including:head(res$table)Typical columns include:
-
model_label– a short identifier, - ARIMA structure (
ARIMA_disp/arima/spec_id), -
with_td,td_p– trading-day regressor and its p-value, -
QS_p_x11,QS_p_seats,QS_p– QS on SA, -
QSori_p_x11,QSori_p_seats,QSori_p– QS on original, -
LB_p– Ljung–Box p-value, -
seasonal_amp_pct– seasonal amplitude (% of level), -
vola_reduction_pct– volatility reduction (%), -
dist_sa_L1– L1 distance vs. the current SA (if supplied), -
rev_mae– mean absolute revision (if history info is available), -
score– the composite score used for ranking.
-
res$seasonalityA nested list with an “existence-of-seasonality” decision for the original series, based on QS, IDS and M7 (see Eurostat guidelines).(European Commission)
Calendar regressors (trading days & moving holidays)
seasight can compare models without
regressors against models with user-supplied calendar
regressors via td_candidates.
A key design choice: the package does not ship country-specific calendars. Instead you can build generic regressors yourself and pass them in.
# Example: build a Diwali "pulse" regressor (quarterly here, for illustration)
diwali_dates <- as.Date(c(
"2018-11-07","2019-10-27","2020-11-14","2021-11-04",
"2022-10-24","2023-11-12","2024-11-01"
))
td <- build_user_xreg(
y = x,
holidays = list(diwali = list(dates = diwali_dates, start = -1, end = 1)),
td_usertype = "holiday"
)
res_td <- auto_seasonal_analysis(x, td_candidates = td, engine = "auto")For more realistic workflows (multiple TD candidates, baselines, and decision rules), see the SA practice and Advanced vignettes.
Inspecting the winning model
The winning model is in res$best:
best <- res$best
summary(best)You can use it like any other seas object:
If you prefer to keep everything explicit, you can access the
underlying specification as R code using sa_copyable_call()
(also shown in the HTML report, see below):
sa_copyable_call(best, x_expr = "AirPassengers")Visual “cards”: sa_existence_card() and
sa_engine_choice_card()
In interactive HTML outputs (e.g. pkgdown site, Quarto, Shiny) it is often helpful to summarise key decisions in compact “cards”.
seasight exposes two such cards:
# Existence-of-seasonality card
sa_existence_card(res)
# Engine choice card (SEATS vs X-11)
sa_engine_choice_card(res)- The existence card explains whether the series should be adjusted, combining QS, M7 and IDS into a single “robust” call.
- The engine card provides a transparent rationale for choosing SEATS vs X-11 based on their diagnostics and stability.
From analysis to decision: sa_should_switch()
If you provide a current (baseline) model,
seasight can suggest whether you should
keep it or switch to the new best
candidate.
res_with_baseline <- auto_seasonal_analysis(
y = x,
current_model = m_current
)
sa_should_switch(res_with_baseline)The decision rule takes into account:
- whether the new model passes basic diagnostics (QS / Ljung–Box),
- whether the new seasonal pattern is materially different from the current one (L1 distance, correlation of seasonal factors),
- and whether the new model improves the composite score.
You can always override this decision – the goal is to provide a transparent, reproducible default that is broadly aligned with Eurostat practice (e.g. avoid switching for tiny cosmetic improvements).(European Commission)
A full HTML report in one call: sa_report_html()
For documentation, review meetings or method reports you often want a self-contained HTML document:
tmp_file <- tempfile(fileext = ".html")
sa_report_html(
y = x,
current_model = m_current,
title = "AirPassengers – seasight demo",
outfile = tmp_file
)
tmp_file
# Browse to this file in your file manager or with browseURL(tmp_file)The report includes:
- an executive summary (existence of seasonality, best model, decision),
- narrative cards explaining why the model was chosen,
- comparison plots vs. the current model (levels and growth),
- diagnostics (QS, M7, IDS, Ljung–Box, seasonal amplitude, volatility reduction),
- outlier listings for current and new model,
- copy-pasteable
seas()calls for both specifications, and - a “Top candidates” table with the highest-ranked alternatives.
Where to go next
For a deeper dive into:
- using baselines (current production models),
- passing custom trading-day candidates, and
- understanding the built-in decision rules,
see the companion vignette:
“Advanced usage: baselines, TD candidates & decision rules”
which uses the same AirPassengers series but goes
further into methodological details.