STL
This function applies STL (Seasonal-Trend decomposition using LOESS) to a univariate time series and returns observed, trend, seasonal, and residual components.
STL models a series as:
y_t = T_t + S_t + R_t
where T_t is a smooth trend, S_t is a seasonal component with known period, and R_t is the remainder. The robust option can reduce the influence of outliers.
Excel Usage
=STL(data, period, seasonal, robust)
data(list[list], required): 2D range of time-series values (numeric).period(int, required): Seasonal period in samples (positive integer).seasonal(int, optional, default: 7): Length of seasonal smoother (odd integer).robust(bool, optional, default: false): Use robust fitting to reduce outlier influence.
Returns (list[list]): 2D array with columns [observed, trend, seasonal, residual].
Example 1: STL decomposition of seasonal series
Inputs:
| data | period | seasonal | robust | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 10 | 12 | 14 | 12 | 11 | 13 | 15 | 13 | 12 | 14 | 16 | 14 | 13 | 15 | 17 | 15 | 4 | 7 | false |
Excel formula:
=STL({10,12,14,12,11,13,15,13,12,14,16,14,13,15,17,15}, 4, 7, FALSE)
Expected output:
| Result | |||
|---|---|---|---|
| 10 | 11.625 | -1.625 | 0 |
| 12 | 11.875 | 0.125 | 1.77636e-15 |
| 14 | 12.125 | 1.875 | 0 |
| 12 | 12.375 | -0.375 | 1.77636e-15 |
| 11 | 12.625 | -1.625 | 0 |
| 13 | 12.875 | 0.125 | -1.77636e-15 |
| 15 | 13.125 | 1.875 | 1.77636e-15 |
| 13 | 13.375 | -0.375 | 1.77636e-15 |
| 12 | 13.625 | -1.625 | 1.77636e-15 |
| 14 | 13.875 | 0.125 | 3.55271e-15 |
| 16 | 14.125 | 1.875 | -5.32907e-15 |
| 14 | 14.375 | -0.375 | 0 |
| 13 | 14.625 | -1.625 | 7.10543e-15 |
| 15 | 14.875 | 0.125 | 3.55271e-15 |
| 17 | 15.125 | 1.875 | 8.88178e-15 |
| 15 | 15.375 | -0.375 | 7.10543e-15 |
Example 2: Robust STL decomposition
Inputs:
| data | period | seasonal | robust | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 10 | 12 | 14 | 12 | 11 | 13 | 15 | 13 | 12 | 14 | 16 | 14 | 13 | 15 | 17 | 15 | 4 | 7 | true |
Excel formula:
=STL({10,12,14,12,11,13,15,13,12,14,16,14,13,15,17,15}, 4, 7, TRUE)
Expected output:
| Result | |||
|---|---|---|---|
| 10 | 11.625 | -1.625 | -7.10543e-15 |
| 12 | 11.875 | 0.125 | 0 |
| 14 | 12.125 | 1.875 | 0 |
| 12 | 12.375 | -0.375 | 1.77636e-15 |
| 11 | 12.625 | -1.625 | 3.55271e-15 |
| 13 | 12.875 | 0.125 | 1.77636e-15 |
| 15 | 13.125 | 1.875 | 0 |
| 13 | 13.375 | -0.375 | -5.32907e-15 |
| 12 | 13.625 | -1.625 | 8.88178e-15 |
| 14 | 13.875 | 0.125 | 1.77636e-15 |
| 16 | 14.125 | 1.875 | -1.77636e-15 |
| 14 | 14.375 | -0.375 | -1.77636e-15 |
| 13 | 14.625 | -1.625 | -1.06581e-14 |
| 15 | 14.875 | 0.125 | -1.95399e-14 |
| 17 | 15.125 | 1.875 | 4.44089e-14 |
| 15 | 15.375 | -0.375 | -8.34888e-14 |
Example 3: STL with single-column range input
Inputs:
| data | period | seasonal | robust |
|---|---|---|---|
| 10 | 4 | 7 | false |
| 12 | |||
| 14 | |||
| 12 | |||
| 11 | |||
| 13 | |||
| 15 | |||
| 13 | |||
| 12 | |||
| 14 | |||
| 16 | |||
| 14 | |||
| 13 | |||
| 15 | |||
| 17 | |||
| 15 |
Excel formula:
=STL({10;12;14;12;11;13;15;13;12;14;16;14;13;15;17;15}, 4, 7, FALSE)
Expected output:
| Result | |||
|---|---|---|---|
| 10 | 11.625 | -1.625 | 0 |
| 12 | 11.875 | 0.125 | 1.77636e-15 |
| 14 | 12.125 | 1.875 | 0 |
| 12 | 12.375 | -0.375 | 1.77636e-15 |
| 11 | 12.625 | -1.625 | 0 |
| 13 | 12.875 | 0.125 | -1.77636e-15 |
| 15 | 13.125 | 1.875 | 1.77636e-15 |
| 13 | 13.375 | -0.375 | 1.77636e-15 |
| 12 | 13.625 | -1.625 | 1.77636e-15 |
| 14 | 13.875 | 0.125 | 3.55271e-15 |
| 16 | 14.125 | 1.875 | -5.32907e-15 |
| 14 | 14.375 | -0.375 | 0 |
| 13 | 14.625 | -1.625 | 7.10543e-15 |
| 15 | 14.875 | 0.125 | 3.55271e-15 |
| 17 | 15.125 | 1.875 | 8.88178e-15 |
| 15 | 15.375 | -0.375 | 7.10543e-15 |
Example 4: STL with longer period and data length
Inputs:
| data | period | seasonal | robust | |||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 20 | 21 | 23 | 25 | 24 | 22 | 21 | 22 | 24 | 26 | 25 | 23 | 22 | 23 | 25 | 27 | 26 | 24 | 23 | 24 | 26 | 28 | 27 | 25 | 6 | 7 | false |
Excel formula:
=STL({20,21,23,25,24,22,21,22,24,26,25,23,22,23,25,27,26,24,23,24,26,28,27,25}, 6, 7, FALSE)
Expected output:
| Result | |||
|---|---|---|---|
| 20 | 22.0833 | -2.08333 | 0 |
| 21 | 22.25 | -1.25 | 7.10543e-15 |
| 23 | 22.4167 | 0.583333 | 3.55271e-15 |
| 25 | 22.5833 | 2.41667 | 3.55271e-15 |
| 24 | 22.75 | 1.25 | 3.55271e-15 |
| 22 | 22.9167 | -0.916667 | -3.55271e-15 |
| 21 | 23.0833 | -2.08333 | 3.55271e-15 |
| 22 | 23.25 | -1.25 | -7.10543e-15 |
| 24 | 23.4167 | 0.583333 | -3.55271e-15 |
| 26 | 23.5833 | 2.41667 | -3.55271e-15 |
| 25 | 23.75 | 1.25 | -3.55271e-15 |
| 23 | 23.9167 | -0.916667 | 3.55271e-15 |
| 22 | 24.0833 | -2.08333 | -3.55271e-15 |
| 23 | 24.25 | -1.25 | 0 |
| 25 | 24.4167 | 0.583333 | 3.55271e-15 |
| 27 | 24.5833 | 2.41667 | 3.55271e-15 |
| 26 | 24.75 | 1.25 | -7.10543e-15 |
| 24 | 24.9167 | -0.916667 | 3.55271e-15 |
| 23 | 25.0833 | -2.08333 | -3.55271e-15 |
| 24 | 25.25 | -1.25 | 0 |
| 26 | 25.4167 | 0.583333 | -1.06581e-14 |
| 28 | 25.5833 | 2.41667 | -1.06581e-14 |
| 27 | 25.75 | 1.25 | -3.55271e-15 |
| 25 | 25.9167 | -0.916667 | -1.06581e-14 |
Python Code
import numpy as np
from statsmodels.tsa.seasonal import STL as sm_STL
def stl(data, period, seasonal=7, robust=False):
"""
Perform STL decomposition of a univariate time series.
See: https://www.statsmodels.org/stable/generated/statsmodels.tsa.seasonal.STL.html
This example function is provided as-is without any representation of accuracy.
Args:
data (list[list]): 2D range of time-series values (numeric).
period (int): Seasonal period in samples (positive integer).
seasonal (int, optional): Length of seasonal smoother (odd integer). Default is 7.
robust (bool, optional): Use robust fitting to reduce outlier influence. Default is False.
Returns:
list[list]: 2D array with columns [observed, trend, seasonal, residual].
"""
try:
def to2d(x):
return [[x]] if not isinstance(x, list) else x
data = to2d(data)
if not isinstance(period, int) or period < 2:
return "Error: period must be an integer greater than or equal to 2"
if not isinstance(seasonal, int) or seasonal < 3 or seasonal % 2 == 0:
return "Error: seasonal must be an odd integer greater than or equal to 3"
if not isinstance(data, list) or not all(isinstance(row, list) for row in data):
return "Error: data must be a 2D list"
values = []
for row in data:
for item in row:
try:
values.append(float(item))
except (TypeError, ValueError):
continue
if len(values) < 2 * period:
return "Error: data must contain at least two complete seasonal cycles"
result = sm_STL(values, period=period, seasonal=seasonal, robust=robust).fit()
observed = np.asarray(values)
trend = np.asarray(result.trend)
seasonal_comp = np.asarray(result.seasonal)
resid = np.asarray(result.resid)
output = []
for i in range(len(observed)):
row = []
for arr in (observed, trend, seasonal_comp, resid):
val = arr[i]
row.append(float(val) if np.isfinite(val) else "")
output.append(row)
return output
except Exception as e:
return f"Error: {str(e)}"Online Calculator
2D range of time-series values (numeric).
Seasonal period in samples (positive integer).
Length of seasonal smoother (odd integer).
Use robust fitting to reduce outlier influence.