Returns the carryover left in flight at the end of a series, in a form
adstock_geometric() and friends accept as their state argument. This is
how you continue a filter across contiguous chunks of a series without
re-running it from the beginning, and it is what step_adstock() stores at
prep() time.
Usage
adstock_state(
x,
decay,
max_lag = Inf,
state = 0,
by = NULL,
na_action = c("error", "zero", "keep")
)Arguments
- x
Numeric vector of media spend (or impressions, or GRPs) in time order.
xmust already be sorted by time and evenly spaced; the function has no index argument and cannot check this for you. Usestep_adstock()if you want the time index validated.- decay
Geometric decay coefficient in
[0, 1]. Seedecay_from_half_life()for the half-life vocabulary.- max_lag
Number of periods the kernel spans.
Infgives the recursive form, whose state is a single number.- state
Carryover already in flight at the start of
x, for chaining calls across contiguous chunks of a series. The default0is a cold start, meaning no media ran beforexbegan. For the infinite kernel this is a single number; for a finitemax_lagit is the precedingmax_lag - 1values ofx. Obtain it fromadstock_state().When
byis supplied, pass either the scalar0(orNULL) to cold-start every group, or a named list with one entry per group – which is the shapeadstock_state()returns when it is givenby. A list with aNULLentry is an error rather than a silent cold start for that group.- by
Optional grouping vector, or data frame of grouping vectors, the same length as
x. Adstock is applied independently within each group, which is what geo-level and panel models need. Never rely ondplyr::group_by()for this: grouping metadata does not reliably survive into every context where this function is called.- na_action
What to do about missing values in
x."error"(the default) refuses to guess."zero"treats missing media as no media, which is usually right for spend but is a substantive assumption."keep"letsNApropagate through the filter, which for the recursive form poisons every subsequent value.
Value
For the infinite kernel, a single number: the raw (unnormalised)
accumulator. For a finite max_lag, the last max_lag - 1 values of x,
oldest first. When by is supplied, a named list of such objects, one per
group.
Details
The stored state is always in raw units, independent of normalise, so a
state captured under one normalisation setting stays valid under the other.
The size of this object is the reason step_adstock() can survive a
train/test boundary without the leakage and row-count problems that
recipes::step_lag() runs into. For the recursive kernel it is one
double per series: no training observations are retained, so there is nothing
to leak and nothing to inflate the size of a fitted workflow.
See also
adstock_geometric(), adstock_weibull(), adstock_filter(),
and step_adstock(), which stores this state at prep() time.
Examples
first_half <- c(100, 80, 60, 40)
second_half <- c(20, 10, 5, 0)
s <- adstock_state(first_half, decay = 0.5)
s
#> [1] 102.5
# Filtering in two chunks with the state carried across gives exactly the
# same answer as filtering the whole series at once
chunked <- c(
adstock_geometric(first_half, decay = 0.5),
adstock_geometric(second_half, decay = 0.5, state = s)
)
whole <- adstock_geometric(c(first_half, second_half), decay = 0.5)
all.equal(chunked, whole)
#> [1] TRUE