Skip to content

msdecompose

Ivan Svetunkov edited this page Jun 16, 2026 · 5 revisions

msdecompose - Multiple Seasonal Decomposition

msdecompose performs classical seasonal decomposition for time series with multiple seasonal patterns. It extends the standard decomposition method to handle multiple seasonal periods simultaneously.

This function is used internally by ADAM and ES for initializing ETS models, but can also be used standalone for decomposition and forecasting.

Function signatures

R

msdecompose(y, lags = c(12),
            type = c("additive", "multiplicative"),
            smoother = c("lowess", "ma", "supsmu", "global"), ...)

Python

def msdecompose(
    y,
    lags: list[int] = [12],
    type: Literal["additive", "multiplicative"] = "additive",
    smoother: Literal["lowess", "ma", "global"] = "lowess",
) -> dict: ...

smoother="supsmu" (Friedman's SuperSmoother) is R-only — see Roadmap. The R↔Python shared C++ olsCore backend behind smoother="global" produces byte-identical output across languages.

Overview

The function separates a time series into:

  • Trend: Long-term movement (captured via smoothing)
  • Seasonal components: One for each seasonal period specified in lags
  • Residuals: Residual after removing trend and seasonals

This is particularly useful for:

  • Hourly data with daily (24) and weekly (168) patterns
  • Daily data with weekly (7) and annual (365) patterns
  • Monthly data with yearly (12) patterns
  • Any time series with multiple overlapping seasonal cycles

Mathematical Form

For additive decomposition:

yₜ = Trendₜ + Σᵢ Seasonalᵢ(t) + εₜ

For multiplicative decomposition:

yₜ = Trendₜ × ∏ᵢ Seasonalᵢ(t) × εₜ

Algorithm

  1. Log Transform (if multiplicative): Apply log to convert to additive form
  2. Missing Value Imputation: Fill NA values using polynomial + Fourier regression
  3. Iterative Smoothing: For each lag period (sorted ascending):
    • Apply smoother with window = lag period
    • Extract seasonal pattern as residual from the smoother level
    • Center patterns by removing seasonal mean
  4. Trend Extraction: Final smoothed series becomes the trend
  5. Initial States: Compute level and slope from trend for model initialization

R Usage

library(smooth)

# Basic decomposition with yearly seasonality
result <- msdecompose(AirPassengers, lags=12, type="multiplicative")

# Multiple seasonality (daily and weekly patterns in hourly data)
result <- msdecompose(y, lags=c(24, 168), type="additive")

# Using different smoothers
msdecompose(y, lags=12, type="additive", smoother="ma")      # Moving average
msdecompose(y, lags=12, type="additive", smoother="lowess")  # LOWESS (STL-like)
msdecompose(y, lags=12, type="additive", smoother="supsmu")  # Super smoother
msdecompose(y, lags=12, type="additive", smoother="global")  # Global linear trend

# Plot decomposition
plot(result)

# Forecast using decomposition
resultForecast <- forecast(result, model="AAN", h=12)
plot(resultForecast)

Python Usage

from smooth import msdecompose
import numpy as np

# Basic decomposition with LOWESS as a smoother
result = msdecompose(y, lags=[12], type='additive', smoother='lowess')

# Access components
trend = result['trend']
seasonal = result['seasonal'][0]  # First seasonal pattern
level = result['initial']['nonseasonal']['level']
slope = result['initial']['nonseasonal']['trend']

# Multiple seasonality (hourly data with daily and weekly patterns)
result = msdecompose(hourly_data, lags=[24, 168], type='additive')
daily_pattern = result['seasonal'][0]   # 24-hour pattern
weekly_pattern = result['seasonal'][1]  # 168-hour pattern

# Multiplicative decomposition (requires positive data)
result = msdecompose(sales_data, lags=[12], type='multiplicative')

# Use for ADAM initialization
result = msdecompose(y, lags=[12], type='additive')
initial_level = result['initial']['nonseasonal']['level']
initial_trend = result['initial']['nonseasonal']['trend']
initial_seasonal = result['initial']['seasonal'][0]

Parameters

Parameter Type (R) Type (Python) Default Description
y vector/ts array-like - Time series data (can contain NaN)
lags numeric vector list/array 12 / [12] Seasonal periods to extract
type character str "additive" Decomposition type
smoother character str "lowess" Smoothing method
... - - - Additional parameters for smoothers (R only)

Decomposition Types

  • "additive": Components are summed. Use for stable seasonality amplitude.
  • "multiplicative": Components are multiplied. Use for proportional seasonality (requires y > 0).

Smoother Types

Smoother Description
"ma" Centred moving average. Fast, classical decomposition.
"lowess" Locally weighted scatterplot smoothing. Robust to outliers, similar to STL. Default in R and Python.
"supsmu" Friedman's super smoother. More sensitive than LOWESS.
"global" Global linear regression. Fits a straight line for trend, uses ma for seasonality smoothing.

Python LOWESS: the "lowess" (and "supsmu") smoothing is provided by the greybox package (>= 1.0.2), via greybox.lowess / greybox.smoothers.supsmu. smooth no longer ships its own LOWESS implementation; greybox is installed automatically as a dependency. Import it directly with from greybox import lowess if you need the smoother on its own.

Lag Examples

Data Frequency Lags Description
Monthly [12] Month of year seasonality
Daily [7] Day of week seasonality
Daily [7, 365] Day of week and year
Hourly [24] Hour of day seasonality
Hourly [24, 168] Hour of day and week (168 = 24×7)
Half-hourly [48, 336] Half-hour of day (48) and week (336 = 48×7)

Output

Returns an object of class "msdecompose" (R) or a dictionary (Python) containing:

Element Type (R) Type (Python) Description
y vector/ts numpy.ndarray Original time series
states matrix numpy.ndarray State matrix (T × n_states) with level, trend, and seasonal columns
initial list dict Named list/dict with nonseasonal (level, trend) and seasonal components
seasonal list list List of seasonal patterns, one per lag
fitted vector numpy.ndarray Fitted values from decomposition
lags numeric vector numpy.ndarray Lags used in decomposition
type character str Decomposition type used
yName character str Name of the input data
smoother character str Smoother type used

Accessing Initial Values

# R
result <- msdecompose(y, lags=12)
result$initial$nonseasonal["level"]   # Initial level
result$initial$nonseasonal["trend"]   # Initial trend (slope)
result$initial$seasonal[[1]]          # First lag[1] seasonal values
# Python
result = msdecompose(y, lags=[12])
result['initial']['nonseasonal']['level']   # Initial level
result['initial']['nonseasonal']['trend']   # Initial trend (slope)
result['initial']['seasonal'][0]            # First 12 seasonal values

Forecasting (R)

The R implementation supports forecasting by fitting an ETS model to the deseasonalised trend:

result <- msdecompose(AirPassengers, lags=12, type="m")

# Forecast with automatic ETS model selection
forecast(result, h=24)

# Specify ETS model for trend
forecast(result, model="AAN", h=24)

# Automaric ETS with prediction intervals
forecast(result, h=24, interval="parametric", level=0.95)

The forecast adds back the seasonal patterns to the ETS forecast of the deseasonalised series.

Use in ADAM/ES Initialization

The primary use of msdecompose is to provide initial values for ETS. The decomposition provides:

  • Initial level state
  • Initial trend state (slope)
  • Initial seasonal states for each lag

Comparison to Other Methods

Method Multiple Seasons Smoothers Forecasting
msdecompose Yes MA, LOWESS, SupSmu, Global Yes (R)
stats::decompose No MA No
stats::stl No LOWESS with additional steps Via forecast package
mstl (forecast) Yes LOWESS with additional steps Yes

Missing Values

Missing values (NaN) are automatically imputed using polynomial + Fourier regression before decomposition:

ŷₜ = Σₖ βₖtᵏ + Σⱼ αⱼsin(πtj/m)

where the polynomial degree is min(max(⌊T/10⌋, 1), 5) and m is the maximum lag.

References

See Also

  • ADAM - Uses msdecompose for initialization
  • ES - Uses msdecompose for initialization
  • Home - Package overview

Clone this wiki locally