Skip to contents

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.

Usage

rotation_program(cohorts, entry_wave = NULL, schedule = NULL, through = NULL)

Arguments

cohorts

A named list of executed tbl_sample objects, 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-frame schedule and omitted with an svyplan_schedule.

schedule

A data frame declaring which components are active at which wave, or an svyplan_schedule from svyplan::design_schedule().

through

Last occasion to register from an svyplan_schedule. Required for that route and unused with a data-frame schedule.

Value

A rotation_program.

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.
#>