Abacus Core Mixins: Plotting Scenario (plotting_scenario.py)

This module provides the ScenarioPlottingMixin class, designed to be inherited by Marketing Mix Model (MMM) classes in Abacus. It offers methods for visualising the results of budget optimisation scenarios and plotting the direct response curves for marketing channels based on the fitted model.

ScenarioPlottingMixin Class

This mixin assumes the inheriting class provides attributes and methods like:

  • X: The original input DataFrame used for training.

  • channel_columns: List of channel names.

  • compute_channel_contribution_original_scale(): A method (likely from ContributionMixin) that returns channel contributions in the original target scale.

  • _estimate_budget_contribution_fit(): A method (likely from OptimizationMixin) to estimate contribution bounds for a given budget.

Methods

plot_budget_scenarios

def plot_budget_scenarios(
    self, *, base_data: Dict, method: str = "sigmoid", **kwargs: Any
) -> plt.Figure:

(Experimental) Plots side-by-side bar charts comparing budget allocation and resulting contribution across different scenarios.

This visualisation helps compare the initial budget/contribution (base_data) with one or more alternative scenarios (scenarios_data passed via kwargs). For the contribution plot, it also shows estimated 90% credible intervals based on fitting a specified saturation curve (method) to the posterior contribution quantiles.

Parameters:

  • base_data (dict, keyword-only): Required. A dictionary representing the baseline scenario. It must contain two keys:

    • 'budget': A dictionary mapping channel names to their budget values in this scenario.

    • 'contribution': A dictionary mapping channel names to their corresponding contribution values in this scenario. (Both inner dictionaries can optionally include a ‘total’ key, which is ignored in the plot.)

  • method (str, optional): The saturation function type ("sigmoid" or "michaelis-menten") used to estimate the contribution bounds (passed to internal _estimate_budget_contribution_fit). Defaults to "sigmoid".

  • **kwargs: Additional keyword arguments. Currently accepts:

    • scenarios_data (List[Dict], optional): A list of dictionaries, each structured like base_data, representing alternative scenarios to plot alongside the base scenario.

Returns:

  • plt.Figure: The matplotlib Figure object containing two subplots (one for budget, one for contribution).

Notes:

  • This method is marked as experimental.

  • It relies on the _estimate_budget_contribution_fit method (likely inherited from OptimizationMixin) to calculate the contribution bounds shown in the second plot.

  • Helper function ut.standardize_scenarios_dict_keys is used internally to ensure input dictionaries have the expected keys.


plot_direct_contribution_curves

def plot_direct_contribution_curves(
    self,
    show_fit: bool = False,
    xlim_max: Optional[Union[int, float]] = None,
    method: str = "sigmoid",
    channels: Optional[List[str]] = None,
    same_axes: bool = False,
) -> plt.Figure:

Plots the relationship between historical channel spend and the resulting mean posterior contribution (direct response curve). Optionally overlays a fitted saturation curve.

This plot shows a scatter of actual spend points versus their corresponding mean contribution from the model fit. The term “direct” signifies that it plots immediate contribution against spend, without explicitly visualising the lagged effects captured by adstock transformations within the model. If show_fit is True, it estimates parameters for a chosen saturation function (method) based on this relationship and plots the resulting curve, along with its inflection point.

Parameters:

  • show_fit (bool, optional): If True, estimates and plots a saturation curve fit (Sigmoid or Michaelis-Menten) over the scatter plot. Defaults to False.

  • xlim_max (int | float, optional): Sets the maximum limit for the x-axis (spend). If None (default), the limit is determined by the maximum observed spend for the channel(s) being plotted.

  • method (str, optional): The saturation function type ("sigmoid" or "michaelis-menten") to use if show_fit is True. Defaults to "sigmoid".

  • channels (List[str], optional): A list of specific channel names to plot. If None (default), plots curves for all channels defined in self.channel_columns.

  • same_axes (bool, optional): If True, plots all selected channel curves on a single subplot. If False (default), creates a separate subplot for each channel.

Returns:

  • plt.Figure: The matplotlib Figure object containing the plot(s).

Raises:

  • ValueError: If any channel specified in channels is not found in self.channel_columns, or if channels contains duplicates. If method is invalid when show_fit is True.

  • RuntimeError: If the model hasn’t been fitted with X data yet.


(Private helper methods _plot_scenario and _plot_response_curve_fit are used internally to handle the plotting logic for individual scenarios/bars and the fitted response curves, respectively.)