Skip to content

BaseForecastTransformer

yohou.base.BaseForecastTransformer

Bases: _BaseTransformer

Base class for "forecast"-kind transformers over X_forecast frames.

fit and transform operate on a frame carrying "vintage_time" and "time" index columns plus one or more feature columns. transform preserves the two index columns on output and is stateless. A frame may contain any number of vintages, including one (serving a single fresh vintage) or none (an empty frame).

Attributes

Name Type Description
feature_names_in_ list[str]

Names of the non-index columns seen during fit.

n_features_in_ int

Number of non-index columns seen during fit.

X_schema_ dict[str, DataType]

Feature column name to dtype mapping seen during fit.

See Also

Source Code

Source code in src/yohou/base/forecast_transformer.py
class BaseForecastTransformer(_BaseTransformer, metaclass=abc.ABCMeta):
    """Base class for ``"forecast"``-kind transformers over ``X_forecast`` frames.

    ``fit`` and ``transform`` operate on a frame carrying ``"vintage_time"`` and
    ``"time"`` index columns plus one or more feature columns. ``transform``
    preserves the two index columns on output and is stateless. A frame may
    contain any number of vintages, including one (serving a single fresh
    vintage) or none (an empty frame).

    Attributes
    ----------
    feature_names_in_ : list[str]
        Names of the non-index columns seen during ``fit``.
    n_features_in_ : int
        Number of non-index columns seen during ``fit``.
    X_schema_ : dict[str, pl.DataType]
        Feature column name to dtype mapping seen during ``fit``.

    See Also
    --------
    - [`BaseActualTransformer`][yohou.base.transformer.BaseActualTransformer] : Base class for single-axis transformers.
    - [`PerVintageActualTransformer`][yohou.compose.per_vintage.PerVintageActualTransformer] : Lift a stateless actual transformer onto the vintage axis.

    """

    _tags: dict = {"kind": "forecast"}

    @property
    def min_vintage_rows(self) -> int:
        """Get the smallest vintage length that yields non-empty output.

        A vintage shorter than this contributes no rows to ``transform`` output.
        The default is ``1``: a transformer imposing no per-vintage minimum emits
        output for any non-empty vintage. Implementations that consume rows within
        a vintage, or that need a minimum number of rows to fit on, report their
        own larger value.

        This is deliberately not named ``observation_horizon``. On
        [`BaseActualTransformer`][yohou.base.transformer.BaseActualTransformer]
        that name means a buffer carried *between* calls, sized so the next
        ``transform`` has enough history behind it. A forecast transformer keeps
        no such buffer: each vintage is self-contained, so this quantity is a
        length requirement *within* one vintage rather than a memory depth across
        calls.

        A forecaster holding this transformer in its ``forecast_transformer`` slot
        asserts ``forecasting_horizon >= min_vintage_rows`` at fit, because a
        served vintage spans the forecasting horizon.

        Returns
        -------
        int
            Smallest vintage length yielding non-empty output, at least ``1``.

        Raises
        ------
        NotFittedError
            If the transformer has not been fitted yet.

        """
        check_is_fitted(self, ["X_schema_", "feature_names_in_", "n_features_in_"])
        return 1

    @_fit_context(prefer_skip_nested_validation=True)
    def fit(self, X: pl.DataFrame, y: pl.DataFrame | None = None, **params) -> "BaseForecastTransformer":
        """Fit the transformer to an ``X_forecast`` frame.

        Parameters
        ----------
        X : pl.DataFrame
            Input ``X_forecast`` frame with ``"vintage_time"`` and ``"time"``
            columns and one or more feature columns.
        y : pl.DataFrame or None, default=None
            Ignored.  Present for API compatibility.
        **params : dict
            Metadata to route to nested estimators.

        Returns
        -------
        self
            The fitted transformer instance.

        Raises
        ------
        ValueError
            If ``X`` is missing the ``"vintage_time"`` or ``"time"`` index
            columns.

        """
        X = _validate_forecast_transformer_data(self, X, reset=True)
        self._fit(X, y)
        return self

    def transform(self, X: pl.DataFrame, **params) -> pl.DataFrame:
        """Transform an ``X_forecast`` frame.

        Parameters
        ----------
        X : pl.DataFrame
            Input ``X_forecast`` frame with ``"vintage_time"`` and ``"time"``
            columns and one or more feature columns.
        **params : dict
            Metadata to route to nested estimators.

        Returns
        -------
        pl.DataFrame
            Transformed ``X_forecast`` frame with the ``"vintage_time"`` and
            ``"time"`` index columns preserved.

        Raises
        ------
        sklearn.exceptions.NotFittedError
            If the transformer has not been fitted yet.
        ValueError
            If ``X`` is missing an index column or its feature columns differ
            from those seen during ``fit``.

        """
        check_is_fitted(self, ["X_schema_", "feature_names_in_", "n_features_in_"])
        X = _validate_forecast_transformer_data(self, X, reset=False)
        return self._transform(X)

Methods

min_vintage_rows property

Get the smallest vintage length that yields non-empty output.

A vintage shorter than this contributes no rows to transform output. The default is 1: a transformer imposing no per-vintage minimum emits output for any non-empty vintage. Implementations that consume rows within a vintage, or that need a minimum number of rows to fit on, report their own larger value.

This is deliberately not named observation_horizon. On BaseActualTransformer that name means a buffer carried between calls, sized so the next transform has enough history behind it. A forecast transformer keeps no such buffer: each vintage is self-contained, so this quantity is a length requirement within one vintage rather than a memory depth across calls.

A forecaster holding this transformer in its forecast_transformer slot asserts forecasting_horizon >= min_vintage_rows at fit, because a served vintage spans the forecasting horizon.

Returns
Type Description
int

Smallest vintage length yielding non-empty output, at least 1.

Raises
Type Description
NotFittedError

If the transformer has not been fitted yet.

fit(X, y=None, **params)

Fit the transformer to an X_forecast frame.

Parameters
Name Type Description Default
X DataFrame

Input X_forecast frame with "vintage_time" and "time" columns and one or more feature columns.

required
y DataFrame or None

Ignored. Present for API compatibility.

None
**params dict

Metadata to route to nested estimators.

{}
Returns
Type Description
self

The fitted transformer instance.

Raises
Type Description
ValueError

If X is missing the "vintage_time" or "time" index columns.

Source Code
Source code in src/yohou/base/forecast_transformer.py
@_fit_context(prefer_skip_nested_validation=True)
def fit(self, X: pl.DataFrame, y: pl.DataFrame | None = None, **params) -> "BaseForecastTransformer":
    """Fit the transformer to an ``X_forecast`` frame.

    Parameters
    ----------
    X : pl.DataFrame
        Input ``X_forecast`` frame with ``"vintage_time"`` and ``"time"``
        columns and one or more feature columns.
    y : pl.DataFrame or None, default=None
        Ignored.  Present for API compatibility.
    **params : dict
        Metadata to route to nested estimators.

    Returns
    -------
    self
        The fitted transformer instance.

    Raises
    ------
    ValueError
        If ``X`` is missing the ``"vintage_time"`` or ``"time"`` index
        columns.

    """
    X = _validate_forecast_transformer_data(self, X, reset=True)
    self._fit(X, y)
    return self

transform(X, **params)

Transform an X_forecast frame.

Parameters
Name Type Description Default
X DataFrame

Input X_forecast frame with "vintage_time" and "time" columns and one or more feature columns.

required
**params dict

Metadata to route to nested estimators.

{}
Returns
Type Description
DataFrame

Transformed X_forecast frame with the "vintage_time" and "time" index columns preserved.

Raises
Type Description
NotFittedError

If the transformer has not been fitted yet.

ValueError

If X is missing an index column or its feature columns differ from those seen during fit.

Source Code
Source code in src/yohou/base/forecast_transformer.py
def transform(self, X: pl.DataFrame, **params) -> pl.DataFrame:
    """Transform an ``X_forecast`` frame.

    Parameters
    ----------
    X : pl.DataFrame
        Input ``X_forecast`` frame with ``"vintage_time"`` and ``"time"``
        columns and one or more feature columns.
    **params : dict
        Metadata to route to nested estimators.

    Returns
    -------
    pl.DataFrame
        Transformed ``X_forecast`` frame with the ``"vintage_time"`` and
        ``"time"`` index columns preserved.

    Raises
    ------
    sklearn.exceptions.NotFittedError
        If the transformer has not been fitted yet.
    ValueError
        If ``X`` is missing an index column or its feature columns differ
        from those seen during ``fit``.

    """
    check_is_fitted(self, ["X_schema_", "feature_names_in_", "n_features_in_"])
    X = _validate_forecast_transformer_data(self, X, reset=False)
    return self._transform(X)