Module futureexpert.plot
Contains all the functionality to plot the checked in time series and the forecast and backtesting results.
Functions
def create_multiple_yaxis(count_y_axis: int) ‑> dict[str, typing.Any]-
Expand source code
def create_multiple_yaxis(count_y_axis: int) -> dict[str, Any]: """Create multiple yaxis for interactive plots. Parameters ---------- count_y_axis: builtins.int Number of how many yaxis are needed. return: builtins.dict[builtins.str, typing.Any] """ return { f"yaxis{'' if ax == 0 else ax+1}": { "showticklabels": False, "overlaying": None if ax == 0 else "y", } for ax in range(count_y_axis) }Create multiple yaxis for interactive plots.
Parameters
count_y_axis:builtins.int- Number of how many yaxis are needed.
return:builtins.dict[builtins.str, typing.Any]
def create_subtitle(model: Model,
is_discarded: bool) ‑> str-
Expand source code
def create_subtitle(model: Model, is_discarded: bool) -> str: """Create subtitle for backtesting and forecasting plots. Parameters ---------- model: futureexpert.forecast.Model Model. is_discarded: builtins.bool Is Model part of the active ranking or not. return: builtins.str """ if not is_discarded and model.model_selection.ranking: subtitle = f'using {model.model_name} (Rank {model.model_selection.ranking.rank_position})' else: subtitle = f'using {model.model_name} (discarded)' return subtitleCreate subtitle for backtesting and forecasting plots.
Parameters
model:Model- Model.
is_discarded:builtins.bool- Is Model part of the active ranking or not.
return:builtins.str
def filter_models(models: list[Model],
ranks: list[int] | None = [1],
model_names: list[str] | None = None) ‑> list[Model]-
Expand source code
def filter_models(models: list[Model], ranks: Optional[list[int]] = [1], model_names: Optional[list[str]] = None,) -> list[Model]: """Filter models based on the given criteria. Parameters ---------- models: builtins.list[futureexpert.forecast.Model] List of models. model_names: typing.Optional[builtins.list[builtins.str]] Names of the models to filtered by. ranks: typing.Optional[builtins.list[builtins.int]] Ranks of the models to filtered by. return: builtins.list[futureexpert.forecast.Model] """ if model_names: models = [mo for mo in models if mo.model_name in model_names] if ranks: models = [mo for mo in models if mo.model_selection.ranking and mo.model_selection.ranking.rank_position in ranks] return modelsFilter models based on the given criteria.
Parameters
def plot_backtesting(result: ForecastResult,
iteration: int = 1,
plot_last_x_data_points_only: int | None = None,
model_names: list[str] | None = None,
ranks: list[int] | None = [1],
plot_prediction_intervals: bool = True,
plot_outliers: bool = False,
plot_change_points: bool = False,
plot_replaced_missings: bool = False,
plot_covariates: bool = False,
as_interactive: bool = False) ‑> None-
Expand source code
def plot_backtesting(result: ForecastResult, iteration: int = 1, plot_last_x_data_points_only: Optional[int] = None, model_names: Optional[list[str]] = None, ranks: Optional[list[int]] = [1], plot_prediction_intervals: bool = True, plot_outliers: bool = False, plot_change_points: bool = False, plot_replaced_missings: bool = False, plot_covariates: bool = False, as_interactive: bool = False) -> None: """Plots actuals and backtesting results from a single time series. Parameters ---------- result: futureexpert.forecast.ForecastResult Forecasting and backtesting results of a single time series and model. iteration: builtins.int Iteration of the backtesting forecast. Starting from 1. plot_last_x_data_points_only: typing.Optional[builtins.int] Number of data points of the actuals that should be shown in the plot. model_names: typing.Optional[builtins.list[builtins.str]] Names of the models to plot. ranks: typing.Optional[builtins.list[builtins.int]] Ranks of the models to plot. If this filter is active no discarded models are plotted. plot_prediction_intervals: builtins.bool Shows prediction intervals. plot_outliers: builtins.bool Shows outlieres and replacement values. plot_change_points: builtins.bool Shows change point like level shifts and few observations. plot_replaced_missings: builtins.bool Shows replaced missing values. plot_covariates: builtins.bool Shows the covariates that where used in the model. as_interactive: builtins.bool Plots the data in an interactive plot or as static image. return: builtins.NoneType """ if ranks and model_names: logger.warning('Both filters `ranks` and `model_names` are used. This could cause no results.') if iteration <= 0: raise ValueError('`iteration` needs to be a positive Integer.') plot_models = filter_models(result.models, ranks, model_names) discarded_plot_models = [] if not ranks: discarded_plot_models = filter_models(result.discarded_models, ranks, model_names) df_ac = _prepare_actuals(result.input.actuals, plot_last_x_data_points_only) characteristics = _prepare_characteristics(result, df_ac) plot_few_observations = [] if plot_change_points: change_points = characteristics.change_points or [] few_observations = [copy.deepcopy(x) for x in change_points if x.change_point_type.startswith('FEW_OBS')] plot_few_observations = _calculate_few_observation_borders(df_ac.date.tolist(), few_observations) level_shifts = [x for x in change_points if x.change_point_type == 'LEVEL_SHIFT'] df_ac = _add_level_shifts(df_ac, level_shifts) if plot_outliers: outliers = characteristics.outliers or [] df_ac = _add_outliers(df_ac, outliers, result.changed_values) df_ac = _add_changed_start_date(df_ac, result.changed_start_date) missing_borders = [] if plot_replaced_missings: df_ac = _add_replaced_missings(df_ac, result.changed_values) if 'replaced_missing' in df_ac.columns: missing_borders = _calculate_replaced_missing_borders(df_ac) if len(plot_models) == 0 and len(discarded_plot_models) == 0: logger.warning('No models left for plotting with the current filter. Adjust `ranks` or `model_names`') for i, model in enumerate(chain(plot_models, discarded_plot_models)): is_discarded = False if i < len(plot_models) else True if not model.model_selection.backtesting: logger.warning(f'Cannot create backtesting plot, {model.model_name} has no backtesting results available.') continue df_bt = _prepare_backtesting(model, iteration) title = f'Backtesting of {result.input.actuals.name} - Iteration: {iteration}' subtitle = create_subtitle(model, is_discarded) if plot_covariates and len(model.covariates) > 0: df_concat = _add_covariates(df_ac, model.covariates, result.input.covariates, _calculate_max_covariate_date(result.input.actuals.granularity, df_ac.date.max())) else: df_concat = df_ac if as_interactive: _create_interactive_backtesting_plot(title=title, subtitle=subtitle, df_concat=df_concat, df_bt=df_bt, missing_borders=missing_borders, plot_prediction_intervals=plot_prediction_intervals, plot_few_observations=plot_few_observations) else: _create_static_backtesting_plot(title=title, subtitle=subtitle, df_concat=df_concat, df_bt=df_bt, plot_prediction_intervals=plot_prediction_intervals, plot_few_observations=plot_few_observations)Plots actuals and backtesting results from a single time series.
Parameters
result:ForecastResult- Forecasting and backtesting results of a single time series and model.
iteration:builtins.int- Iteration of the backtesting forecast. Starting from 1.
plot_last_x_data_points_only:typing.Optional[builtins.int]- Number of data points of the actuals that should be shown in the plot.
model_names:typing.Optional[builtins.list[builtins.str]]- Names of the models to plot.
ranks:typing.Optional[builtins.list[builtins.int]]- Ranks of the models to plot. If this filter is active no discarded models are plotted.
plot_prediction_intervals:builtins.bool- Shows prediction intervals.
plot_outliers:builtins.bool- Shows outlieres and replacement values.
plot_change_points:builtins.bool- Shows change point like level shifts and few observations.
plot_replaced_missings:builtins.bool- Shows replaced missing values.
plot_covariates:builtins.bool- Shows the covariates that where used in the model.
as_interactive:builtins.bool- Plots the data in an interactive plot or as static image.
return:builtins.NoneType
def plot_forecast(result: ForecastResult,
plot_last_x_data_points_only: int | None = None,
model_names: list[str] | None = None,
ranks: list[int] | None = [1],
plot_prediction_intervals: bool = True,
plot_outliers: bool = False,
plot_change_points: bool = False,
plot_replaced_missings: bool = False,
plot_covariates: bool = False,
as_interactive: bool = False) ‑> None-
Expand source code
def plot_forecast(result: ForecastResult, plot_last_x_data_points_only: Optional[int] = None, model_names: Optional[list[str]] = None, ranks: Optional[list[int]] = [1], plot_prediction_intervals: bool = True, plot_outliers: bool = False, plot_change_points: bool = False, plot_replaced_missings: bool = False, plot_covariates: bool = False, as_interactive: bool = False) -> None: """Plots actuals and forecast from a single time series. Parameters ---------- forecasts Forecasting results of a single time series and model. plot_last_x_data_points_only: typing.Optional[builtins.int] Number of data points of the actuals that should be shown in the plot. model_names: typing.Optional[builtins.list[builtins.str]] Names of the models to plot. ranks: typing.Optional[builtins.list[builtins.int]] Ranks of the models to plot. If this filter is active no discarded models are plotted. plot_prediction_intervals: builtins.bool Shows prediction intervals. plot_outliers: builtins.bool Shows outlieres and replacement values. plot_change_points: builtins.bool Shows change point like level shifts and few observations. plot_replaced_missings: builtins.bool Shows replaced missing values. plot_covariates: builtins.bool Shows the covariates that where used in the model. as_interactive: builtins.bool Plots the data in an interactive plot or as static image. result: futureexpert.forecast.ForecastResult return: builtins.NoneType """ if ranks and model_names: logger.warning('Both filters `ranks` and `model_names` are used. This could cause no results.') df_ac = _prepare_actuals(actuals=result.input.actuals, plot_last_x_data_points_only=plot_last_x_data_points_only) characteristics = _prepare_characteristics(result, df_ac) name = result.input.actuals.name plot_models = filter_models(result.models, ranks, model_names) discarded_plot_models = [] if not ranks: discarded_plot_models = filter_models(result.discarded_models, ranks, model_names) plot_few_observations = [] if plot_change_points: change_points = characteristics.change_points or [] few_observations = [copy.deepcopy(x) for x in change_points if x.change_point_type.startswith('FEW_OBS')] plot_few_observations = _calculate_few_observation_borders(df_ac.date.tolist(), few_observations) level_shifts = [x for x in change_points if x.change_point_type == 'LEVEL_SHIFT'] df_ac = _add_level_shifts(df_ac, level_shifts) if plot_outliers: outliers = characteristics.outliers or [] df_ac = _add_outliers(df_ac, outliers, result.changed_values) df_ac = _add_changed_start_date(df_ac, result.changed_start_date) missing_borders = [] if plot_replaced_missings: df_ac = _add_replaced_missings(df_ac, result.changed_values) if 'replaced_missing' in df_ac.columns: missing_borders = _calculate_replaced_missing_borders(df_ac) if len(plot_models) == 0 and len(discarded_plot_models) == 0: logger.warning('No models left for plotting with the current filter. Adjust `ranks` or `model_names`.') for i, model in enumerate(chain(plot_models, discarded_plot_models)): is_discarded = False if i < len(plot_models) else True if not model.forecasts: logger.warning(f'Cannot create forecast plot, {model.model_name} has no forecasting results available.') continue df_concat = _add_forecast(df_ac, model) title = f'Forecast for {name}' subtitle = create_subtitle(model, is_discarded) if plot_covariates and len(model.covariates) > 0: df_concat = _add_covariates(df_concat, model.covariates, result.input.covariates, df_concat.date.max()) if as_interactive: _create_interactive_forecast_plot(title=title, subtitle=subtitle, df_concat=df_concat, missing_borders=missing_borders, plot_prediction_intervals=plot_prediction_intervals, plot_few_observations=plot_few_observations) else: _create_static_forecast_plot(title=title, subtitle=subtitle, df_concat=df_concat, plot_prediction_intervals=plot_prediction_intervals, plot_few_observations=plot_few_observations)Plots actuals and forecast from a single time series.
Parameters
forecasts- Forecasting results of a single time series and model.
plot_last_x_data_points_only:typing.Optional[builtins.int]- Number of data points of the actuals that should be shown in the plot.
model_names:typing.Optional[builtins.list[builtins.str]]- Names of the models to plot.
ranks:typing.Optional[builtins.list[builtins.int]]- Ranks of the models to plot. If this filter is active no discarded models are plotted.
plot_prediction_intervals:builtins.bool- Shows prediction intervals.
plot_outliers:builtins.bool- Shows outlieres and replacement values.
plot_change_points:builtins.bool- Shows change point like level shifts and few observations.
plot_replaced_missings:builtins.bool- Shows replaced missing values.
plot_covariates:builtins.bool- Shows the covariates that where used in the model.
as_interactive:builtins.bool- Plots the data in an interactive plot or as static image.
result:ForecastResultreturn:builtins.NoneType
def plot_scenario(scenario: Scenario,
plot_last_x_data_points_only: int | None = None,
as_interactive: bool = False) ‑> None-
Expand source code
def plot_scenario(scenario: Scenario, plot_last_x_data_points_only: Optional[int] = None, as_interactive: bool = False) -> None: """Plots a scenario with covariate time series and high/low projections. Parameters ---------- scenario: futureexpert.shaper.Scenario Scenario containing covariate time series with high and low projections. plot_last_x_data_points_only: typing.Optional[builtins.int] Number of data points of the covariate that should be shown in the plot. as_interactive: builtins.bool Plots the data in an interactive plot or as static image. return: builtins.NoneType """ assert isinstance(scenario.ts, Covariate), 'Cannot plot scenario with CovariateRef instance.' cov_name = scenario.ts.ts.name lag = scenario.ts.lag title = f'Scenario: Covariate {cov_name} (lag: {lag})' df_cov = _prepare_actuals(scenario.ts.ts, plot_last_x_data_points_only) if as_interactive: _create_interactive_scenario_plot(scenario, title, df_cov) else: _create_static_scenario_plot(scenario, title, df_cov)Plots a scenario with covariate time series and high/low projections.
Parameters
scenario:Scenario- Scenario containing covariate time series with high and low projections.
plot_last_x_data_points_only:typing.Optional[builtins.int]- Number of data points of the covariate that should be shown in the plot.
as_interactive:builtins.bool- Plots the data in an interactive plot or as static image.
return:builtins.NoneType
def plot_shaper_results(result: ShaperResult,
plot_last_x_data_points_only: int | None = None,
plot_prediction_intervals: bool = True,
as_interactive: bool = False) ‑> None-
Expand source code
def plot_shaper_results(result: ShaperResult, plot_last_x_data_points_only: Optional[int] = None, plot_prediction_intervals: bool = True, as_interactive: bool = False) -> None: """Plots the shaper forecast results including high, low, and optional custom scenarios. Parameters ---------- result: futureexpert.shaper.ShaperResult ShaperResult containing actuals and the different scenario forecasts. plot_last_x_data_points_only: typing.Optional[builtins.int] Number of data points of the actuals that should be shown in the plot. plot_prediction_intervals: builtins.bool Shows prediction intervals for each forecast scenario. as_interactive: builtins.bool Plots the data in an interactive plot or as static image. return: builtins.NoneType """ title = f'Shaper Forecast for {result.input.actuals.name}' df_ac = _prepare_actuals(result.input.actuals, plot_last_x_data_points_only) last_actual_date = df_ac.date.iloc[-1] last_actual_value = df_ac.actuals.iloc[-1] fc_high_df = _forecast_values_to_df(result.forecast_high, last_actual_date, last_actual_value) fc_low_df = _forecast_values_to_df(result.forecast_low, last_actual_date, last_actual_value) fc_custom_df = (_forecast_values_to_df(result.forecast_custom, last_actual_date, last_actual_value) if result.forecast_custom else None) if as_interactive: _create_interactive_shaper_results_plot(result, title, df_ac, fc_high_df, fc_low_df, fc_custom_df, plot_last_x_data_points_only, plot_prediction_intervals) else: _create_static_shaper_results_plot(result, title, df_ac, fc_high_df, fc_low_df, fc_custom_df, plot_last_x_data_points_only, plot_prediction_intervals)Plots the shaper forecast results including high, low, and optional custom scenarios.
Parameters
result:ShaperResult- ShaperResult containing actuals and the different scenario forecasts.
plot_last_x_data_points_only:typing.Optional[builtins.int]- Number of data points of the actuals that should be shown in the plot.
plot_prediction_intervals:builtins.bool- Shows prediction intervals for each forecast scenario.
as_interactive:builtins.bool- Plots the data in an interactive plot or as static image.
return:builtins.NoneType
def plot_time_series(ts: TimeSeries,
covariate: list[Covariate] | None = None,
plot_last_x_data_points_only: int | None = None,
as_interactive: bool = False) ‑> None-
Expand source code
def plot_time_series(ts: TimeSeries, covariate: Optional[list[Covariate]] = None, plot_last_x_data_points_only: Optional[int] = None, as_interactive: bool = False) -> None: """Plots actuals from a single time series. Optional a Covariate can be plotted next to it. Parameters ---------- ts: futureexpert.shared_models.TimeSeries time series data covariate: typing.Optional[builtins.list[futureexpert.shared_models.Covariate]] covariate data plot_last_x_data_points_only: typing.Optional[builtins.int] Number of data points of the actuals that should be shown in the plot. as_interactive: builtins.bool Plots the data as an interactive plot or as static image. return: builtins.NoneType """ df_ac = _prepare_actuals(actuals=ts, plot_last_x_data_points_only=plot_last_x_data_points_only) name = ts.name if covariate: df_ac = _add_covariates(df_ac, covariate, covariate, _calculate_max_covariate_date(ts.granularity, df_ac.date.max())) if as_interactive: _create_interactive_time_series_plot(df_ac, name) else: _create_static_time_series_plot(df_ac, name)Plots actuals from a single time series. Optional a Covariate can be plotted next to it.
Parameters
ts:TimeSeries- time series data
covariate:typing.Optional[builtins.list[Covariate]]- covariate data
plot_last_x_data_points_only:typing.Optional[builtins.int]- Number of data points of the actuals that should be shown in the plot.
as_interactive:builtins.bool- Plots the data as an interactive plot or as static image.
return:builtins.NoneType