# PyAF: automatic time series forecasting in a pandas dataframe

> PyAF wraps signal decomposition, AR/ARX models and scikit-learn estimation behind a single forecast engine object. It suits pandas users who want a working baseline forecast without hand-picking a model.

**antoinecarme/pyaf** — PyAF is an Open Source Python library for Automatic Time Series Forecasting built on top of popular pydata modules.

- Repository: https://github.com/antoinecarme/pyaf
- Stars: 460 · Forks: 72
- Language: Python
- License: BSD-3-Clause
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/antoinecarme-pyaf

## The problem PyAF solves for pandas users

Fitting a time series model by hand means choosing a decomposition, deciding whether the trend is linear or not, guessing the seasonal period, and then estimating an AR component on the residual. PyAF automates that selection. The README describes it as "an automated process for predicting future values of a signal using a machine learning approach", and the intended user is someone who already has a pandas dataframe with a time column and a signal column and does not want to write the model-selection loop themselves.

The library is explicit about its scope: it consumes a dataframe and returns a dataframe. There is no storage layer, no scheduler, no serving component in the core package. If your pipeline is pandas-shaped, the fit is natural. If your data lives in a feature store or a streaming system, you will be exporting to pandas before PyAF can do anything.

## How the forecast engine selects a model

The core object is cForecastEngine. Training splits the signal into an estimation part and a validation part, 80% and 20% respectively according to the README, and the performance figure reported by getModelInfo() is computed on the part that was not used for estimation. That detail matters: the reported error is a holdout error, not a fitted-sample error, so it is a usable starting point for comparison.

Underneath, PyAF runs what the README calls "a competition between a comprehensive set of possible signal transformations and linear decompositions". For each transformed signal, candidate trends, periodic components and AR models are generated, all combinations are estimated, and the best decomposition by validation performance is kept. Trend regressions and AR/ARX models are estimated with scikit-learn linear regression, so the estimation path is the one you already know. Supported transformations include four defaults plus others such as Box-Cox. Error measures listed in the README are L1, RMSE, MAPE, MedAE and LnQ.

Exogenous variables enter through their past values as ARX terms. They can be numeric, string, date or object typed; non-numeric columns are dummified and numeric ones standardized. Hierarchical forecasting follows the approach in Hyndman and Athanasopoulos, covering both strict hierarchies and grouped time series.

## Installing PyAF and running a first forecast

There is no published install command in the README; the package is named pyaf in setup.py, version 5.0, and requires Python 3 or later. The declared dependencies are scipy, pandas, scikit-learn, matplotlib, pydot and dill. A normal pip install from the repository or from PyPI is the expected route, but the README does not spell it out, so check the package index before assuming a wheel exists.

```bash
pip install pyaf
```

The README ships a runnable demo. It builds a daily signal of 360 points, trains with a horizon of 7, and prints the forecast columns. Note the iTime, iSignal and iHorizon keyword names; those are the argument names used in the example.

```python
import numpy as np, pandas as pd
import pyaf.ForecastEngine as autof

N = 360
df_train = pd.DataFrame({"Date": pd.date_range(start="2016-01-25", periods=N, freq='D'),
                         "Signal": (np.arange(N)//40 + np.arange(N) % 21 + np.random.randn(N))})

lEngine = autof.cForecastEngine()
lEngine.train(iInputDS=df_train, iTime='Date', iSignal='Signal', iHorizon=7)
lEngine.getModelInfo()
```

After training, getModelInfo() reports the relative error, which the README puts at 7% MAPE for this synthetic signal. Forecasting returns a dataframe whose last seven rows carry the future dates and the predicted values under Signal_Forecast.

```python
df_forecast = lEngine.forecast(iInputDS=df_train, iHorizon=7)
print(df_forecast.columns)
print(df_forecast['Date'].tail(7).values)
print(df_forecast['Signal_Forecast'].tail(7).values)
```

The README notes the same example is available as a Jupyter notebook at docs/sample_code.ipynb, which is the faster path if you want to see the intermediate decomposition plots rather than read them out of the engine.

## Time frequency inference and where it breaks

PyAF infers the frequency from the data rather than requiring you to declare it. Natural frequencies Minute, Hour, Day, Week and Month are supported, and irregular spacings such as every 3.2 days or every 17 minutes are handled if the data are recorded that way. By default the frequency is the mean duration between consecutive observations, expressed as a pandas DateOffset, and it is used to generate future dates. Real or integer valued fake dates are accepted too.

The README is candid that this is approximate when dates are not regularly observed: "PyAF does its best when dates are not regularly observed. Time frequency is approximate in this case." That is the main failure mode to watch. If your series has gaps from outages, a mean-duration frequency will smear the seasonal index and the periodic component will be fitted against the wrong phase. For a signal with a known calendar, passing a clean regularly spaced frame is safer than relying on inference. The README does not document a way to override the inferred frequency directly, which is a real gap for anyone with messy timestamps.

## PyAF against statsmodels and Prophet-style workflows

statsmodels is the obvious alternative and it appears in the repository requirements.txt. The difference is control versus automation. statsmodels gives you the estimator: you choose SARIMAX orders, you specify the seasonal period, you inspect the summary table. PyAF gives you the search: it enumerates decompositions and returns the best one by holdout error, with no order specification from you. If you need to defend a specific model form to a reviewer, statsmodels is the better fit. If you need a baseline in an afternoon, PyAF removes the specification step.

The cost of that automation is transparency in the other direction. PyAF does expose the chosen decomposition and the model info, but the selection is driven by an internal competition over a candidate set the README does not enumerate exhaustively. You get a validation error, not a derivation. For a signal where the generating process is known, that trade is usually worth taking; for one where it is not, the automatic winner can be a periodic component that happens to fit the validation window.

## Maintenance, releases and licence

The repository is not archived and the last push was on 2026-06-26. Releases are annual and sparse: 5.0 in July 2023, 4.0 in July 2022, 3.0 in July 2021. The gap between the 5.0 release and the most recent commits means the master branch and the released package are not the same thing, and the README does not describe a compatibility policy or a rollback procedure between major versions. Treat a version bump as something to test against your own signal rather than assume.

The licence is BSD-3-Clause, declared in setup.py as "BSD 3-clause" and linked from the README. That is a permissive licence, which generally means you can use the library in commercial work provided the copyright notice and disclaimer are retained. The repository also carries a CITATION.cff and a Zenodo DOI, so academic citation is supported. For the exact obligations, read the LICENSE file; this is a description of what the repository states, not legal advice.

## Conclusion

Adopt PyAF if your data already lives in a pandas dataframe and you need a defensible baseline forecast for daily, weekly or monthly signals, including hierarchies and exogenous columns. Do not adopt it if you need a documented upgrade path or a response-time guarantee: the last push was on 2026-06-26, the latest release 5.0 dates from July 2023, and the README does not document rollback or compatibility guarantees between versions. Before committing, run the engine on your own signal, check getModelInfo() against a naive seasonal baseline, and read the LICENSE file for the BSD-3-Clause terms.

## FAQ

### What is PyAF used for?

PyAF is a Python library for automatic time series forecasting. It takes a pandas dataframe with a time column and a signal column, trains a model by competing signal transformations and decompositions, and returns forecasts in another dataframe.

### How do I install PyAF?

The package is named pyaf and setup.py declares version 5.0 with Python 3 or later. The README does not give an install command, so confirm the current distribution on the package index before installing.

### What are the main arguments of cForecastEngine.train in PyAF?

The README example calls train with iInputDS for the training dataframe, iTime for the time column name, iSignal for the signal column name and iHorizon for the number of future periods. Forecast uses iInputDS and iHorizon.

### Does PyAF need the time frequency to be specified?

No. PyAF infers the frequency from the data, using the mean duration between consecutive observations as a pandas DateOffset by default. The README notes that the frequency is approximate when dates are not regularly observed.

### What licence does PyAF use?

PyAF is distributed under the 3-Clause BSD license, declared as "BSD 3-clause" in setup.py. The repository also includes a CITATION.cff and a Zenodo DOI for citation.

## Sources

- [antoinecarme/pyaf on GitHub](https://github.com/antoinecarme/pyaf)
- [Issues](https://github.com/antoinecarme/pyaf/issues)
- [License: BSD-3-Clause](https://github.com/antoinecarme/pyaf/blob/master/LICENSE)
- [README](https://github.com/antoinecarme/pyaf/blob/master/README.md)
- [Releases](https://github.com/antoinecarme/pyaf/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/antoinecarme-pyaf
