STL, SSA, Wavelets, EMD, or VMD? Choosing Python Decomposition Tools
Source review: 29 October 2026.
Choose a decomposition method by the structure you want to estimate, the observations available when you will use it, and the outputs your next step requires. A package name alone answers none of those questions.
For one known seasonal period, STL is a useful starting point. For several known periods, consider MSTL. For an explicitly chosen scale representation, inspect wavelets. For data-adaptive oscillatory components, compare EMD-family methods or VMD. For a low-rank trajectory representation, examine SSA. These are conditional starting points, based on the APIs and assumptions described below; performance on a particular application still requires measurement.
This maintainer-written guide compares official documentation and the DeTime source. It reports software capabilities and practical evaluation choices. The existing comparison evidence separately identifies which package versions and timings were actually checked. Reading a current documentation page does not establish that every feature works in an older installed release.
1. A map of the Python ecosystem
The table describes the selected decomposition interfaces, rather than every feature of each project. The linked documentation is the evidence for each row.
| Tool | Useful starting point | Main output | Choice to make explicitly |
|---|---|---|---|
| statsmodels STL | A series with one seasonal period | Trend, seasonal component, residual | Period, smoothing spans, robust weighting |
| statsmodels MSTL | Several seasonal periods in one series | Trend, multiple seasonal components, residual | Periods, seasonal windows, optional Box–Cox transform |
| PyWavelets | Wavelet scale analysis and reconstruction | Approximation/detail coefficients | Wavelet, level, signal extension mode |
| PyEMD / EMD-signal | EMD, EEMD and CEEMDAN | Intrinsic mode functions and method-specific residual information | Sifting settings; noise and ensemble settings when applicable |
| emd | EMD with spectral and cycle analysis | IMFs plus separate phase, frequency, amplitude and cycle-analysis outputs | Sift variant and analysis conventions |
| pyts SSA | Decomposing a collection of univariate series | Per-series reconstructed groups | Embedding window and component grouping |
| SSALib | Detailed exploration of one series using SSA | SSA objects, grouped reconstructions and diagnostics | Matrix construction, SVD solver and grouping |
| sktime VmdTransformer | VMD within a time-series estimator workflow | Modes or spectra | Mode count, bandwidth parameter, initialization and tolerance |
| PySDKit | Exploring multiple signal-decomposition families | Method-specific modes/results through fit_transform interfaces |
Method, input layout and reconstruction convention |
| DeTime | Comparing families while retaining one configuration and result interface | trend, season, residual, optional components, meta |
Method parameters, backend and grouping policy |
Several projects already offer broad catalogs or common estimator interfaces. DeTime's practical contribution is its combination of a shared decomposition result, configuration, CLI, saved artifacts and machine-readable metadata. Those features are useful when a project needs to repeat the same workflow across families. A specialist library remains a strong choice when its method-specific diagnostics or controls are central to the analysis.
2. What the method choice actually changes
STL and MSTL: specify the seasonal structure
STL uses LOESS smoothing with a specified period. Its seasonal argument is
the seasonal smoother length; it is distinct from period. Robust weighting
is available through robust=True. For NumPy arrays, the period must be
provided. MSTL extends this workflow to multiple periods and permits an
optional Box–Cox transformation. Its result retains the separate seasonal
components. STL documentation; MSTL documentation.
For hourly observations, a daily period corresponds to 24 samples only if the sampling grid is actually hourly. State how gaps, duplicate timestamps and clock changes were handled before interpreting the components. A period specified in samples should always be accompanied by the sampling interval.
One naming detail matters in DeTime: ROBUST_STL selects the statsmodels STL
wrapper with robust weighting enabled by default. This identifier should not
be cited as an implementation of a different paper merely because that paper
has a similar title. The wrapper source and
method references identify the implemented method.
Wavelets: define scales and boundary behavior
PyWavelets exposes approximation/detail coefficient arrays, multilevel
decomposition and inverse reconstruction. Decimated coefficients generally
have different lengths from the original series. Reconstruct selected levels
before treating them as sample-aligned components. The documented
waverec interface supports partial reconstruction by replacing unwanted
coefficient arrays with zeros of matching shape. DWT; inverse DWT.
Boundary handling is part of the method specification. PyWavelets documents several extension modes and explains that the choice can introduce edge artifacts. Record the same extension convention for analysis and synthesis. Calling a low-frequency reconstruction “trend” is an interpretation that should be justified by the application. Signal extension modes.
EMD-family methods: identify the implementation and randomness
PyEMD and emd are separate projects. PyEMD is distributed as EMD-signal
and imported as PyEMD; its documented classes include EMD, EEMD and CEEMDAN.
The emd distribution is imported as emd and includes ensemble, complete
ensemble and masked sifts, together with spectral and cycle analysis.
Installation names and import names therefore belong in the experiment
record. PyEMD introduction; emd installation;
emd API.
Noise-assisted methods need a reproducibility policy. Current PyEMD CEEMDAN
documentation recommends calling noise_seed() and using parallel=False
for reproducible runs. It documents epsilon for adaptive noise scaling;
EEMD documents a separate noise_width parameter. Copying parameter names
between the two classes can change the intended experiment.
CEEMDAN documentation; EEMD documentation.
The application must also specify how IMFs are assigned to the quantities it will use. A low-frequency group, a selected oscillation and the remaining signal are different outputs from the raw IMF array. Retain the grouping rule with the result so another researcher can reconstruct that decision.
SSA: the grouping rule carries scientific meaning
The pyts SSA interface accepts a matrix of univariate samples and exposes
window size and grouping controls. groups='auto' uses documented
frequency-based criteria for trend, seasonal and residual groups. Its fit
method is a pass-through; the decomposition happens during transform.
chunksize batches the collection of series to trade memory for runtime.
It does not turn one long series into an online decomposition.
pyts SSA documentation.
SSALib provides a different SSA workflow: multiple SVD solver options, grouped reconstruction, weighted-correlation plots and Monte Carlo SSA. Those diagnostics can matter more than a common interface when the research question concerns the interpretation of a particular component. SSALib repository.
For an SSA comparison, report window length, rank when truncated, solver and the exact groups used in reconstruction. Changing any of these can change the estimated components. A component index is an algorithmic label; assigning a physical meaning requires additional evidence.
VMD and multivariate decomposition: fix the output contract
sktime documents VmdTransformer as the maintained continuation of vmdpy.
The original repository was archived in June 2024 and directs development to
sktime. The transformer supports a specified mode count or an iterative
selection based on its reconstruction-loss criterion. Record K, alpha,
initialization and stopping tolerance; an automatically selected mode count
is an outcome of that criterion. VmdTransformer;
vmdpy maintenance notice.
PySDKit documents a broad family of signal decompositions, including MEMD and
MVMD. Its MVMD interface documents mode output with shape (K, length,
num_channels). Check the axis convention before connecting that output to a
plotting or learning pipeline. Shared mode indices across channels do not by
themselves establish that a mode corresponds to a particular physical source.
PySDKit API; MVMD documentation.
3. What a unified result can and cannot establish
DeTime provides one decompose() entry point and a DecompResult containing
trend, season, residual, components and meta. Its implementation
mixes maintained in-package methods, native-backed paths and integrations:
STL/MSTL call statsmodels, WAVELET calls PyWavelets, EMD/CEEMDAN use PyEMD,
and optional multivariate wrappers use PySDKit. These relationships are
documented in the method matrix and
source tree.
The common fields simplify code that saves, compares or visualizes results. They do not make the underlying component definitions equivalent. A wavelet approximation, an SSA group and an STL trend express different assumptions. In several DeTime methods, the residual is explicitly calculated as the input minus the selected trend and seasonal components. SSA implementation; wavelet implementation.
Consequently, a near-zero reconstruction error can confirm arithmetic
consistency while providing little evidence about identification. If
residual = input - trend - season, then the three fields reconstruct the
input by construction. A useful component evaluation needs a separate target:
known synthetic components, a controlled physical process, external
measurements, or a downstream question with an appropriate held-out test.
DeTime also documents architecture-inspired experimental decomposition operators. Their identifiers record a source of inspiration. Treat those operators according to their documented implementation scope; a standalone moving-average or wavelet block does not reproduce a complete trained forecasting system. Experimental method scope.
4. Keep future observations outside a forecasting feature
For a forecast issued at time t, every preprocessing step must use only
information available at t. Consider a centered smoother computed once over
an entire record: an estimated trend at an earlier point can depend on later
observations. Slicing its output afterward does not remove that dependence.
This follows from the information used by the computation, regardless of the
package name.
A practical forecasting protocol is:
- Fix training, validation and test forecast origins before tuning.
- At each origin, pass only the available history to the decomposition.
- Construct the input features and forecast using that history.
- Evaluate against the future observations after prediction is complete.
- Keep period selection, normalization, missing-value treatment and parameter tuning within the corresponding training/validation information boundary.
Refitting on a growing prefix is a valid way to enforce this boundary, but it
can be expensive. A rolling window changes the estimator and should be
declared. A dedicated online method has its own update and latency contract.
For example, PySDKit lists OnlineEMD; that capability should be evaluated
through its specific API rather than inferred for every EMD implementation.
PySDKit catalog.
Offline analysis has a different information budget. Describing a completed record can legitimately use the whole record. Classifying a fully observed window can also use that window if it matches the intended deployment input. The relevant question is whether the evaluation reproduces what will be available when the output is used.
5. A comparison protocol that produces useful evidence
The following is a proposed evaluation protocol, not a report of executed cross-package experiments.
| Question | Evidence to collect | Interpretation limit |
|---|---|---|
| Does the implementation reconstruct its declared output? | Reconstruction error, shape checks and retained residual policy | Does not identify the true generating components |
| Does it recover components relevant to the task? | Known components or independent reference measurements; grouping rule | A visually smooth curve alone is insufficient |
| Is it stable under reasonable choices? | Perturbations of window, rank, period, mode count, noise and seed | Stability around one configuration can miss other regimes |
| Does it improve a downstream task? | Same splits, model, tuning budget and information boundary | A change in the whole pipeline does not isolate decomposition |
| What resources does it use? | Wall time, peak memory, input dimensions, threads, backend and versions | A small input or one machine cannot establish general scaling |
Measure startup and steady-state execution separately when they affect the deployment workload. Report failed decompositions and unavailable optional dependencies alongside successful runs. Do not average them away by silently changing the compared dataset or method set.
For multivariate data, record whether channels were decomposed jointly or independently. For stochastic methods, retain the seed and process settings. For modes that can reorder, compare components using a declared matching rule; assigning “component 1” the same meaning in every run is an additional assumption.
6. Pick a first workflow
Use statsmodels directly for its seasonal-decomposition and statistical
modeling workflow. Use PyWavelets for detailed transform controls. Compare
PyEMD and emd according to the sifting and oscillation-analysis tools needed.
Consider pyts for batched SSA transforms, SSALib for SSA diagnostics, sktime
for estimator composition, and PySDKit for broader signal-decomposition
exploration. These recommendations follow the documented interfaces above.
Use DeTime when the repeated task is to run several families, retain one
result layout, inspect backend metadata, and export results through Python or
the CLI. Start with the quickstart, inspect the
configuration reference, and preserve the exact
configuration with the output. Install the distribution detime-toolkit and
import detime, as specified in the installation guide.
Source-head maintenance and released wheels have separate version histories.
For example, the CEEMDAN parameter-forwarding and seed-handling corrections
accompanying this guide belong to the unreleased source changes. They should
not be assumed to exist in detime-toolkit==0.1.3. Record the installed version
or source commit and consult the changelog when reproducing
a configuration.
For the research behind the methods and newer decomposition-based models, continue with the decomposition literature map. For reproducible software comparisons, begin with the existing evidence and its stated limits.
Sources
All external sources below are official project documentation or repositories. Links were reviewed on 29 October 2026. They can change independently of the package version installed in an experiment.
- statsmodels STL and MSTL.
- PyWavelets DWT, inverse DWT, and signal extension modes.
- PyEMD documentation, installation, CEEMDAN, and EEMD.
- emd API and installation.
- pyts SingularSpectrumAnalysis.
- SSALib repository.
- sktime VmdTransformer and vmdpy maintenance notice.
- PySDKit API and VMD/MVMD interfaces.
- DeTime source, STL wrapper, SSA, and wavelets.