Package {stlpro}


Type: Package
Title: STL with Extended Capabilities
Version: 0.1.0
Description: Implements a Seasonal-Trend decomposition procedure based on LOESS (STL, developed by Cleveland, Cleveland, McRae, and Terpenning, 1990) in 'R' and 'C++'. The package supports missing values, fractional seasonal periods, multiplicative decompositions, and cross-validation based selection of the seasonal smoothing window.
License: GPL (≥ 3)
Encoding: UTF-8
Imports: Rcpp
LinkingTo: Rcpp
Suggests: knitr, rmarkdown, testthat (≥ 3.0.0)
Config/testthat/edition: 3
VignetteBuilder: knitr
Config/roxygen2/version: 8.1.1
NeedsCompilation: yes
Packaged: 2026-10-23 14:32:49 UTC; s3504do
Author: Daniel Ollech [aut, cre], Pavithra Purushothaman [ctb]
Maintainer: Daniel Ollech <daniel.ollech@bundesbank.de>
Repository: CRAN
Date/Publication: 2026-11-07 14:50:07 UTC

Calculate an error metric between two series

Description

Computes a scalar error metric between two numeric vectors, such as MAE, MSE, or RMSE.

Usage

calculate_error_metric(x, y, error_metric = "RMSE")

Arguments

x

Numeric vector of fitted or predicted values.

y

Numeric vector of observed values, same length as x.

error_metric

Character string specifying the error metric. One of "rmse", "mse", or "mae" (case-insensitive).

Details

The metrics are defined as:

Non-finite values are omitted from the calculation. If no finite paired observations remain, NA is returned.

Value

Numeric scalar, the value of the chosen error metric.

Author(s)

Daniel Ollech


Moving average over a non-integer number of observations

Description

Moving average over a non-integer number of observations

Usage

fractional_moving_average(x, p, reverse = FALSE)

Arguments

x

Numeric vector.

p

Numeric (>= 1). Span of the moving average in observations.

reverse

Logical. If TRUE, the observation with the fractional weight comes first instead of last.

Details

Averages floor(p) observations with weight 1 / p each and one further observation with weight (p - floor(p)) / p. For integer p this equals simple_moving_average.

Value

Numeric vector of length length(x) - ceiling(p) + 1.

Author(s)

Daniel Ollech


Impute missing values using local regression

Description

Replaces NA values in a series by local regression estimates based on neighboring observations.

Usage

impute_missing_localreg(y, window = 7, ideg = 0, userw = FALSE, rw = NULL)

Arguments

y

Numeric vector possibly containing NAs.

window

Integer. Window length used for the local regression around each missing value.

ideg

Integer (0 or 1). Degree of local polynomial (0 = local mean, 1 = local linear).

userw

Logical. If TRUE, robustness weights rw are used.

rw

Optional numeric vector of robustness weights, same length as y. If NULL, all weights are set to 1.

Details

For each missing value, a local regression is fitted using local_regression on the available neighbors within the specified window, and the missing value is replaced by the fitted value.

Value

Numeric vector of the same length as y, with missing values imputed.

Author(s)

Daniel Ollech

See Also

local_regression


Local regression at a single point

Description

Performs a local regression (degree 0 or 1) at a single target index using tricube weights and optional robustness weights.

Usage

local_regression(y, len, ideg, xs, nleft, nright, userw, rw)

Arguments

y

Numeric vector. Input time series.

len

Integer. Window length for the local regression.

ideg

Integer (0 or 1). Degree of local polynomial (0 = local mean, 1 = local linear).

xs

Integer. Target index at which the fit is evaluated (1-based).

nleft

Integer. Left bound of the window (1-based).

nright

Integer. Right bound of the window (1-based).

userw

Logical. If TRUE, robustness weights rw are used.

rw

Numeric vector of robustness weights, same length as y.

Details

The function constructs a local neighborhood around xs, computes tricube distance weights, optionally multiplies them by robustness weights, and then fits either a local mean or local linear model. Missing values in y are automatically excluded.

Value

A list with components:

ok

Logical. TRUE if a valid fit was obtained, FALSE otherwise.

ys

Numeric scalar. Fitted value at xs (or NA_real_ if ok = FALSE).

weights

Numeric vector of normalized weights used in the fit.

Author(s)

Daniel Ollech


Plot an STL decomposition fitted by stlpro Plot the reconstructed observed series and its seasonal, trend, and remainder components.

Description

Plot an STL decomposition fitted by stlpro

Plot the reconstructed observed series and its seasonal, trend, and remainder components.

Usage

## S3 method for class 'stlpro'
plot(
  x,
  plot_type = c("multiple", "single"),
  multiplicative = NULL,
  xlab = "",
  ylab = "data",
  main = NULL,
  labels = c("Unadjusted and adjusted series", "Seasonal component", "Trend component",
    "Remainder component"),
  col = c("#071108", "#D31B0D", "#d35e13", "#417246", "#2274A5"),
  lwd = 1,
  ...
)

Arguments

x

An object returned by stl().

plot_type

Either "multiple" for one panel per component or "single" for one plot containing all components.

multiplicative

Logical. Is the decomposition multiplicative? If NULL, the method looks for x$call$multiplicative. If this is not available, as in older stlpro objects, an additive decomposition is assumed.

xlab

Label for the x-axis.

ylab

Label for the y-axis of the observed-data panel.

main

Optional overall plot title.

labels

Optional character vector of length four giving labels for the observed, seasonal, trend, and remainder panels.

col

Colours used for the observed, seasonally adjusted, seasonal, trend, and remainder series, respectively.

lwd

Line width.

...

Further graphical parameters passed to graphics::plot().

Value

Invisibly returns x.


Print method for cross-validation results

Description

Pretty-prints an object of class "cv_results".

Usage

## S3 method for class 'cv_results'
print(x, ...)

Arguments

x

Object of class "cv_results" as returned by run_cross_validation.

...

Currently ignored.

Value

Invisibly returns the printed character string.

Author(s)

Daniel Ollech


Run cross-validation for the seasonal window

Description

Evaluates several candidate seasonal window lengths via cross-validation and selects the one that minimizes a chosen error metric.

Usage

run_cross_validation(
  work1,
  period,
  s_window_candidates,
  s_degree,
  s_jump,
  userw,
  rw,
  error_metric
)

Arguments

work1

Numeric vector. Trend-adjusted series (e.g., y - trend).

period

Numeric. Seasonal period (e.g., 12 for monthly data); may be non-integer.

s_window_candidates

Integer vector of candidate seasonal window lengths.

s_degree

Integer (0 or 1). Degree of local polynomial for the seasonal smoother.

s_jump

Integer. Jump (subsampling) parameter for the seasonal smoother.

userw

Logical. If TRUE, robustness weights rw are used.

rw

Numeric vector of robustness weights, same length as work1.

error_metric

Character string specifying the error metric. One of "rmse", "mse", or "mae" (case-insensitive).

Details

For each candidate window length, the function computes a seasonal component using stl_subseries_smoother_cv and evaluates the discrepancy between the seasonal component and work1 using calculate_error_metric. It will never approve s_window = 3, because this window size does not smooth the data, the weights in the local regression is (0,1,0), so no smoothing occurs. Technically s_window = 3 drops out, because for the comparison of the cross-validation errors only time points that could be removed and still be smoothed are considered.

Value

An object of class "cv_results", which is a list with components:

cv_choice

Integer. Selected seasonal window length.

error_metrics

Named numeric vector of error metric values for each candidate.

Author(s)

Daniel Ollech

See Also

stl_subseries_smoother_cv, calculate_error_metric, print.cv_results


Simple moving average

Description

Computes a simple moving average of a numeric vector with a fixed window length.

Usage

simple_moving_average(x, len)

Arguments

x

Numeric vector.

len

Integer. Window length for the moving average.

Details

The result has length length(x) - len + 1. If len is larger than length(x), an error is thrown.

Value

Numeric vector of moving average values.

Author(s)

Daniel Ollech


Single STL decomposition run with optional seasonal window cross-validation

Description

Performs one STL-like decomposition step given a current trend estimate, optionally choosing the seasonal window via cross-validation.

Usage

single_stl_run(
  y,
  trend,
  userw,
  rw,
  period,
  s_window,
  s_degree,
  s_jump,
  l_window,
  l_degree,
  l_jump,
  t_window,
  t_degree,
  t_jump,
  s_window_candidates,
  error_metric,
  first_round,
  multiplicative
)

Arguments

y

Numeric vector. Original time series.

trend

Numeric vector of the same length as y. Current trend estimate.

userw

Logical. If TRUE, robustness weights rw are used in the local regressions.

rw

Numeric vector of robustness weights, same length as y.

period

Numeric. Seasonal period (e.g., 12 for monthly data, 4 for quarterly). May be non-integer, e.g. 365.25 / 7 for weekly data.

s_window

Either an integer seasonal window length, "cv" to select the window by cross-validation, or NULL/missing to trigger cross-validation.

s_degree

Integer (0 or 1). Degree of local polynomial for seasonal smoothing.

s_jump

Integer. Jump (subsampling) parameter for seasonal smoothing.

l_window

Integer. Window length for the low-pass smoother applied to the preliminary seasonal component.

l_degree

Integer (0 or 1). Degree of local polynomial for the low-pass smoother.

l_jump

Integer. Jump (subsampling) parameter for the low-pass smoother.

t_window

Integer. Window length for the trend smoother.

t_degree

Integer (0 or 1). Degree of local polynomial for the trend smoother.

t_jump

Integer. Jump (subsampling) parameter for the trend smoother.

s_window_candidates

Integer vector of candidate seasonal window lengths to be evaluated when s_window is NULL or "cv".

error_metric

Character string specifying the error metric used in cross-validation. One of "rmse", "mse", or "mae" (case-insensitive).

first_round

Logical. If TRUE s_window=13 will be used

multiplicative

Logical. If TRUE a multiplicative adjustment will be employed, otherwise additive.

Details

The function:

  1. Computes a trend-adjusted series Y - T.

  2. Obtains a preliminary seasonal component via stl_subseries_smoother.

  3. Applies a low-pass filter and smoothing to obtain a smooth seasonal mean.

  4. Derives the seasonal component as the difference between the preliminary seasonal and the low-pass component.

  5. Computes the seasonally adjusted series Y - S.

  6. Re-estimates the trend via stl_full_smoother.

If s_window is NULL or "cv", the seasonal window is chosen by run_cross_validation using s_window_candidates.

Value

A list with components:

season

Numeric vector of seasonal component estimates.

trend

Numeric vector of trend estimates.

use_swindow

Integer. Seasonal window length actually used.

cv_results

Object of class "cv_results" with cross-validation results, or NULL if cross-validation was not used.

Author(s)

Daniel Ollech

See Also

stl_subseries_smoother, stl_full_smoother, run_cross_validation


Enhanced STL Decomposition

Description

Decompose a time series into seasonal, trend, and remainder components using STL, optionally with robust fitting. Compare to stats::stl it included cross-validation, multiplicative decompositions, allows non-integer seasonal periods and can handle missing values.

Usage

stl(
  y,
  period = NULL,
  multiplicative = FALSE,
  s_window = NULL,
  t_window = NULL,
  l_window = NULL,
  s_degree = 0,
  t_degree = 1,
  l_degree = 1,
  s_jump = NULL,
  t_jump = NULL,
  l_jump = NULL,
  inner = NULL,
  outer = 0,
  robust = NULL,
  s_window_candidates = c(7, 9, 13, 19, 37),
  error_metric = "RMSE"
)

Arguments

y

Numeric vector or time series.

period

Seasonal period, can be non-integer. If NULL and y is ts, uses frequency(y).

multiplicative

Logical. If TRUE a multiplicative decomposition is calculated, additive otherwise.

s_window

Seasonal window (odd integer >= 3). If NULL, is set using cross-validation.

t_window

Trend window (odd integer >= 3). If NULL, uses the default, namely nextodd(ceiling((1.5*period) / (1-(1.5/s_window)))).

l_window

Low-pass window (odd integer >= 3). If NULL, uses default.

s_degree

Degree of locally-fitted polynomial in seasonal smoothing (0 or 1).

t_degree

Degree of locally-fitted polynomial in trend smoothing (0 or 1).

l_degree

Degree of locally-fitted polynomial in low-pass smoothing (0 or 1).

s_jump

Seasonal jump (integer >= 1). If NULL, uses default.

t_jump

Trend jump (integer >= 1). If NULL, uses default.

l_jump

Low-pass jump (integer >= 1). If NULL, uses default.

inner

Number of inner iterations. If NULL, uses a default determined by outer: one inner iteration when outer > 0, otherwise two. Ignored when robust is not NULL.

outer

Number of outer robustifying iterations (default 0). Ignored when robust is not NULL.

robust

Logical scalar controlling the robustness iteration settings.

If TRUE, robust fitting is used with inner = 1 and outer = 15. If FALSE, non-robust fitting is used with inner = 2 and outer = 0. If NULL (the default), inner and outer are used as supplied.

s_window_candidates

Candidates for cross-validation based selection of s_window.

error_metric

Error metric used for cross-validation: "MAE", "MSE" or "RMSE".

Details

Values of period that are within 1e-8 of an integer are rounded to that integer. Values must be finite scalars greater than 1.

Value

A list with components: seasonal, trend, remainder, sa, weights, call, cv_results.

Author(s)

Daniel Ollech


Loess smoother over an entire series with optional skipping

Description

Applies a local regression smoother over a univariate series, optionally evaluating the smoother only at every njump-th point and linearly interpolating in between.

Usage

stl_full_smoother(y, len, ideg, njump, userw, rw)

Arguments

y

Numeric vector. Input time series.

len

Integer. Window length for the local regression.

ideg

Integer (0 or 1). Degree of local polynomial (0 = local mean, 1 = local linear).

njump

Integer. Jump (subsampling) parameter. If 1, the smoother is evaluated at every point; if greater than 1, only every njump-th point is smoothed and the rest are linearly interpolated.

userw

Logical. If TRUE, robustness weights rw are used.

rw

Numeric vector of robustness weights, same length as y.

Details

The function calls local_regression at selected indices and fills in skipped points by linear interpolation when njump > 1.

Value

Numeric vector of smoothed values, same length as y.

Author(s)

Daniel Ollech

See Also

local_regression


STL low-pass filter

Description

Applies a low-pass filter used in STL decomposition, consisting of two moving averages of length period followed by a moving average of length 3.

Usage

stl_lowpassfilter(x, period)

Arguments

x

Numeric vector. Input series.

period

Numeric. Seasonal period (e.g., 12 for monthly data); may be non-integer.

Details

The filter is:

  1. Moving average of length period.

  2. Moving average of length period of the result.

  3. Moving average of length 3 of the result.

For non-integer period, a moving average of length period averages ceiling(period) observations, the last one with the weight of the fractional part only (see fractional_moving_average). The second average is mirrored, so the combined filter stays centred. For integer period this is exactly the classic STL low-pass filter.

Value

Numeric vector of filtered values, of length length(x) - 2 * ceiling(period).

Author(s)

Daniel Ollech

See Also

simple_moving_average, fractional_moving_average


Check and normalize the seasonal period

Description

Periods within 1e-8 of an integer are treated as that integer, so that e.g. 12.000000001 takes the faster integer code paths.

Usage

stl_period(period)

Arguments

period

Numeric scalar, the seasonal period (> 1).

Value

period, rounded if it is numerically an integer.

Author(s)

Daniel Ollech


Compute robustness weights for STL

Description

Computes robustness weights based on residuals between the observed series and a fitted component, following the robust STL scheme.

Usage

stl_robustness_weights(y, fit)

Arguments

y

Numeric vector. Observed series.

fit

Numeric vector. Fitted values (e.g., trend + seasonal).

Details

The weights are based on the absolute residuals |y - fit| and a scaled median absolute deviation. Observations with small residuals get weight 1, and those with large residuals are down-weighted smoothly.

Value

Numeric vector of robustness weights in [0, 1], same length as y.

Author(s)

Daniel Ollech


Seasonal subseries smoother

Description

Smooths every cycle-subseries with loess and extrapolates n_ext values at both ends. The period may be non-integer (e.g. 365.25 / 7 for weekly data): then the subseries through each time point t consists of the values at t + k * period, interpolated linearly where they fall between two observations, and the smooth is evaluated at t.

Usage

stl_subseries_smoother(
  y,
  period,
  ns,
  isdeg,
  nsjump,
  userw,
  rw,
  n_ext = NULL,
  loo = FALSE
)

Arguments

y

Numeric vector. Input time series.

period

Numeric. Seasonal period (e.g., 12 for monthly data); may be non-integer.

ns

Integer. Window length for the local regression within each subseries.

isdeg

Integer (0 or 1). Degree of local polynomial for the subseries smoother.

nsjump

Integer. Jump (subsampling) parameter for the subseries smoother.

userw

Logical. If TRUE, robustness weights rw are used.

rw

Numeric vector of robustness weights, same length as y.

n_ext

Integer number of extension values at each end. Defaults to ceiling(period).

loo

Logical. If TRUE, each fitted value leaves out its own observation (leave-one-out, for cross-validation of ns).

Details

For integer period, the function extracts for each seasonal position j = 1, ..., period the subseries y[j], y[j + period], ..., smooths it with loess and extrapolates one value at both ends.

For non-integer period (and for loo = TRUE or n_ext != period), every time point t gets its own subseries t + k * period; positions between two observations are interpolated linearly. For integer period both ways give the same result.

Value

Numeric vector of length length(y) + 2 * n_ext containing the smoothed seasonal component with extra values at both ends; element m belongs to time point m - n_ext.

Author(s)

Daniel Ollech

See Also

stl_full_smoother, local_regression


Seasonal subseries smoother for cross-validation

Description

Variant of stl_subseries_smoother used for cross-validation, returning a seasonal component of the same length as the input series.

Usage

stl_subseries_smoother_cv(y, period, ns, isdeg, nsjump, userw, rw)

Arguments

y

Numeric vector. Input time series.

period

Numeric. Seasonal period (e.g., 12 for monthly data); may be non-integer.

ns

Integer. Window length for the local regression within each subseries.

isdeg

Integer (0 or 1). Degree of local polynomial for the subseries smoother.

nsjump

Integer. Jump (subsampling) parameter for the subseries smoother.

userw

Logical. If TRUE, robustness weights rw are used.

rw

Numeric vector of robustness weights, same length as y.

Details

Each fitted value is obtained by leaving out its own observation (leave-one-out). With nsjump > 1, values between the fitted points are interpolated linearly, as in stl_full_smoother. If a leave-one-out fit fails (no other observation with positive weight in the window), the observation itself is returned.

Value

Numeric vector of length length(y) containing the smoothed seasonal component.

Author(s)

Daniel Ollech

See Also

stl_subseries_smoother