Source code for ibex._function_transformer
from __future__ import absolute_import
from six import string_types
import pandas as pd
from sklearn import base
from ._base import FrameMixin
from ._utils import verify_x_type, verify_y_type
__all__ = []
def _process_cols(cols):
if cols is None:
return None
return [cols] if isinstance(cols, string_types) else list(cols)
# Tmp Ami - add kw_args, inverse shit
[docs]class FunctionTransformer(base.BaseEstimator, base.TransformerMixin, FrameMixin):
"""
Transforms using a function.
Arguments:
func: One of:
* ``None``
* a callable
* a step
in_cols: One of:
* ``None``
* a string
* a list of strings
out_cols:
pass_y: Boolean indicating whether to pass the ``y`` argument to
kw_args: Keyword arguments.
Returns:
An :py:class:`sklearn.preprocessing.FunctionTransformer` object.
"""
def __init__(self, func=None, in_cols=None, out_cols=None, pass_y=None, kw_args=None):
FrameMixin.__init__(self)
params = {
'func': func,
'in_cols': in_cols,
'out_cols': out_cols,
'pass_y': pass_y,
'kw_args': kw_args,
}
self.set_params(**params)
[docs] def fit(self, X, y=None):
"""
Fits the transformer using ``X`` (and possibly ``y``).
Returns:
``self``
"""
verify_x_type(X)
verify_y_type(y)
self.x_columns = X.columns
if self.in_cols is not None:
Xt = X[self.in_cols]
else:
Xt = X
if self.func is None:
return self
if isinstance(self.func, FrameMixin):
if self.pass_y:
self.func.fit(Xt, y)
else:
self.func.fit(Xt)
return self
[docs] def fit_transform(self, X, y=None):
"""
Fits the transformer using ``X`` (and possibly ``y``), and transforms, in one
step if possible
Returns:
Transformed data.
"""
verify_x_type(X)
verify_y_type(y)
if not isinstance(self.func, FrameMixin) or not hasattr(self.func, 'fit_transform'):
if self.pass_y:
return self.fit(X, y).transform(X, y)
return self.fit(X).transform(X)
self.x_columns = X.columns
Xt = X[self.x_columns]
in_cols = _process_cols(self.in_cols)
if in_cols is not None:
Xt = Xt[in_cols]
if self.func is None:
res = Xt
elif isinstance(self.func, FrameMixin):
if self.pass_y:
res = self.func.fit_transform(Xt, y)
else:
res = self.func.fit_transform(Xt)
else:
if self.kw_args is not None:
res = pd.DataFrame(self.func(Xt, **self.kw_args), index=Xt.index)
else:
res = pd.DataFrame(self.func(Xt), index=Xt.index)
return self.__process_res(Xt, res)
[docs] def transform(self, X, y=None):
"""
Returns:
Transformed data.
"""
verify_x_type(X)
verify_y_type(y)
Xt = X[self.x_columns]
in_cols = _process_cols(self.in_cols)
if in_cols is not None:
Xt = Xt[in_cols]
if self.func is None:
res = Xt
elif isinstance(self.func, FrameMixin):
if self.pass_y:
res = self.func.transform(Xt, y)
else:
res = self.func.transform(Xt)
else:
if self.kw_args is not None:
res = pd.DataFrame(self.func(Xt, **self.kw_args), index=Xt.index)
else:
res = pd.DataFrame(self.func(Xt), index=Xt.index)
return self.__process_res(Xt, res)
def __process_res(self, Xt, res):
in_cols = _process_cols(self.in_cols)
out_cols = _process_cols(self.out_cols)
if out_cols is not None:
res_cols = out_cols
elif in_cols is not None:
res_cols = in_cols
else:
res_cols = Xt.columns
res = res.copy()
res.columns = res_cols
return res