The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
library(fasster)
#> Loading required package: fabletools
#> Registered S3 method overwritten by 'tsibble':
#> method from
#> as_tibble.grouped_df dplyrFASSTER (Forecasting with Additive Switching of Seasonality, Trend and Exogenous Regressors) is a state space model designed for forecasting time series with complex multiple seasonality patterns. The model addresses common limitations in existing approaches by providing:
FASSTER is particularly useful for time series with:
Common applications include:
FASSTER uses a formula-based interface similar to R’s
lm():
Use poly() to specify polynomial trends:
poly(1) - constant levelpoly(2) - linear trendpoly(n) - polynomial of order nTwo types of seasonality are available:
season(period) - seasonal factorsfourier(period, harmonics) - Fourier termsFor example: - season("year") - annual seasonal factors
- fourier("day") - daily seasonality with Fourier terms -
fourier("day", K = 6) - daily Fourier seasonality with 6
harmonics
Include autoregressive and moving average terms:
ARMA(p, q) - ARMA model with p AR terms and q MA
termsInclude external variables using standard formula notation:
x1 + x2 - add regressorslog(x1) - transformationsThe key innovation in FASSTER is the switching operator
%S%, which allows different model components for different
categories:
This creates separate states for each level of group.
For example:
Switching can be nested for more complex patterns:
Let’s demonstrate FASSTER using quarterly gas production data.
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
library(lubridate)
#>
#> Attaching package: 'lubridate'
#> The following objects are masked from 'package:base':
#>
#> date, intersect, setdiff, union
# Use Australian gas production data
gas_data <- tsibbledata::aus_production |>
select(Quarter, Gas) |>
filter(!is.na(Gas))
# Split into training and test sets
train <- gas_data |> filter(year(Quarter) < 2008)
test <- gas_data |> filter(year(Quarter) >= 2008)A simple model with switching trend to capture the structural break that occurred around 1970:
# Fit model with pre/post 1970 trends
fit <- train |>
model(
fasster = FASSTER(log(Gas) ~ (year(Quarter) < 1970) %S% trend(2) + fourier("year"))
)
fit
#> # A mable: 1 x 1
#> fasster
#> <model>
#> 1 <FASSTER>The model includes:
log(Gas) - a log transformation to regularise the
data’s variationtrend(2) - separate level and trend switched before and
after 1970fourier("year") - annual seasonal pattern with Fourier
termsFASSTER provides model-based decomposition of the time series components:
components(fit)
#> # A dable: 208 x 6 [1Q]
#> # Key: .model [1]
#> # : log(Gas) = `(year(Quarter) < 1970)_TRUE/trend(2)` + `(year(Quarter)
#> # < 1970)_FALSE/trend(2)` + `fourier("year")`
#> .model Quarter `log(Gas)` (year(Quarter) < 1970)_TR…¹ (year(Quarter) < 197…²
#> <chr> <qtr> <dbl> <dbl> <dbl>
#> 1 fasster 1956 Q1 1.61 1.75 -4.43
#> 2 fasster 1956 Q2 1.79 1.78 -4.31
#> 3 fasster 1956 Q3 1.95 1.68 -4.19
#> 4 fasster 1956 Q4 1.79 1.77 -4.24
#> 5 fasster 1957 Q1 1.61 1.86 -4.43
#> 6 fasster 1957 Q2 1.95 1.79 -3.34
#> 7 fasster 1957 Q3 1.95 1.88 -3.22
#> 8 fasster 1957 Q4 1.79 1.85 -3.23
#> 9 fasster 1958 Q1 1.61 1.84 -3.15
#> 10 fasster 1958 Q2 1.95 1.82 -2.81
#> # ℹ 198 more rows
#> # ℹ abbreviated names: ¹`(year(Quarter) < 1970)_TRUE/trend(2)`,
#> # ²`(year(Quarter) < 1970)_FALSE/trend(2)`
#> # ℹ 1 more variable: `fourier("year")` <dbl>
# Plot decomposition
components(fit) |>
autoplot()The decomposition reveals: - Original data and fitted values - Level components (separate for pre/post 1970) - Seasonal components
Notice how the pre-1970 level remains flat after 1970, while the post-1970 level takes over, highlighting the structural break.
Generate forecasts using the fitted model:
The forecasts: - Use the post-1970 pattern for future predictions - Include uncertainty intervals that grow over time - Capture both trend and seasonal patterns learned from the data
FASSTER handles missing values naturally during estimation. The Kalman filter simply skips updating states when data is missing:
# Model works even with missing values
data_with_na <- gas_data |>
# Insert some missing values randomly
mutate(Gas = if_else(row_number() %in% sample(n(), 10), NA_real_, Gas))
fit_na <- data_with_na |>
model(FASSTER(Gas ~ (year(Quarter) < 1970) %S% trend(2) + fourier("year", K = 2)))
# Interpolate missing values
fit_na |>
interpolate(data_with_na)
#> # A tsibble: 218 x 2 [1Q]
#> Quarter Gas
#> <qtr> <dbl>
#> 1 1956 Q1 5
#> 2 1956 Q2 6
#> 3 1956 Q3 7
#> 4 1956 Q4 6
#> 5 1957 Q1 5
#> 6 1957 Q2 7
#> 7 1957 Q3 7
#> 8 1957 Q4 6
#> 9 1958 Q1 5
#> 10 1958 Q2 7
#> # ℹ 208 more rowsCreate complex models with nested switching:
Mix grouped and ungrouped components:
FASSTER uses a heuristic approach for fast parameter estimation:
This “filterSmooth” approach: - Requires only two passes through the data - Works well with non-saturating Fourier terms - Provides reasonable estimates without maximum likelihood
For very long series, estimation can be sped up by using only recent data:
FASSTER provides a flexible framework for modeling complex time series with:
The concise formula interface makes it easy to specify models suitable for high-frequency data with complex seasonal patterns.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.