Source code for etna.transforms.math.log

import warnings
from math import log
from math import pow
from typing import Optional

import pandas as pd

from etna.transforms.base import PerSegmentWrapper
from etna.transforms.base import Transform
from etna.transforms.utils import match_target_quantiles


[docs]class _OneSegmentLogTransform(Transform): """Instance of this class applies logarithmic transformation to one segment data.""" def __init__(self, in_column: str, base: int = 10, inplace: bool = True, out_column: Optional[str] = None): """ Init OneSegmentLogTransform. Parameters ---------- in_column: column to apply transform. base: base of logarithm to apply to series. inplace: * if True, apply logarithm transformation inplace to in_column, * if False, add transformed column to dataset. out_column: name of added column. If not given, use ``self.__repr__()`` """ self.base = base self.in_column = in_column self.inplace = inplace self.out_column = out_column
[docs] def fit(self, df: pd.Series) -> "_OneSegmentLogTransform": """Fit preprocess method, does nothing in OneSegmentLogTransform case. Returns ------- : """ return self
[docs] def transform(self, df: pd.DataFrame) -> pd.DataFrame: """Apply log transformation to series from df. Parameters ---------- df: series to transform Returns ------- : transformed series Raises ------ ValueError: if given series contains negative samples """ if (df[self.in_column] < 0).any(): raise ValueError("LogPreprocess can be applied only to non-negative series") result_df = df.copy() result_df[self.out_column] = result_df[self.in_column].apply(lambda x: log(x + 1, self.base)) return result_df
[docs] def inverse_transform(self, df: pd.DataFrame) -> pd.DataFrame: """Apply inverse transformation to the series from df. Parameters ---------- df: series to transform Returns ------- : transformed series """ result_df = df.copy() if self.inplace: result_df[self.in_column] = result_df[self.out_column].apply(lambda x: pow(self.base, x) - 1) if self.in_column == "target": quantiles = match_target_quantiles(set(result_df.columns)) for quantile_column_nm in quantiles: result_df[quantile_column_nm] = result_df[quantile_column_nm].apply(lambda x: pow(self.base, x) - 1) return result_df
[docs]class LogTransform(PerSegmentWrapper): """LogTransform applies logarithm transformation for given series.""" def __init__(self, in_column: str, base: int = 10, inplace: bool = True, out_column: Optional[str] = None): """Init LogTransform. Parameters ---------- in_column: column to apply transform base: base of logarithm to apply to series inplace: * if True, apply logarithm transformation inplace to in_column, * if False, add column add transformed column to dataset out_column: name of added column. If not given, use ``self.__repr__()`` """ self.in_column = in_column self.base = base self.inplace = inplace self.out_column = out_column if self.inplace and out_column: warnings.warn("Transformation will be applied inplace, out_column param will be ignored") if self.inplace: result_out_column = self.in_column elif out_column: result_out_column = out_column else: result_out_column = self.__repr__() super().__init__( transform=_OneSegmentLogTransform( in_column=in_column, base=base, inplace=inplace, out_column=result_out_column ) )
__all__ = ["LogTransform"]