A rotating panel that replenishes is drawn as a series of executions: a
start-up master against the first frame vintage, then one refreshment
cohort against each later vintage. rotation_program() records which
samples make up the program, when each entered, and which components are
live at each occasion, so that execute() can materialize a wave across
all of them.
Arguments
- cohorts
A named list of executed
tbl_sampleobjects, one per cohort. Each must be complete, unmodified and a single replicate.- entry_wave
Integer vector of entry occasions, named to match
cohorts. Required with a data-framescheduleand omitted with ansvyplan_schedule.- schedule
A data frame declaring which components are active at which wave, or an
svyplan_schedulefromsvyplan::design_schedule().- through
Last occasion to register from an
svyplan_schedule. Required for that route and unused with a data-frame schedule.
Details
Cohorts
cohorts is a named list of executed samples. A cohort may be
partitioned, drawn with panels so that it carries .panel and a frozen
assignment, or whole, drawn without panels. A whole cohort has one
implicit panel numbered 1 covering all its rows. Activating it is not a
subsample, so its weights are unchanged.
Entry waves
With a data-frame schedule, entry_wave names the occasion at which each
cohort's vintage enters the program. It is declared rather than inferred
from first activity because a cohort may be drawn early and held in reserve.
An svyplan_schedule already records every entry occasion, so it supplies
this field and redundant entry_wave input is refused.
Schedule
schedule is a data frame with cohort (a name from cohorts), integer
panel, integer wave, and an optional logical active. A combination
left out is inactive. For a one-cohort program the cohort column may be
omitted. Waves are numbered from 1 without gaps. Activity need not be
contiguous: a 4-8-4 rotation deliberately leaves and re-enters.
The schedule is completed to the full grid only after the registry is known, because a cohort's available panels come from its own receipt rather than from the schedule.
An svyplan_schedule registers the program as of through. Exactly the
startup and intake cohorts entering by that occasion must be supplied.
Later cohorts remain planned but unfielded. The executed receipts determine
realized panel and issue counts, which are checked against the plan.
What a wave returns
execute(program, wave = t) returns a collection of samples with separate
receipts, one per live cohort, each carrying its own exact activation
factor. It is not row-bound and its weights are not combined.
Overlap between cohorts is unknown, not assumed absent
A program records when its cohorts are live. It does not record how they relate. Whether a unit could have been drawn into more than one cohort depends on facts no receipt carries: whether it was in the population at each vintage, what chance it would have had in a draw it was not selected into, and whether the draws were independent of one another. Two executions with identical inclusion probabilities can be independent or identical depending on how they were seeded and coordinated, and nothing stored can tell them apart.
So the weights of a wave are valid within a cohort, and combining them across cohorts is left to the analyst, who may know things the program does not.
The common case where that knowledge is easy is a refreshment cohort drawn from an entrant register, a frame holding only units that entered the population since the previous vintage. No unit can appear on both frames, so the cohorts are disjoint by construction, each unit belongs to exactly one, and the component weights are already the right ones for the combined live set. A refresher drawn from the whole population at a later vintage is the other case: a unit present at both times had two chances of selection, and combining then needs a union probability, which is a multi-frame problem rather than a scheduling one.
See also
execute() for drawing a master and materializing a wave,
vignette("rotating-panels") for the design taxonomy this fits
into.
Other execution:
execute(),
execution-conditions,
validate_frame()
Examples
frame_1 <- data.frame(id = 1:200, value = rnorm(200))
# Two groups, each live for two of the three occasions.
startup_schedule <- data.frame(
panel = rep(1:2, times = 3),
wave = rep(1:3, each = 2),
active = c(TRUE, TRUE, TRUE, FALSE, FALSE, TRUE)
)
startup <- sampling_design() |>
draw(n = 40) |>
execute(frame_1, seed = 1, panels = startup_schedule)
# A refreshment cohort drawn from the entrants of a later vintage.
entrants <- data.frame(id = 201:260, value = rnorm(60))
intake_2 <- sampling_design() |>
draw(n = 12) |>
execute(entrants, seed = 2)
program <- rotation_program(
cohorts = list(startup = startup, intake_2 = intake_2),
entry_wave = c(startup = 1, intake_2 = 2),
schedule = rbind(
transform(startup_schedule, cohort = "startup"),
data.frame(
cohort = "intake_2", panel = 1, wave = 1:3,
active = c(FALSE, TRUE, TRUE)
)
)
)
program
#> ── Rotation Program ────────────────────────────────────────────────────────────
#>
#> ℹ 2 cohorts over 3 waves
#> • startup: 40 rows, 2 panels, enters at wave 1, live at waves 1, 2, 3
#> • intake_2: 12 rows, 1 panel, enters at wave 2, live at waves 2, 3
#>
execute(program, wave = 2)
#> ── Rotation Wave 2 ─────────────────────────────────────────────────────────────
#>
#> • startup: 20 rows, panel 1
#> • intake_2: 12 rows, panel 1
#> ℹ Weights are valid within a cohort and are not combined.
#>