def transform(self, Z, X=None): """Transform data. Parameters ---------- Z : pd.Series Series to transform. X : pd.DataFrame, optional (default=None) Exogenous data used in transformation. Returns ------- theta_lines: ndarray or pd.DataFrame Transformed series: single Theta-line or a pd.DataFrame of shape: len(Z)*len(self.theta). """ self.check_is_fitted() z = check_series(Z, enforce_univariate=True) theta = _check_theta(self.theta) forecaster = PolynomialTrendForecaster() forecaster.fit(z) fh = ForecastingHorizon(z.index, is_relative=False) trend = forecaster.predict(fh) theta_lines = np.zeros((z.shape[0], len(theta))) for i, theta in enumerate(theta): theta_lines[:, i] = _theta_transform(z, trend, theta) if isinstance(self.theta, (float, int)): return pd.Series(theta_lines.flatten(), index=z.index) else: return pd.DataFrame(theta_lines, columns=self.theta, index=z.index)
def _transform(self, X, y=None): """Transform X and return a transformed version. private _transform containing the core logic, called from transform Parameters ---------- X : pd.Series or pd.DataFrame Data to be transformed y : ignored argument for interface compatibility Additional data, e.g., labels for transformation Returns ------- theta_lines: pd.Series or pd.DataFrame Transformed series pd.Series, with single Theta-line, if self.theta is float pd.DataFrame of shape: [len(X), len(self.theta)], if self.theta is tuple """ z = X theta = _check_theta(self.theta) forecaster = PolynomialTrendForecaster() forecaster.fit(z) fh = ForecastingHorizon(z.index, is_relative=False) trend = forecaster.predict(fh) theta_lines = np.zeros((z.shape[0], len(theta))) for i, theta in enumerate(theta): theta_lines[:, i] = _theta_transform(z, trend, theta) if isinstance(self.theta, (float, int)): return pd.Series(theta_lines.flatten(), index=z.index) else: return pd.DataFrame(theta_lines, columns=self.theta, index=z.index)
def transform(self, Z, X=None): """Transform data. Returns a transformed version of Z. Parameters ---------- Z : pd.Series, pd.DataFrame Returns ------- Z : pd.Series, pd.DataFrame Transformed time series(es). """ self.check_is_fitted() self._check_method() Z = check_series(Z) # replace missing_values with np.nan if self.missing_values: Z = Z.replace(to_replace=self.missing_values, value=np.nan) if self.method == "random": if isinstance(Z, pd.DataFrame): for col in Z: Z[col] = Z[col].apply(lambda i: self._get_random(Z[col]) if np.isnan(i) else i) else: Z = Z.apply(lambda i: self._get_random(Z) if np.isnan(i) else i) elif self.method == "constant": Z = Z.fillna(value=self.value) elif self.method in ["backfill", "bfill", "pad", "ffill"]: Z = Z.fillna(method=self.method) elif self.method in ["drift", "forecaster"]: if self.method == "forecaster": forecaster = self.forecaster else: forecaster = PolynomialTrendForecaster(degree=1) # in-sample forecasting horizon fh_ins = -np.arange(len(Z)) # fill NaN before fitting with ffill and backfill (heuristic) Z = Z.fillna(method="ffill").fillna(method="backfill") # multivariate if isinstance(Z, pd.DataFrame): for col in Z: forecaster.fit(y=Z[col]) Z_pred = forecaster.predict(fh=fh_ins) Z[col] = Z[col].fillna(value=Z_pred) # univariate else: forecaster.fit(y=Z) Z_pred = forecaster.predict(fh=fh_ins) Z = Z.fillna(value=Z_pred) elif self.method == "mean": Z = Z.fillna(value=Z.mean()) elif self.method == "median": Z = Z.fillna(value=Z.median()) elif self.method in ["nearest", "linear"]: Z = Z.interpolate(method=self.method) else: raise ValueError(f"method {self.method} not available") # fill first/last elements of series, # as some methods (e.g. "linear") cant impute those Z = Z.fillna(method="ffill").fillna(method="backfill") return Z