SpendProbe.measure#

SpendProbe.measure(*, effects, l_max)[source]#

Measure how far in time a change in spend moves the evaluated nodes.

The evaluation window is sized by this number, so taking it from an effect’s own declaration alone is a hazard: declare too little and the mediated tail falls outside the window, which returns a smaller increment with no indication anything was cut. So it is measured. Each node’s contribution under the probe is compared against the baseline, and the last date that moves by more than REACH_TOLERANCE of that node’s largest move fixes its reach.

channel_contribution is measured alongside the effects and not assumed to inherit the model’s own adstock.l_max. A custom adstock or saturation that reduces over date – anything of the shape x / x.mean("date") – is not a causal filter, and a plain MMM carrying one would otherwise be windowed silently wrong.

Two outcomes select full-axis evaluation instead of a window: a perturbation that still moves the far end of the axis (reach longer than the axis can show), and one that moves dates before the perturbed one. The latter cannot happen through a causal filter and identifies exactly the reduction above, whose value depends on the whole series, so no window reproduces it.

Parameters:
effectssequence of ChannelDependentEffect

The effects being evaluated alongside channel_contribution. Empty for a separable model, which still has channel_contribution measured.

l_maxint

The model’s own adstock.l_max, subtracted from each measured reach because the window already carries it.

Returns:
SpendReach

The window length and mode the evaluation has to use.