Python implementation of BASTION (Bayesian Adaptive Seasonality and Trend Decomposition Incorporating Outliers and Noise).
BASTION is a flexible Bayesian framework for decomposing time series into trend and multiple seasonality components. It offers three key advantages over existing decomposition methods:
- Locally adaptive estimation of trend and seasonality for enhanced accuracy
- Explicit modeling of outliers and time-varying volatility for greater robustness
- Rigorous uncertainty quantification through credible intervals
This package is a Python translation of the R package BASTION by Jason B. Cho and David S. Matteson.
pip install pybastionFor development:
git clone https://github.com/danielandresarcones/pybastion.git
cd pybastion
pip install -e ".[dev]"For large time series, install scikit-sparse to enable sparse Cholesky factorization (requires SuiteSparse system library):
pip install "pybastion[fast]"from pybastion import fit_BASTION
from pybastion.datasets import load_airtraffic
# Load example dataset
df = load_airtraffic()
y = df["Int_Pax"].values
# Decompose with weekly (7-day) seasonality
result = fit_BASTION(y, Ks=[7], Outlier=True, seed=42)
# Access results
summary = result["summary"]
trend = summary["Trend_sum"] # Mean, CR_lower, CR_upper
seasonal = summary["Seasonal7_sum"] # Seasonal component for period 7from pybastion import fit_BASTION
from pybastion.datasets import load_NYelectricity
df = load_NYelectricity()
y = df.iloc[:, 1].values
# Weekly (7) and yearly (365) seasonal periods
result = fit_BASTION(y, Ks=[7, 365], Outlier=True, seed=42)
summary = result["summary"]
print(summary["Trend_sum"].head())
print(summary["Seasonal7_sum"].head())
print(summary["Seasonal365_sum"].head())result = fit_BASTION(y, Ks=[7], obsSV="SV", seed=42)
volatility = result["summary"]["Volatility"]import numpy as np
X = np.column_stack([covariate1, covariate2]) # (T, p) matrix
result = fit_BASTION(y, Ks=[7], X=X, seed=42)Decompose a time series using BASTION.
| Parameter | Type | Default | Description |
|---|---|---|---|
y |
array-like (T,) | required | Time series observations |
Ks |
list of int | required | Seasonal periods |
X |
array-like (T, p) or None | None |
Regression covariate matrix |
Outlier |
bool | False |
Whether to model outliers |
cl |
float | 0.95 |
Credible level for intervals |
sparse |
bool | False |
Extra shrinkage on trend |
obsSV |
str | "const" |
Observation error model: "const" or "SV" |
nchains |
int | 2 |
Number of MCMC chains |
nsave |
int | 1000 |
Iterations to save per chain |
nburn |
int | 1000 |
Burn-in iterations |
nskip |
int | 4 |
Thinning interval |
verbose |
bool | True |
Show progress bar |
save_samples |
bool | False |
Return full posterior samples |
seed |
int or None | None |
Random seed for reproducibility |
Returns: A dict with key "summary" (and "samples" if save_samples=True).
The summary dict contains:
p_means— DataFrame with posterior means of y and all componentsTrend_sum— DataFrame withMean,CR_lower,CR_upperSeasonalK_sum— DataFrame for each seasonal period KOutlier_sum— DataFrame (ifOutlier=True)Volatility— DataFrame withMean,CR_lower,CR_upper
from pybastion.datasets import load_airtraffic, load_NYelectricity
df_air = load_airtraffic() # 249 × 3 DataFrame
df_elec = load_NYelectricity() # 3288 × 2 DataFrame- Python ≥ 3.10
- NumPy ≥ 1.22
- SciPy ≥ 1.8
- pandas ≥ 1.4
- tqdm ≥ 4.0
If you use pyBASTION in your research, please cite the original paper:
@article{cho2025bastion,
title={BASTION: Bayesian Adaptive Seasonality and Trend Decomposition Incorporating Outliers and Noise},
author={Cho, Jason B. and Matteson, David S.},
year={2025},
eprint={2601.18052},
archivePrefix={arXiv},
primaryClass={stat.ME}
}MIT