Skip to content

Commit

Permalink
[ENH] Created _DelegatedTransformer (#2612)
Browse files Browse the repository at this point in the history
Related to convo in #2603, simpler alternative to #2570

Creates a `_DelegatedTransformer`. Design and use are identical to `_DelegatedForecaster`.
  • Loading branch information
miraep8 committed May 10, 2022
1 parent 1f1fdcf commit 2a0df3f
Showing 1 changed file with 168 additions and 0 deletions.
168 changes: 168 additions & 0 deletions sktime/transformations/_delegate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
# -*- coding: utf-8 -*-
"""Delegator mixin that delegates all methods to wrapped transformer.
Useful for building estimators where all but one or a few methods are delegated.
For that purpose, inherit from this estimator and then override only the methods
that are not delegated.
"""
# copyright: sktime developers, BSD-3-Clause License (see LICENSE file)

__author__ = ["miraep8"]
__all__ = ["_DelegatedTransformer"]

from sktime.transformations.base import BaseTransformer


class _DelegatedTransformer(BaseTransformer):
"""Delegator mixin that delegates all methods to wrapped transformer.
Delegates inner transformer methods to a wrapped estimator.
Wrapped estimator is value of attribute with name self._delegate_name.
By default, this is "estimator_", i.e., delegates to self.estimator_
To override delegation, override _delegate_name attribute in child class.
Delegates the following inner underscore methods:
_fit, _transform, _inverse_transform, _update
Does NOT delegate get_params, set_params.
get_params, set_params will hence use one additional nesting level by default.
Does NOT delegate or copy tags, this should be done in a child class if required.
"""

_delegate_name = "estimator_"

def _get_delegate(self):
return getattr(self, self._delegate_name)

def _fit(self, X, y=None):
"""Fit wrapped transformer to X, optionally to y.
Parameters
----------
X : Series or Panel, any supported mtype
Data to fit transform to, of python type as follows:
Series: pd.Series, pd.DataFrame, or np.ndarray (1D or 2D)
Panel: pd.DataFrame with 2-level MultiIndex, list of pd.DataFrame,
nested pd.DataFrame, or pd.DataFrame in long/wide format
subject to sktime mtype format specifications, for further details see
examples/AA_datatypes_and_datasets.ipynb
y : Series or Panel, default=None
Additional data, e.g., labels for transformation
Returns
-------
self : a fitted instance of the estimator
"""
estimator = self._get_delegate()
estimator.fit(X=X, y=y)
return self

def _transform(self, X, y=None):
"""Use wrapped transformer to transform X and return a transformed version.
Parameters
----------
X : Series or Panel, any supported mtype
Data to be transformed, of python type as follows:
Series: pd.Series, pd.DataFrame, or np.ndarray (1D or 2D)
Panel: pd.DataFrame with 2-level MultiIndex, list of pd.DataFrame,
nested pd.DataFrame, or pd.DataFrame in long/wide format
subject to sktime mtype format specifications, for further details see
examples/AA_datatypes_and_datasets.ipynb
y : Series or Panel, default=None
Additional data, e.g., labels for transformation
Returns
-------
transformed version of X
type depends on type of X and scitype:transform-output tag:
| | `transform` | |
| `X` | `-output` | type of return |
|----------|--------------|------------------------|
| `Series` | `Primitives` | `pd.DataFrame` (1-row) |
| `Panel` | `Primitives` | `pd.DataFrame` |
| `Series` | `Series` | `Series` |
| `Panel` | `Series` | `Panel` |
| `Series` | `Panel` | `Panel` |
instances in return correspond to instances in `X`
combinations not in the table are currently not supported
Explicitly, with examples:
if `X` is `Series` (e.g., `pd.DataFrame`) and `transform-output` is `Series`
then the return is a single `Series` of the same mtype
Example: detrending a single series
if `X` is `Panel` (e.g., `pd-multiindex`) and `transform-output` is `Series`
then the return is `Panel` with same number of instances as `X`
(the transformer is applied to each input Series instance)
Example: all series in the panel are detrended individually
if `X` is `Series` or `Panel` and `transform-output` is `Primitives`
then the return is `pd.DataFrame` with as many rows as instances in `X`
Example: i-th row of the return has mean and variance of the i-th series
if `X` is `Series` and `transform-output` is `Panel`
then the return is a `Panel` object of type `pd-multiindex`
Example: i-th instance of the output is the i-th window running over `X`
"""
estimator = self._get_delegate()
return estimator.transform(X, y=y)

def _inverse_transform(self, X, y=None):
"""Use wrapped transformer to inverse transform X and return.
Currently it is assumed that only transformers with tags
"scitype:transform-input"="Series", "scitype:transform-output"="Series",
have an inverse_transform.
Parameters
----------
X : Series or Panel, any supported mtype
Data to be inverse transformed, of python type as follows:
Series: pd.Series, pd.DataFrame, or np.ndarray (1D or 2D)
Panel: pd.DataFrame with 2-level MultiIndex, list of pd.DataFrame,
nested pd.DataFrame, or pd.DataFrame in long/wide format
subject to sktime mtype format specifications, for further details see
examples/AA_datatypes_and_datasets.ipynb
y : Series or Panel, default=None
Additional data, e.g., labels for transformation
Returns
-------
inverse transformed version of X
of the same type as X, and conforming to mtype format specifications
"""
estimator = self._get_delegate()
return estimator.inverse_transform(X=X, y=y)

def _update(self, X, y=None, update_params=True):
"""Update wrapped transformer with X, optionally y.
State required:
Requires state to be "fitted".
Writes to self:
May update fitted model attributes ending in for the delegated
transformer "_" via update.
Parameters
----------
X : Series or Panel, any supported mtype
Data to fit transform to, of python type as follows:
Series: pd.Series, pd.DataFrame, or np.ndarray (1D or 2D)
Panel: pd.DataFrame with 2-level MultiIndex, list of pd.DataFrame,
nested pd.DataFrame, or pd.DataFrame in long/wide format
subject to sktime mtype format specifications, for further details see
examples/AA_datatypes_and_datasets.ipynb
y : Series or Panel, default=None
Additional data, e.g., labels for transformation
update_params : bool, default=True
whether the model is updated. Yes if true, if false, simply skips call.
argument exists for compatibility with forecasting module.
Returns
-------
self : a fitted instance of the estimator
"""
estimator = self._get_delegate()
estimator.update(y=y, X=X, update_params=update_params)
return self

0 comments on commit 2a0df3f

Please sign in to comment.