seasight provides R tools for seasonal adjustment diagnostics, model comparison and reproducible HTML reporting. It builds on seasonal and X-13ARIMA-SEATS, with workflows aimed at official statistics, macroeconomic monitoring and production review.
seasight is designed for teams that need more than a one-off adjustment:
transparent diagnostics, comparable candidates, readable reports, and a
workflow that survives handover across analysts and over time.
Status: seasight is in a pre-submission stabilization phase. The 0.1.x
series focuses on a stable core workflow, stronger tests, and review-ready
documentation.
seasight
seasight complements rather than replaces
seasonal.
seasonal when you want direct manual control of a specific X-13 spec.seasight when you want a reviewable workflow around those specs:
screening for apparent seasonality, generating candidate models, ranking
them with explicit diagnostics, and producing a report that colleagues can
inspect without reading the source code first.This is especially useful in official statistics and macroeconomic production workflows, where revisions, analyst turnover, and repeated model review all matter.

The package supports a six-step workflow:
seasonal::seas() code.The aim is not full automation without judgment. It is a human-in-the-loop review workflow with explicit rules and outputs that are easy to audit, communicate, and revisit later.
sa_tests_model(),
sa_existence_call(), and sa_is_do_not_adjust().auto_seasonal_analysis().sa_should_switch(), sa_compare(), and sa_top_candidates_table().sa_report_html().build_user_xreg() and td_candidates.remotes::install_github("p-wegmueller/seasight")
library(seasight)
library(seasonal)
y <- AirPassengers
res <- auto_seasonal_analysis(y, max_specs = 3)
res$best
head(res$table)
res$seasonality$overall
out <- sa_report_html(
y = y,
max_specs = 3,
outfile = tempfile("sa_airpassengers-", fileext = ".html")
)
out$report
library(seasight)
library(seasonal)
y <- AirPassengers
current_model <- seas(
y,
x11 = "",
arima.model = c(0, 1, 1, 0, 1, 1),
transform.function = "log"
)
res <- auto_seasonal_analysis(
y = y,
current_model = current_model,
engine = "auto",
max_specs = 3
)
sa_should_switch(res)
sa_report_html(
y = y,
current_model = current_model,
max_specs = 3,
outfile = tempfile("sa_airpassengers_with_baseline-", fileext = ".html")
)
For an ARIMA-only attribution check, set comparison_mode = "incumbent_fixed". This requires current_model and holds its selected
transformation, calendar terms, fixed outliers and stored user regressors
constant while candidate ARIMA specifications (and the requested engine) are
refitted. Coefficients remain free. The candidate table records
comparison_mode, regression_variables and outlier_variables.
auto_seasonal_analysis() may fit several X-13 models: default specifications,
optional seasonal::fivebestmdl() specifications, no-trading-day and
trading-day candidates, and in engine = "auto" mode both SEATS and X-11
attempts. Use max_specs for quick exploratory runs and increase the grid only
when you need a broader review.
Model ranking combines residual seasonality on the adjusted series (QS_p),
Ljung-Box residual diagnostics, AICc, revision metrics for the top candidates,
distance from any incumbent model, and an engine-preference penalty. The
switching helper sa_should_switch() then compares the selected candidate with
the incumbent. A change requires a material improvement in comparable AICc,
acceptable absolute diagnostics, no material deterioration in QS or
Ljung-Box p-values, and compliance with distance and seasonal-correlation
safeguards. Identical adjustments are kept. Missing or non-comparable evidence
is reported as "REVIEW_REQUIRED"; without an incumbent the result is
"NO_BASELINE".
sa_report_html() writes an HTML file. In examples, use tempfile() or an
explicit review-output path so report generation does not unexpectedly create
files in your project root.
seasight was designed for settings where seasonal adjustment decisions need
to be documented and explained, not just computed. The report output is meant
to support internal review, communication with subject-matter experts, and
reproducible handover across analysts.
td_candidates should be a named list of ts or ts-boxable regressors aligned to y. seasight does not ship broad holiday calendars; production calendar data should come from an authoritative source for the country, sector and series being adjusted. The example below is artificial but copy-pasteable.
library(seasight)
y <- AirPassengers
month_length <- rep(c(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31), length.out = length(y))
td_len <- ts(month_length - mean(month_length), start = start(y), frequency = frequency(y))
td_candidates <- list(length_of_month = td_len)
res_td <- auto_seasonal_analysis(
y = y,
td_candidates = td_candidates,
td_usertype = "td",
include_easter = "auto",
engine = "auto"
)
res_td$table[1, c(
"model_label", "with_td", "td_name", "with_easter", "easter_window",
"td_p", "score_100"
)]
With include_easter = "auto", X-13 tests whether Easter improves the model
and selects among its supported Easter windows. Use "always" to impose
easter[easter_len], or "off" to disable both inclusion and testing. The
candidate table records the effect actually retained in with_easter and
easter_window.
For moving-holiday pulses, use build_user_xreg():
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_holiday <- build_user_xreg(
y = y,
holidays = list(diwali = list(dates = diwali_dates, start = -1, end = 1)),
td_usertype = "holiday"
)
library(seasight)
library(seasonal)
y <- AirPassengers
m <- seas(y)
diag_tbl <- sa_tests_model(m)
diag_tbl
sa_existence_call(diag_tbl)
extract_outliers(m)
sa_copyable_call(m, x_expr = "AirPassengers")
vignettes/seasight-getting-started.Rmd
vignettes/seasight-advanced.Rmd
vignettes/seasight-sa-practice.Rmd
vignettes/seasight-seats-absent.Rmd
If you use seasight in research, policy work, or production documentation,
please cite the package metadata:
citation("seasight")
Feedback from practitioners is welcome, especially from statistical offices, central banks, finance ministries and researchers working with real-time macroeconomic data and revisions. Please open issues for bugs, diagnostics gaps or report improvements.
Development setup, testing expectations and review-readiness notes are described
in CONTRIBUTING.md. Normal local tests do not require
tokens or external services; a GitHub token is only useful for checks that query
GitHub metadata, such as pkgcheck.
All participants are expected to follow the project Code of Conduct.
This package is released under the MIT License. See LICENSE.