Incrementality.compute_incremental_contribution#

Incrementality.compute_incremental_contribution(frequency, period_start=None, period_end=None, include_carryover=True, num_samples=None, random_state=None, counterfactual_spend_factor=0.0)[source]#

Compute incremental channel contributions using counterfactual analysis.

Core incrementality function. Compares the model’s prediction under actual spend with its prediction under a counterfactual spend scenario, properly accounting for adstock carryover. Results are always returned in the original scale of the target variable. See the module docstring for the full mathematical formulation.

Parameters:
frequency{“original”, “weekly”, “monthly”, “quarterly”, “yearly”, “all_time”}

Time aggregation frequency. "original" uses data’s native frequency. "all_time" returns a single value across the entire period.

period_startstr or pd.Timestamp, optional

Start date for evaluation window. If None, uses start of fitted data.

period_endstr or pd.Timestamp, optional

End date for evaluation window. If None, uses end of fitted data.

include_carryoverbool, default=True

Include adstock carryover effects. When True, prepends l_max observations before the period to capture historical effects carrying into the evaluation period, and extends the evaluation window by l_max periods to capture trailing adstock effects from spend during the period.

num_samplesint or None, optional

Number of posterior samples to use. If None, all samples are used. If less than total available (chain × draw), a random subset is drawn.

random_stateRandomState or Generator or None, optional

Random state for reproducible subsampling. Only used when num_samples is not None.

counterfactual_spend_factorfloat, default=0.0

Multiplicative factor α applied to channel spend in the counterfactual scenario.

  • 0.0 (default): Zeroes out channel spend → total incremental contribution (classic on/off counterfactual).

  • 1.01: Scales spend to 101% of actual → marginal incremental contribution (response to a 1 % spend increase).

  • Any value ≥ 0: Supported. Values > 1 measure the upside of more spend; values in (0, 1) measure the cost of less spend.

Returns:
xr.DataArray

Incremental contributions in original scale with dimensions:

  • (chain, draw, date, channel, *custom_dims) when frequency != "all_time"

  • (chain, draw, channel, *custom_dims) when frequency == "all_time"

For models with hierarchical dimensions like dims=("country",), output has shape (chain, draw, date, channel, country).

Sign convention: The result is always Y(perturbed) Y(actual) when α > 1 and Y(actual) Y(counterfactual) when α < 1 (including 0). Both total and marginal incrementality are therefore positive for channels with a positive effect.

Raises:
ValueError

If frequency is invalid, period dates are outside fitted data range, or counterfactual_spend_factor is negative.

References

Google MMM Paper: https://storage.googleapis.com/gweb-research2023-media/pubtools/3806.pdf

Examples

Compute quarterly incremental contributions:

incremental = mmm.incrementality.compute_incremental_contribution(
    frequency="quarterly",
    period_start="2024-01-01",
    period_end="2024-12-31",
)

Mean contribution per channel per quarter:

incremental.mean(dim=["chain", "draw"])

Total annual contribution (all_time):

annual = mmm.incrementality.compute_incremental_contribution(
    frequency="all_time",
    period_start="2024-01-01",
    period_end="2024-12-31",
)

Quarterly marginal incrementality (1 % spend increase):

marginal = mmm.incrementality.compute_incremental_contribution(
    frequency="quarterly",
    counterfactual_spend_factor=1.01,
)