Skip to content

ForecasterStats

skforecast.recursive._forecaster_stats.ForecasterStats

ForecasterStats(
    estimator,
    transformer_y=None,
    transformer_exog=None,
    forecaster_id=None,
    fit_kwargs=None,
)

Bases: MultiEstimatorMixin

This class turns statistical models into a Forecaster compatible with the skforecast API. It supports single or multiple statistical models for the same time series, enabling model comparison and ensemble predictions.

Supported statistical models are: skforecast.stats.Arima, skforecast.stats.Arar, skforecast.stats.Ets, skforecast.stats.Sarimax, sktime.forecasting.ARIMA, aeon.forecasting.stats.ARIMA and aeon.forecasting.stats.ETS.

Parameters:

Name Type Description Default
estimator object, list of objects

A statistical model instance or a list of statistical model instances. When a list is provided, all models are fitted to the same time series and predictions from all models are returned. Supported models are:

  • skforecast.stats.Arima
  • skforecast.stats.Arar
  • skforecast.stats.Ets
  • skforecast.stats.Sarimax (statsmodels wrapper)
  • sktime.forecasting.ARIMA (pmdarima wrapper)
  • aeon.forecasting.stats.ARIMA
  • aeon.forecasting.stats.ETS
required
transformer_y object transformer (preprocessor)

An instance of a transformer (preprocessor) compatible with the scikit-learn preprocessing API with methods: fit, transform, fit_transform and inverse_transform. ColumnTransformers are not allowed since they do not have inverse_transform method. The transformation is applied to y before training the forecaster.

None
transformer_exog object transformer (preprocessor)

An instance of a transformer (preprocessor) compatible with the scikit-learn preprocessing API. The transformation is applied to exog before training the forecaster. inverse_transform is not available when using ColumnTransformers.

None
forecaster_id (str, int)

Name used as an identifier of the forecaster.

None
fit_kwargs Ignored

Not used, present here for API consistency by convention.

None

Attributes:

Name Type Description
estimators list

List of the original statistical model instances provided by the user without being fitted.

estimators_ list

List of statistical model instances. These are the estimators that will be trained when fit() is called.

estimator_ids list

Unique identifiers for each estimator, generated from estimator types and numeric suffixes to handle duplicates (e.g., 'skforecast.Arima', 'skforecast.Arima_2', 'skforecast.Ets'). Used to identify predictions from each model.

estimator_types list

Full qualified type string for each estimator (e.g., 'skforecast.stats._arima.Arima').

estimator_names_ list

Descriptive names for each estimator including the fitted model configuration (e.g., 'Arima(1,1,1)(0,0,0)[12]', 'Ets(AAA)', etc.). This is updated after fitting to reflect the selected model.

estimator_params_ dict

Dictionary containing the parameters of each estimator.

n_estimators int

Number of estimators in the forecaster.

transformer_y object transformer (preprocessor)

An instance of a transformer (preprocessor) compatible with the scikit-learn preprocessing API with methods: fit, transform, fit_transform and inverse_transform. ColumnTransformers are not allowed since they do not have inverse_transform method. The transformation is applied to y before training the forecaster.

transformer_exog object transformer (preprocessor)

An instance of a transformer (preprocessor) compatible with the scikit-learn preprocessing API. The transformation is applied to exog before training the forecaster. inverse_transform is not available when using ColumnTransformers.

window_size int

Not used, present here for API consistency by convention.

last_window_ pandas Series

Last window the forecaster has seen during training. It stores the values needed to predict the next step immediately after the training data. In the statistical models it stores all the training data.

extended_index_ pandas Index

Index the forecaster has seen during training and prediction. This attribute's initial value is the index of the training data, but this is extended after predictions are made using an external 'last_window'.

index_type_ type

Type of index of the input used in training.

index_freq_ str

Frequency of Index of the input used in training.

training_range_ pandas Index

First and last values of index of the data used during training.

series_name_in_ str

Name of the series provided by the user during training.

exog_in_ bool

If the forecaster has been trained using exogenous variable/s.

exog_names_in_ list

Names of the exogenous variables used during training.

exog_type_in_ type

Type of exogenous variable/s used in training.

exog_dtypes_in_ dict

Type of each exogenous variable/s used in training before the transformation applied by transformer_exog. If transformer_exog is not used, it is equal to exog_dtypes_out_.

exog_dtypes_out_ dict

Type of each exogenous variable/s used in training after the transformation applied by transformer_exog. If transformer_exog is not used, it is equal to exog_dtypes_in_.

X_train_exog_names_out_ list

Names of the exogenous variables included in the matrix X_train created internally for training. It can be different from exog_names_in_ if some exogenous variables are transformed during the training process.

creation_date str

Date of creation.

is_fitted bool

Tag to identify if the estimator has been fitted (trained).

fit_date str

Date of last fit.

valid_estimator_types tuple

Valid estimator types.

estimators_support_last_window tuple

Estimators that support last_window argument in prediction methods.

estimators_support_exog tuple

Estimators that support exogenous variables.

estimators_support_interval tuple

Estimators that support prediction intervals.

estimators_support_reduce_memory tuple

Estimators that support reduce memory method.

_predict_dispatch dict

Dictionary dispatch for estimator-specific predict methods.

_predict_interval_dispatch dict

Dictionary dispatch for estimator-specific predict_interval methods.

_feature_importances_dispatch dict

Dictionary dispatch for estimator-specific feature importance methods.

_info_criteria_dispatch dict

Dictionary dispatch for estimator-specific information criteria methods.

skforecast_version str

Version of skforecast library used to create the forecaster.

python_version str

Version of python used to create the forecaster.

forecaster_id (str, int)

Name used as an identifier of the forecaster.

__skforecast_tags__ dict

Tags associated with the forecaster.

fit_kwargs Ignored

Not used, present here for API consistency by convention.

Methods:

Name Description
fit

Training Forecaster.

predict

Forecast future values.

predict_interval

Forecast future values and their confidence intervals.

set_params

Set new values to the parameters of the model stored in the forecaster.

set_fit_kwargs

This method is a placeholder to maintain API consistency. When using

get_feature_importances

Return feature importances of the estimator stored in the forecaster.

get_info_criteria

Get the selected information criteria.

summary

Show forecaster information.

reduce_memory

Reduce memory usage by removing internal arrays of the estimator not

Source code in skforecast/recursive/_forecaster_stats.py
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
def __init__(
    self,
    estimator: object | list[object],
    transformer_y: object | None = None,
    transformer_exog: object | None = None,
    forecaster_id: str | int | None = None,
    fit_kwargs: Any = None,
) -> None:

    # Valid estimator types (class-level constant)
    self.valid_estimator_types = (
        'skforecast.stats._arima.Arima',
        'skforecast.stats._arar.Arar',
        'skforecast.stats._ets.Ets',
        'skforecast.stats._sarimax.Sarimax',
        'aeon.forecasting.stats._arima.ARIMA',
        'aeon.forecasting.stats._ets.ETS',
        'sktime.forecasting.arima._pmdarima.ARIMA'
    )

    if not isinstance(estimator, list):
        estimator = [estimator]
    else:
        if len(estimator) == 0:
            raise ValueError("`estimator` list cannot be empty.")

    # Validate all estimators and collect types
    estimator_types = []
    for i, est in enumerate(estimator):
        est_type = f"{type(est).__module__}.{type(est).__name__}"
        if est_type not in self.valid_estimator_types:
            raise TypeError(
                f"Estimator at index {i} must be an instance of type "
                f"{self.valid_estimator_types}. Got '{type(est)}'."
            )
        estimator_types.append(est_type)

    # TODO: Evaluate if include 'aggregate' parameter for multiple estimators, it
    # aggregates predictions from all estimators.
    self.estimators              = estimator
    self.estimators_             = [clone(est) for est in self.estimators]
    self.estimator_ids           = self._generate_estimator_ids()
    self.estimator_types         = estimator_types
    self.estimator_names_        = [None] * len(self.estimators)
    self.n_estimators            = len(self.estimators)
    self.transformer_y           = transformer_y
    self.transformer_exog        = transformer_exog
    self.last_window_            = None
    self.extended_index_         = None
    self.index_type_             = None
    self.index_freq_             = None
    self.training_range_         = None
    self.series_name_in_         = None
    self.exog_in_                = False
    self.exog_names_in_          = None
    self.exog_type_in_           = None
    self.exog_dtypes_in_         = None
    self.exog_dtypes_out_        = None
    self.X_train_exog_names_out_ = None
    self.creation_date           = pd.Timestamp.today().strftime('%Y-%m-%d %H:%M:%S')
    self.is_fitted               = False
    self.fit_date                = None
    self.skforecast_version      = __version__
    self.python_version          = sys.version.split(" ")[0]
    self.forecaster_id           = forecaster_id
    self.window_size             = 1     # Ignored, present for API consistency
    self.fit_kwargs              = None  # Ignored, present for API consistency

    self.estimator_params_       = {
        est_id: est.get_params() 
        for est_id, est in zip(self.estimator_ids, self.estimators_)
    }

    self.estimators_support_last_window = (
        'skforecast.stats._sarimax.Sarimax',
    )
    self.estimators_support_exog = (
        'skforecast.stats._arima.Arima',
        'skforecast.stats._arar.Arar',
        'skforecast.stats._sarimax.Sarimax',
        'sktime.forecasting.arima._pmdarima.ARIMA',
    )
    self.estimators_support_interval = (
        'skforecast.stats._arima.Arima',
        'skforecast.stats._arar.Arar',
        'skforecast.stats._ets.Ets',
        'skforecast.stats._sarimax.Sarimax',
        'sktime.forecasting.arima._pmdarima.ARIMA'
    )
    self.estimators_support_reduce_memory = (
        'skforecast.stats._arima.Arima',
        'skforecast.stats._arar.Arar',
        'skforecast.stats._ets.Ets'
    )
    self._predict_dispatch = {
        'skforecast.stats._arima.Arima': self._predict_skforecast_stats,
        'skforecast.stats._arar.Arar': self._predict_skforecast_stats,
        'skforecast.stats._ets.Ets': self._predict_skforecast_stats,
        'skforecast.stats._sarimax.Sarimax': self._predict_sarimax,
        'aeon.forecasting.stats._arima.ARIMA': self._predict_aeon,
        'aeon.forecasting.stats._ets.ETS': self._predict_aeon,
        'sktime.forecasting.arima._pmdarima.ARIMA': self._predict_sktime_arima
    }
    self._predict_interval_dispatch = {
        'skforecast.stats._arima.Arima': self._predict_interval_skforecast_stats,
        'skforecast.stats._arar.Arar': self._predict_interval_skforecast_stats,
        'skforecast.stats._ets.Ets': self._predict_interval_skforecast_stats,
        'skforecast.stats._sarimax.Sarimax': self._predict_interval_sarimax,
        'sktime.forecasting.arima._pmdarima.ARIMA': self._predict_interval_sktime_arima,
    }
    self._feature_importances_dispatch = {
        'skforecast.stats._arima.Arima': self._get_feature_importances_skforecast_stats,
        'skforecast.stats._arar.Arar': self._get_feature_importances_skforecast_stats,
        'skforecast.stats._ets.Ets': self._get_feature_importances_skforecast_stats,
        'skforecast.stats._sarimax.Sarimax': self._get_feature_importances_skforecast_stats,
        'aeon.forecasting.stats._arima.ARIMA': self._get_feature_importances_aeon_arima,
        'aeon.forecasting.stats._ets.ETS': self._get_feature_importances_aeon_ets,
        'sktime.forecasting.arima._pmdarima.ARIMA': self._get_feature_importances_sktime_arima
    }
    self._info_criteria_dispatch = {
        'skforecast.stats._arima.Arima': self._get_info_criteria_skforecast_stats,
        'skforecast.stats._arar.Arar': self._get_info_criteria_skforecast_stats,
        'skforecast.stats._ets.Ets': self._get_info_criteria_skforecast_stats,
        'skforecast.stats._sarimax.Sarimax': self._get_info_criteria_sarimax,
        'aeon.forecasting.stats._arima.ARIMA': self._get_info_criteria_aeon,
        'aeon.forecasting.stats._ets.ETS': self._get_info_criteria_aeon,
        'sktime.forecasting.arima._pmdarima.ARIMA': self._get_info_criteria_sktime_arima
    }

    self.__skforecast_tags__ = {
        "library": "skforecast",
        "forecaster_name": "ForecasterStats",
        "forecaster_task": "regression",
        "forecasting_scope": "single-series",  # single-series | global
        "forecasting_strategy": "recursive",   # recursive | direct | deep_learning | foundation
        "multiple_estimators": True,
        "index_types_supported": ["pandas.RangeIndex", "pandas.DatetimeIndex"],
        "requires_index_frequency": True,

        "allowed_input_types_series": ["pandas.Series"],
        "supports_exog": True,
        "allowed_input_types_exog": ["pandas.Series", "pandas.DataFrame"],
        "handles_missing_values_series": False, 
        "handles_missing_values_exog": False, 

        "supports_lags": False,
        "supports_window_features": False,
        "supports_calendar_features": False,
        "supports_transformer_series": True,
        "supports_transformer_exog": True,
        "supports_categorical_features": False,
        "supports_weight_func": False,
        "supports_differentiation": False,

        "prediction_types": ["point", "interval"],
        "supports_probabilistic": True,
        "probabilistic_methods": ["distribution"],
        "handles_binned_residuals": False
    }

Attributes

valid_estimator_types instance-attribute

valid_estimator_types = (
    "skforecast.stats._arima.Arima",
    "skforecast.stats._arar.Arar",
    "skforecast.stats._ets.Ets",
    "skforecast.stats._sarimax.Sarimax",
    "aeon.forecasting.stats._arima.ARIMA",
    "aeon.forecasting.stats._ets.ETS",
    "sktime.forecasting.arima._pmdarima.ARIMA",
)

estimators instance-attribute

estimators = estimator

estimators_ instance-attribute

estimators_ = [clone(est) for est in self.estimators]

estimator_ids instance-attribute

estimator_ids = self._generate_estimator_ids()

estimator_types instance-attribute

estimator_types = estimator_types

estimator_names_ instance-attribute

estimator_names_ = [None] * len(self.estimators)

n_estimators instance-attribute

n_estimators = len(self.estimators)

transformer_y instance-attribute

transformer_y = transformer_y

transformer_exog instance-attribute

transformer_exog = transformer_exog

last_window_ instance-attribute

last_window_ = None

extended_index_ instance-attribute

extended_index_ = None

index_type_ instance-attribute

index_type_ = None

index_freq_ instance-attribute

index_freq_ = None

training_range_ instance-attribute

training_range_ = None

series_name_in_ instance-attribute

series_name_in_ = None

exog_in_ instance-attribute

exog_in_ = False

exog_names_in_ instance-attribute

exog_names_in_ = None

exog_type_in_ instance-attribute

exog_type_in_ = None

exog_dtypes_in_ instance-attribute

exog_dtypes_in_ = None

exog_dtypes_out_ instance-attribute

exog_dtypes_out_ = None

X_train_exog_names_out_ instance-attribute

X_train_exog_names_out_ = None

creation_date instance-attribute

creation_date = pd.Timestamp.today().strftime(
    "%Y-%m-%d %H:%M:%S"
)

is_fitted instance-attribute

is_fitted = False

fit_date instance-attribute

fit_date = None

skforecast_version instance-attribute

skforecast_version = __version__

python_version instance-attribute

python_version = sys.version.split(' ')[0]

forecaster_id instance-attribute

forecaster_id = forecaster_id

window_size instance-attribute

window_size = 1

fit_kwargs instance-attribute

fit_kwargs = None

estimator_params_ instance-attribute

estimator_params_ = {
    est_id: est.get_params()
    for est_id, est in zip(
        self.estimator_ids, self.estimators_
    )
}

estimators_support_last_window instance-attribute

estimators_support_last_window = (
    "skforecast.stats._sarimax.Sarimax",
)

estimators_support_exog instance-attribute

estimators_support_exog = (
    "skforecast.stats._arima.Arima",
    "skforecast.stats._arar.Arar",
    "skforecast.stats._sarimax.Sarimax",
    "sktime.forecasting.arima._pmdarima.ARIMA",
)

estimators_support_interval instance-attribute

estimators_support_interval = (
    "skforecast.stats._arima.Arima",
    "skforecast.stats._arar.Arar",
    "skforecast.stats._ets.Ets",
    "skforecast.stats._sarimax.Sarimax",
    "sktime.forecasting.arima._pmdarima.ARIMA",
)

estimators_support_reduce_memory instance-attribute

estimators_support_reduce_memory = (
    "skforecast.stats._arima.Arima",
    "skforecast.stats._arar.Arar",
    "skforecast.stats._ets.Ets",
)

Methods:

fit

fit(
    y,
    exog=None,
    store_last_window=True,
    suppress_warnings=False,
)

Training Forecaster.

Fits all estimators to the same time series. Each estimator is trained independently on the transformed data.

Parameters:

Name Type Description Default
y pandas Series

Training time series.

required
exog pandas Series, pandas DataFrame

Exogenous variable/s included as predictor/s. Must have the same number of observations as y and their indexes must be aligned so that y[i] is regressed on exog[i].

None
store_last_window bool

Whether or not to store the last window (last_window_) of training data.

True
suppress_warnings bool

If True, warnings generated during fitting will be ignored.

False

Returns:

Type Description
None
Source code in skforecast/recursive/_forecaster_stats.py
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
@manage_warnings
def fit(
    self,
    y: pd.Series,
    exog: pd.Series | pd.DataFrame | None = None,
    store_last_window: bool = True,
    suppress_warnings: bool = False
) -> None:
    """
    Training Forecaster.

    Fits all estimators to the same time series. Each estimator is trained
    independently on the transformed data.

    Parameters
    ----------
    y : pandas Series
        Training time series.
    exog : pandas Series, pandas DataFrame, default None
        Exogenous variable/s included as predictor/s. Must have the same
        number of observations as `y` and their indexes must be aligned so
        that y[i] is regressed on exog[i].
    store_last_window : bool, default True
        Whether or not to store the last window (`last_window_`) of training data.
    suppress_warnings : bool, default False
        If `True`, warnings generated during fitting will be ignored.

    Returns
    -------
    None

    """

    self.estimators_             = [clone(est) for est in self.estimators]
    self.estimator_names_        = [None] * len(self.estimators)
    self.estimator_params_       = None
    self.last_window_            = None
    self.extended_index_         = None
    self.index_type_             = None
    self.index_freq_             = None
    self.training_range_         = None
    self.series_name_in_         = None
    self.exog_in_                = False
    self.exog_names_in_          = None
    self.exog_type_in_           = None
    self.exog_dtypes_in_         = None
    self.exog_dtypes_out_        = None
    self.X_train_exog_names_out_ = None
    self.in_sample_residuals_    = None
    self.is_fitted               = False
    self.fit_date                = None

    check_y(y=y)

    if exog is not None:

        # NaNs are checked later
        check_exog(exog=exog)
        if len(exog) != len(y):
            raise ValueError(
                f"`exog` must have same number of samples as `y`. "
                f"length `exog`: ({len(exog)}), length `y`: ({len(y)})"
            )

        unsupported_exog = [
            id for id, est_type in zip(self.estimator_ids, self.estimator_types)
            if est_type not in self.estimators_support_exog
        ]
        if unsupported_exog:
            warnings.warn(
                f"The following estimators do not support exogenous variables and "
                f"will ignore them during fit: {unsupported_exog}",
                IgnoredArgumentWarning
            )

    y = transform_series(
            series              = y,
            transformer         = self.transformer_y,
            fit                 = True,
            inverse_transform   = False,
            force_single_column = True
        )

    if exog is not None:

        # NOTE: This must be here, before transforming exog
        self.exog_in_ = True
        self.exog_type_in_ = type(exog)
        self.exog_names_in_ = (
            exog.columns.to_list() if isinstance(exog, pd.DataFrame) else [exog.name]
        )
        self.exog_dtypes_in_ = get_exog_dtypes(exog=exog)

        if isinstance(exog, pd.Series):
            exog = exog.to_frame()

        exog = transform_dataframe(
                   df                = exog,
                   transformer       = self.transformer_exog,
                   fit               = True,
                   inverse_transform = False
               )

        check_exog_dtypes(exog, call_check_exog=True)
        self.exog_dtypes_out_ = get_exog_dtypes(exog=exog)
        self.X_train_exog_names_out_ = exog.columns.to_list()

    if suppress_warnings:
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            for estimator in self.estimators_:
                estimator.fit(y=y, exog=exog)
    else:
        for estimator in self.estimators_:
            estimator.fit(y=y, exog=exog)

    self.is_fitted = True

    for i, estimator in enumerate(self.estimators_):
        # Check if estimator has estimator_name_ attribute (skforecast models)
        if hasattr(estimator, 'estimator_name_') and estimator.estimator_name_ is not None:
            self.estimator_names_[i] = estimator.estimator_name_
        else:
            self.estimator_names_[i] = f"{type(estimator).__module__.split('.')[0]}.{type(estimator).__name__}"

    self.estimator_params_ = {
        est_id: est.get_params() 
        for est_id, est in zip(self.estimator_ids, self.estimators_)
    }
    self.series_name_in_ = y.name if y.name is not None else 'y'
    self.fit_date = pd.Timestamp.today().strftime('%Y-%m-%d %H:%M:%S')
    self.training_range_ = y.index[[0, -1]]
    self.index_type_ = type(y.index)
    if isinstance(y.index, pd.DatetimeIndex):
        self.index_freq_ = y.index.freqstr
    else: 
        self.index_freq_ = y.index.step

    # TODO: Check when multiple series are supported
    if store_last_window:
        self.last_window_ = y.copy()

    # Set extended_index_ based on first SARIMAX estimator or default to y.index
    first_sarimax = next(
        (est for est, est_type in zip(self.estimators_, self.estimator_types)
         if est_type == 'skforecast.stats._sarimax.Sarimax'),
        None
    )
    if first_sarimax is not None:
        self.extended_index_ = first_sarimax.sarimax_res.fittedvalues.index.copy()
    else:
        self.extended_index_ = y.index

predict

predict(
    steps,
    last_window=None,
    last_window_exog=None,
    exog=None,
    suppress_warnings=False,
)

Forecast future values.

Generate predictions (forecasts) n steps in the future using all fitted estimators. If exogenous variables were used during training, they must be provided for prediction.

When using last_window and last_window_exog, they must start right after the end of the index seen by the forecaster during training. This feature is only supported for skforecast.Sarimax estimator; other estimators will ignore last_window and predict from the end of the training data.

Parameters:

Name Type Description Default
steps int

Number of steps to predict.

required
last_window pandas Series

Series values used to create the predictors needed in the predictions. Used to make predictions unrelated to the original data. Values must start at the end of the training data. Only supported for skforecast.Sarimax estimator.

None
last_window_exog pandas Series, pandas DataFrame

Values of the exogenous variables aligned with last_window. Only needed when last_window is not None and the forecaster has been trained including exogenous variables. Values must start at the end of the training data.

None
exog pandas Series, pandas DataFrame

Exogenous variable/s included as predictor/s.

None
suppress_warnings bool

If True, skforecast warnings will be suppressed during the prediction process. See skforecast.exceptions.warn_skforecast_categories for more information.

False

Returns:

Name Type Description
predictions pandas Series, pandas DataFrame

Predicted values from all estimators:

  • For multiple estimators: long format DataFrame with columns 'estimator_id' (estimator id) and 'pred' (predicted value).
  • For a single estimator: pandas Series with predicted values.
Source code in skforecast/recursive/_forecaster_stats.py
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
@manage_warnings
def predict(
    self,
    steps: int,
    last_window: pd.Series | None = None,
    last_window_exog: pd.Series | pd.DataFrame | None = None,
    exog: pd.Series | pd.DataFrame | None = None,
    suppress_warnings: bool = False
) -> pd.Series | pd.DataFrame:
    """
    Forecast future values.

    Generate predictions (forecasts) n steps in the future using all 
    fitted estimators. If exogenous variables were used during training, 
    they must be provided for prediction.

    When using `last_window` and `last_window_exog`, they must start right 
    after the end of the index seen by the forecaster during training. 
    This feature is only supported for skforecast.Sarimax estimator; 
    other estimators will ignore `last_window` and predict from the end 
    of the training data.

    Parameters
    ----------
    steps : int
        Number of steps to predict. 
    last_window : pandas Series, default None
        Series values used to create the predictors needed in the 
        predictions. Used to make predictions unrelated to the original data. 
        Values must start at the end of the training data. Only supported 
        for skforecast.Sarimax estimator.
    last_window_exog : pandas Series, pandas DataFrame, default None
        Values of the exogenous variables aligned with `last_window`. Only
        needed when `last_window` is not None and the forecaster has been
        trained including exogenous variables. Values must start at the end 
        of the training data.
    exog : pandas Series, pandas DataFrame, default None
        Exogenous variable/s included as predictor/s.
    suppress_warnings : bool, default False
        If `True`, skforecast warnings will be suppressed during the prediction 
        process. See skforecast.exceptions.warn_skforecast_categories for more
        information.

    Returns
    -------
    predictions : pandas Series, pandas DataFrame
        Predicted values from all estimators:

        - For multiple estimators: long format DataFrame with columns 
        'estimator_id' (estimator id) and 'pred' (predicted value).
        - For a single estimator: pandas Series with predicted values.

    """

    last_window, last_window_exog, exog, prediction_index = (
        self._create_predict_inputs(
            steps            = steps,
            last_window      = last_window,
            last_window_exog = last_window_exog,
            exog             = exog,
        )
    )

    if last_window is not None:
        prediction_index = self._check_append_last_window(
            steps            = steps,
            last_window      = last_window,
            last_window_exog = last_window_exog
        )

    all_predictions = []
    estimator_ids = []
    for estimator, est_id, est_type in zip(
        self.estimators_, self.estimator_ids, self.estimator_types
    ):
        if last_window is not None and est_type not in self.estimators_support_last_window:
            continue

        pred_func = self._predict_dispatch[est_type]
        preds = pred_func(estimator=estimator, steps=steps, exog=exog)
        all_predictions.append(preds)
        estimator_ids.append(est_id)

    n_estimators = len(estimator_ids)
    if n_estimators == 1:
        all_predictions = all_predictions[0]
    else:
        all_predictions = np.column_stack(all_predictions).ravel()

    predictions = transform_numpy(
                      array             = all_predictions,
                      transformer       = self.transformer_y,
                      fit               = False,
                      inverse_transform = True
                  )

    if self.n_estimators == 1:
        predictions = pd.Series(
                          data  = predictions.ravel(),
                          index = prediction_index,
                          name  = 'pred'
                      )
    else:
        predictions = pd.DataFrame(
            {"estimator_id": np.tile(estimator_ids, steps), "pred": predictions.ravel()},
            index = np.repeat(prediction_index, n_estimators),
        )

    return predictions

predict_interval

predict_interval(
    steps,
    last_window=None,
    last_window_exog=None,
    exog=None,
    alpha=0.05,
    interval=None,
    suppress_warnings=False,
)

Forecast future values and their confidence intervals.

Generate predictions (forecasts) n steps in the future with confidence intervals using fitted estimators that support prediction intervals. If exogenous variables were used during training, they must be provided for prediction.

Estimators that do not support prediction intervals will be skipped with a warning. Supported estimators for intervals are the ones listed in the attribute estimators_support_interval.

When using last_window and last_window_exog, they must start right after the end of the index seen by the forecaster during training. This feature is only supported for skforecast.Sarimax estimator; other estimators will ignore last_window and predict from the end of the training data.

Parameters:

Name Type Description Default
steps int

Number of steps to predict.

required
last_window pandas Series

Series values used to create the predictors needed in the predictions. Used to make predictions unrelated to the original data. Values must start at the end of the training data. Only supported for skforecast.Sarimax estimator.

None
last_window_exog pandas Series, pandas DataFrame

Values of the exogenous variables aligned with last_window. Only needed when last_window is not None and the forecaster has been trained including exogenous variables.

None
exog pandas Series, pandas DataFrame

Exogenous variable/s included as predictor/s.

None
alpha float

The confidence intervals for the forecasts are (1 - alpha) %. If both, alpha and interval are provided, alpha will be used.

0.05
interval (list, tuple)

Confidence of the prediction interval estimated. The values must be symmetric. Sequence of quantiles to compute, which must be between 0 and 1 inclusive. For example, interval of 95% should be as interval = [0.025, 0.975]. If both, alpha and interval are provided, alpha will be used.

Changed in version 0.23.0: interval is now expressed as quantiles (0-1) instead of percentiles (0-100). Passing percentiles is not longer supported and will raise a ValueError.

None
suppress_warnings bool

If True, skforecast warnings will be suppressed during the prediction process. See skforecast.exceptions.warn_skforecast_categories for more information.

False

Returns:

Name Type Description
predictions pandas DataFrame

Predicted values from estimators that support intervals and their estimated intervals:

  • For multiple estimators: long format DataFrame with columns 'estimator_id', 'pred', 'lower_bound', 'upper_bound'.
  • For a single estimator: DataFrame with columns 'pred', 'lower_bound', 'upper_bound'.
Source code in skforecast/recursive/_forecaster_stats.py
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
@manage_warnings
def predict_interval(
    self,
    steps: int,
    last_window: pd.Series | None = None,
    last_window_exog: pd.Series | pd.DataFrame | None = None,
    exog: pd.Series | pd.DataFrame | None = None,
    alpha: float = 0.05,
    interval: list[float] | tuple[float] | None = None,
    suppress_warnings: bool = False
) -> pd.DataFrame:
    """
    Forecast future values and their confidence intervals.

    Generate predictions (forecasts) n steps in the future with confidence
    intervals using fitted estimators that support prediction intervals. 
    If exogenous variables were used during training, they must be provided 
    for prediction.

    Estimators that do not support prediction intervals will be skipped 
    with a warning. Supported estimators for intervals are the ones listed
    in the attribute `estimators_support_interval`.

    When using `last_window` and `last_window_exog`, they must start right 
    after the end of the index seen by the forecaster during training. 
    This feature is only supported for skforecast.Sarimax estimator; 
    other estimators will ignore `last_window` and predict from the end 
    of the training data.

    Parameters
    ----------
    steps : int
        Number of steps to predict. 
    last_window : pandas Series, default None
        Series values used to create the predictors needed in the 
        predictions. Used to make predictions unrelated to the original data. 
        Values must start at the end of the training data. Only supported 
        for skforecast.Sarimax estimator.
    last_window_exog : pandas Series, pandas DataFrame, default None
        Values of the exogenous variables aligned with `last_window`. Only
        needed when `last_window` is not None and the forecaster has been
        trained including exogenous variables.
    exog : pandas Series, pandas DataFrame, default None
        Exogenous variable/s included as predictor/s.
    alpha : float, default 0.05
        The confidence intervals for the forecasts are (1 - alpha) %.
        If both, `alpha` and `interval` are provided, `alpha` will be used.
    interval : list, tuple, default None
        Confidence of the prediction interval estimated. The values must be
        symmetric. Sequence of quantiles to compute, which must be between 
        0 and 1 inclusive. For example, interval of 95% should be as 
        `interval = [0.025, 0.975]`. If both, `alpha` and `interval` are 
        provided, `alpha` will be used.

        **Changed in version 0.23.0:** `interval` is now expressed as
        quantiles (0-1) instead of percentiles (0-100). Passing percentiles
        is not longer supported and will raise a `ValueError`.
    suppress_warnings : bool, default False
        If `True`, skforecast warnings will be suppressed during the prediction 
        process. See skforecast.exceptions.warn_skforecast_categories for more
        information.

    Returns
    -------
    predictions : pandas DataFrame
        Predicted values from estimators that support intervals and their 
        estimated intervals:

        - For multiple estimators: long format DataFrame with columns
          'estimator_id', 'pred', 'lower_bound', 'upper_bound'.
        - For a single estimator: DataFrame with columns
          'pred', 'lower_bound', 'upper_bound'.

    """

    # If interval and alpha take alpha, if interval transform to alpha
    if alpha is None:
        check_interval(
            interval                   = interval,
            ensure_symmetric_intervals = True
        )
        alpha = 2 * (1 - interval[1])

    last_window, last_window_exog, exog, prediction_index = (
        self._create_predict_inputs(
            steps            = steps,
            last_window      = last_window,
            last_window_exog = last_window_exog,
            exog             = exog,
        )
    )

    if last_window is not None:
        prediction_index = self._check_append_last_window(
            steps            = steps,
            last_window      = last_window,
            last_window_exog = last_window_exog
        )

    unsupported_interval = [
        id for id, est_type in zip(self.estimator_ids, self.estimator_types)
        if est_type not in self.estimators_support_interval
    ]
    if unsupported_interval:
        warnings.warn(
            f"Interval prediction is not implemented for estimators: {unsupported_interval}. "
            f"These estimators will be skipped. Available estimators for prediction "
            f"intervals are: {list(self.estimators_support_interval)}.",
            IgnoredArgumentWarning
        )

    all_predictions = []
    estimator_ids = []
    for estimator, est_id, est_type in zip(
        self.estimators_, self.estimator_ids, self.estimator_types
    ):

        if est_type not in self.estimators_support_interval:
            continue
        if last_window is not None and est_type not in self.estimators_support_last_window:
            continue

        pred_func = self._predict_interval_dispatch[est_type]
        preds = pred_func(estimator=estimator, steps=steps, exog=exog, alpha=alpha)
        all_predictions.append(preds)
        estimator_ids.append(est_id)

    n_estimators = len(estimator_ids)
    if n_estimators == 1:
        all_predictions = all_predictions[0]
    else:
        all_predictions = np.stack(all_predictions).transpose(1, 0, 2).reshape(-1, 3)

    predictions = transform_numpy(
                      array             = all_predictions,
                      transformer       = self.transformer_y,
                      fit               = False,
                      inverse_transform = True
                  )

    predictions = pd.DataFrame(
                      data    = predictions,
                      index   = np.repeat(prediction_index, n_estimators),
                      columns = ['pred', 'lower_bound', 'upper_bound']
                  )

    if self.n_estimators == 1:
        # This is done to restore the frequency
        predictions.index = prediction_index
    else:
        predictions.insert(0, 'estimator_id', np.tile(estimator_ids, steps))

    return predictions

set_params

set_params(params)

Set new values to the parameters of the model stored in the forecaster. After calling this method, the forecaster is reset to an unfitted state. The fit method must be called before prediction.

Parameters:

Name Type Description Default
params dict

Parameters values. The expected format depends on the number of estimators in the forecaster:

  • Single estimator: A dictionary with parameter names as keys and their new values as values.
  • Multiple estimators: A dictionary where each key is an estimator id (as shown in estimator_ids) and each value is a dictionary of parameters for that estimator.
required

Returns:

Type Description
None
Source code in skforecast/recursive/_forecaster_stats.py
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
def set_params(
    self, 
    params: dict[str, object] | dict[str, dict[str, object]]
) -> None:
    """
    Set new values to the parameters of the model stored in the forecaster.
    After calling this method, the forecaster is reset to an unfitted state. 
    The `fit` method must be called before prediction.

    Parameters
    ----------
    params : dict
        Parameters values. The expected format depends on the number of
        estimators in the forecaster:

        - Single estimator: A dictionary with parameter names as keys 
        and their new values as values.
        - Multiple estimators: A dictionary where each key is an 
        estimator id (as shown in `estimator_ids`) and each value 
        is a dictionary of parameters for that estimator.

    Returns
    -------
    None

    """

    if self.n_estimators == 1:
        # Single estimator: params is a simple dict of parameter values
        self.estimators[0] = clone(self.estimators[0])
        self.estimators[0].set_params(**params)
    else:
        # Multiple estimators: params must be a dict of dicts keyed by estimator name
        if not isinstance(params, dict):
            raise TypeError(
                f"`params` must be a dictionary. Got {type(params).__name__}."
            )

        provided_ids = set(params.keys())
        valid_ids = set(self.estimator_ids)
        invalid_ids = provided_ids - valid_ids
        if invalid_ids == provided_ids:
            raise ValueError(
                f"None of the provided estimator ids {list(invalid_ids)} "
                f"match the available estimator ids: {self.estimator_ids}."
            )
        if invalid_ids:
            warnings.warn(
                f"The following estimator ids do not match any estimator "
                f"in the forecaster and will be ignored: {list(invalid_ids)}. "
                f"Available estimator ids are: {self.estimator_ids}.",
                IgnoredArgumentWarning
            )

        for est_id, est_params in params.items():
            if est_id in valid_ids:
                idx = self.estimator_ids.index(est_id)
                self.estimators[idx] = clone(self.estimators[idx])
                self.estimators[idx].set_params(**est_params)

    self.is_fitted = False
    self.estimator_params_ = {
        est_id: est.get_params() 
        for est_id, est in zip(self.estimator_ids, self.estimators)
    }

set_fit_kwargs

set_fit_kwargs(fit_kwargs=None)

This method is a placeholder to maintain API consistency. When using the skforecast Sarimax model, fit kwargs should be passed using the model parameter sm_fit_kwargs.

Parameters:

Name Type Description Default
fit_kwargs Ignored

Not used, present here for API consistency by convention.

None

Returns:

Type Description
None
Source code in skforecast/recursive/_forecaster_stats.py
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
def set_fit_kwargs(
    self, 
    fit_kwargs: Any = None
) -> None:
    """
    This method is a placeholder to maintain API consistency. When using 
    the skforecast Sarimax model, fit kwargs should be passed using the 
    model parameter `sm_fit_kwargs`.

    Parameters
    ----------
    fit_kwargs : Ignored
        Not used, present here for API consistency by convention.

    Returns
    -------
    None

    """

    warnings.warn(
        "This method is a placeholder to maintain API consistency. When using "
        "the skforecast Sarimax model, fit kwargs should be passed using the "
        "model parameter `sm_fit_kwargs`.",
        IgnoredArgumentWarning
    )

get_feature_importances

get_feature_importances(sort_importance=True)

Return feature importances of the estimator stored in the forecaster.

Parameters:

Name Type Description Default
sort_importance bool

If True, sorts the feature importances in descending order.

True

Returns:

Name Type Description
feature_importances pandas DataFrame

Feature importances associated with each predictor.

Source code in skforecast/recursive/_forecaster_stats.py
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
def get_feature_importances(
    self,
    sort_importance: bool = True
) -> pd.DataFrame:
    """
    Return feature importances of the estimator stored in the forecaster.

    Parameters
    ----------
    sort_importance: bool, default True
        If `True`, sorts the feature importances in descending order.

    Returns
    -------
    feature_importances : pandas DataFrame
        Feature importances associated with each predictor.

    """

    if not self.is_fitted:
        raise NotFittedError(
            "This forecaster is not fitted yet. Call `fit` with appropriate "
            "arguments before using `get_feature_importances()`."
        )

    feature_importances = []
    for estimator, estimator_type, estimator_id in zip(
        self.estimators_, self.estimator_types, self.estimator_ids
    ):
        get_importances_func = self._feature_importances_dispatch[estimator_type]
        importance = get_importances_func(estimator)
        if importance is not None:
            importance.insert(0, 'estimator_id', estimator_id)
            feature_importances.append(importance)

    feature_importances = pd.concat(feature_importances, ignore_index=True)

    if sort_importance:
        feature_importances = feature_importances.sort_values(
                                  by=['estimator_id', 'importance'],
                                  ascending=False
                              ).reset_index(drop=True)

    if self.n_estimators == 1:
        feature_importances = feature_importances.drop(columns=['estimator_id'])

    return feature_importances

get_info_criteria

get_info_criteria(criteria='aic', method='standard')

Get the selected information criteria.

Check https://www.statsmodels.org/dev/generated/statsmodels.tsa.statespace.sarimax.SARIMAXResults.info_criteria.html to know more about statsmodels info_criteria method.

Parameters:

Name Type Description Default
criteria str

The information criteria to compute. Valid options are {'aic', 'bic', 'hqic'}.

'aic'
method str

The method for information criteria computation. Default is 'standard' method; 'lutkepohl' computes the information criteria as in Lütkepohl (2007).

'standard'

Returns:

Name Type Description
metric pandas DataFrame

The value of the selected information criteria.

Source code in skforecast/recursive/_forecaster_stats.py
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
def get_info_criteria(
    self, 
    criteria: str = 'aic', 
    method: str = 'standard'
) -> pd.DataFrame:
    """
    Get the selected information criteria.

    Check https://www.statsmodels.org/dev/generated/statsmodels.tsa.statespace.sarimax.SARIMAXResults.info_criteria.html
    to know more about statsmodels info_criteria method.

    Parameters
    ----------
    criteria : str, default 'aic'
        The information criteria to compute. Valid options are {'aic', 'bic',
        'hqic'}.
    method : str, default 'standard'
        The method for information criteria computation. Default is 'standard'
        method; 'lutkepohl' computes the information criteria as in Lütkepohl
        (2007).

    Returns
    -------
    metric : pandas DataFrame
        The value of the selected information criteria.

    """

    if not self.is_fitted:
        raise NotFittedError(
            "This forecaster is not fitted yet. Call `fit` with appropriate "
            "arguments before using `get_info_criteria()`."
        )

    info_criteria = []
    for estimator, estimator_type in zip(self.estimators_, self.estimator_types):
        get_criteria_method = self._info_criteria_dispatch[estimator_type]
        value = get_criteria_method(estimator, criteria, method)
        info_criteria.append(value)

    if self.n_estimators == 1:
        results = pd.DataFrame({
            'criteria': criteria, 'value': info_criteria
        })
    else:
        results = pd.DataFrame({
            'estimator_id': self.estimator_ids,
            'criteria': criteria,
            'value': info_criteria
        })

    return results

summary

summary()

Show forecaster information.

Returns:

Type Description
None
Source code in skforecast/recursive/_forecaster_stats.py
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
def summary(self) -> None:
    """
    Show forecaster information.

    Returns
    -------
    None

    """

    print(self)

reduce_memory

reduce_memory()

Reduce memory usage by removing internal arrays of the estimator not needed for prediction. This method only works for estimators that expose the method reduce_memory(). The arrays removed depend on the specific estimator used.

Returns:

Type Description
None
Source code in skforecast/recursive/_forecaster_stats.py
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
def reduce_memory(self) -> None:
    """
    Reduce memory usage by removing internal arrays of the estimator not
    needed for prediction. This method only works for estimators that
    expose the method `reduce_memory()`.
    The arrays removed depend on the specific estimator used.

    Returns
    -------
    None

    """

    if not self.is_fitted:
        raise NotFittedError(
            "This forecaster is not fitted yet. Call `fit` with appropriate "
            "arguments before using `reduce_memory()`."
        )

    unsupported_reduce_memory = [
        est_id for est_id, estimator_type in zip(self.estimator_ids, self.estimator_types)
        if estimator_type not in self.estimators_support_reduce_memory
    ]
    if unsupported_reduce_memory:
        warnings.warn(
            f"Memory reduction is not implemented for estimators: {unsupported_reduce_memory}. "
            f"These estimators will be skipped. Available estimators for memory "
            f"reduction are: {list(self.estimators_support_reduce_memory)}.",
            IgnoredArgumentWarning
        )

    for estimator, est_type in zip(self.estimators_, self.estimator_types):
        if est_type in self.estimators_support_reduce_memory:
            estimator.reduce_memory()