Skip to contents

Translate the launch and recruitment quantities in a rotating svyplan_panel into named cohort components, a dense panel-by-occasion schedule, and any interview commitments beyond the planning horizon. The result is a planning object. It does not inspect a frame, execute a sample, or construct analysis weights.

Usage

design_schedule(
  panel_plan,
  horizon,
  horizon_policy,
  refreshment,
  frame_vintage = NULL,
  rounding,
  take = NULL,
  tenures = 1,
  subperiods = 1
)

Arguments

panel_plan

A rotating svyplan_panel from n_panel() or prec_panel() with start = "immediate" or start = "gradual". Its rotation is the life the schedule lays out, and the overlap the manifest records is computed from it, so neither is supplied here.

horizon

A positive whole number of program occasions in the finite planning window.

horizon_policy

One of "continuing", "truncate_lives", or "close_intake". Under "continuing", interviews owed after horizon are returned separately in tail_commitments. "truncate_lives" cuts those interviews at the horizon, and a life it cuts ends at its last interview inside the window. "close_intake" stops recruitment soon enough for every recruited cohort to finish by the horizon.

refreshment

Whether later cohorts are drawn from an "entrant_register" or a "whole_vintage". This records a frame role and does not establish disjointness or combine weights.

frame_vintage

NULL, or a named character vector supplying frame identifiers for any subset of the generated cohort names. Unnamed or unknown entries are refused rather than matched by position.

rounding

The explicit operational rounding rule. The schema supports "ceiling", applied to each startup panel and intake cohort before totals are formed. Operational counts are stored as whole-valued numerics so plans above R's 32-bit integer range remain representable.

take

NULL (default), or a positive whole number of units a PSU takes per tenure. With it the assignment unit is the PSU. Each panel issues ceiling(n_entrants / take) PSUs, rounded at the PSU, and the units it stands for are that number times take. The unit quantities stay with the panel plan, whose target carries the clustering through its deff.

tenures

1 (default) or "open". With 1 a PSU leaves with its units at the end of their life. With "open" the PSUs stay through the horizon and only the units rotate. Each panel is then a PSU group whose life repeats the rotation back to back, and visit restarts at 1 at each tenure, where the group's new units are drawn. A finite number of tenures above 1 is not available.

subperiods

A positive whole number, 1 by default. The rotation, the panel plan and horizon are stated per reporting period, and the schedule is written in horizon * subperiods fieldwork waves. See the section on sub-periods.

Value

An svyplan_schedule list with scalar planning metadata and four data frames. schema_version is 2. The metadata carries n_entrants, n_in_sample and n_held from the panel plan, and n_cohorts, the cohorts in sample at an occasion, which is the number of visits. life_length is the life in occasions, gaps included. take, tenures (1, or Inf for "open") and subperiods record the arguments.

components

One row per execution: startup followed by the intake cohorts permitted by the horizon policy. Continuous and operational issue remain separate.

schedule

The dense component-panel grid over occasions 1 through horizon. period names each wave's reporting period, (wave - 1) %/% subperiods + 1, which equals wave when subperiods = 1. A row is in one of three states. Before a panel's entry or after its life it has active = FALSE and life_stage and visit NA. Held out of sample, in a gap of its life, it has active = FALSE, a life_stage and visit = NA. Interviewed, it has active = TRUE, a life_stage and a visit.

tail_commitments

A sparse table of interviews after horizon owed to components entering within a "continuing" window, with the same period, life_stage and visit. It lists interviews only and has a fixed empty schema under the other policies.

issue

The continuous and operational recruitment issued at each in-horizon occasion, in assignment units, and tenure_issue, the units first interviewed there, which is where a tenure's units are drawn. as.data.frame() returns this view.

The generated activity is checked against panel_plan$launch_waves over every shared period that the horizon policy has not changed. Its realized issued overlap is also checked against the overlap the rotation produces, at every mature membership origin for which the destination occasion exists.

Details

life_stage counts the occasions of a panel's own life and visit its interviews, both from 1. They are equal for a life without a break. Under "2-2-2" an intake cohort has life_stage 1 to 6 and visit 1, 2, NA, NA, 3, 4.

An immediate start covers every stage of the life at the first occasion, one startup panel per stage, as n_panel() plans it. A panel covering a stage out of sample is selected at the first occasion and held until the rest of its life returns to sample. Its first interview, where visit is 1, comes later. Under "2-2-2" the panels covering stages 3 and 4 are first interviewed at occasions 3 and 2. A panel numbers its own stages and interviews, so every panel has a visit of 1 at its first interview.

PSUs and tenures

With take, the schedule counts PSUs. Each panel is a group of ceiling(n_entrants / take) PSUs, and a group takes take units in each PSU at every tenure. The PSU allocation then reads its total from the schedule, as in n_alloc(frame, n = schedule$components$operational_issue[1], n_step = G) with G the number of startup panels, so that the master has the PSU count the schedule promises.

Under tenures = "open" no PSU is replaced inside the horizon. An immediate start selects every group at the first occasion, each group's first tenure being the rest of the life from the stage it covers, and a gradual start brings in one group an occasion until the life is covered. A new tenure is a new draw of units, so the overlap of the units is still the one design_overlap() gives for the rotation. The horizon policies apply to tenures. "continuing" lists the rest of every tenure opened in the window, "truncate_lives" cuts tenures at the horizon, and "close_intake" opens no tenure that cannot finish by it.

Sub-periods

Monthly fieldwork for quarterly estimates is a schedule over months. With subperiods = s, each reporting panel g becomes s panels, numbered (g - 1) * s + j for j in 1 to s, so the group of a panel is ceiling(panel / s). Panel j is interviewed at wave (period - 1) * s + j of every period its group is interviewed in, and is held in the other waves of the group's life. A unit keeps its sub-period at every visit and across tenures. period names the reporting period of each wave, and life_stage, life_length and visit count periods and interviews, not waves. horizon, wave, entry_wave and steady_state_from count waves, and a cohort entering in period t enters at wave (t - 1) * s + 1, every sub-period panel being selected then. Each sub-period panel takes ceiling(n_entrants / s) units, or that over take in PSUs, so a period issues up to s - 1 more per group than the continuous plan. The launch and overlap checks run on the reporting grid, and $overlap is the reporting-period profile.

See also

design_rotation() for the pattern this schedules, n_panel() and prec_panel() for the rotating plan, plot.svyplan_overlap() for the rotation chart, and print.svyplan_schedule() for the printed form and its summary().

Other repeated survey functions: design_overlap(), design_rotation(), n_change(), n_panel(), n_pooled(), prec_change(), prec_panel(), prec_pooled()

Examples

panel <- n_panel(
  n_prop(p = 0.5, moe = 0.03),
  retention = c(0.9, 0.9, 0.9),
  resp_rate = 0.75,
  design = "rotating",
  start = "immediate"
)
schedule <- design_schedule(
  panel,
  horizon = 6,
  horizon_policy = "continuing",
  refreshment = "entrant_register",
  rounding = "ceiling"
)
schedule
#> Longitudinal design schedule (immediate launch, continuing)
#> life: 4 stages over 6 occasions, steady from occasion 4
#> rounding: ceiling at panel and cohort level
#> issue: 1656 at startup, 414 per occasion (occasions 2-6)
#> tail commitments: 6 panel-interviews after occasion 6
#> # summary() for the occasion-by-occasion profile and the overlap
schedule$components
#>     cohort entry_wave       frame_role planned_issue operational_issue panels
#> 1  startup          1          startup      1654.856              1656      4
#> 2 intake_2          2 entrant_register       413.714               414      1
#> 3 intake_3          3 entrant_register       413.714               414      1
#> 4 intake_4          4 entrant_register       413.714               414      1
#> 5 intake_5          5 entrant_register       413.714               414      1
#> 6 intake_6          6 entrant_register       413.714               414      1
#>   panel_issue frame_vintage  status
#> 1         414          <NA> planned
#> 2         414          <NA> planned
#> 3         414          <NA> planned
#> 4         414          <NA> planned
#> 5         414          <NA> planned
#> 6         414          <NA> planned

# A 2-2-2 rotation: six startup panels, four interviewed at each occasion
quarterly <- n_panel(
  n_prop(p = 0.5, moe = 0.03),
  retention = c(0.9, 0.85, 0.9),
  resp_rate = 0.75,
  design = "rotating",
  start = "immediate",
  rotation = "2-2-2"
)
gapped <- design_schedule(
  quarterly,
  horizon = 8,
  horizon_policy = "continuing",
  refreshment = "entrant_register",
  rounding = "ceiling"
)
gapped
#> Longitudinal design schedule (immediate launch, continuing)
#> life: 6 stages over 8 occasions, steady from occasion 6
#> rotation: 2 in, 2 out, 2 in
#> rounding: ceiling at panel and cohort level
#> issue: 2550 at startup, 425 per occasion (occasions 2-8)
#> tail commitments: 10 panel-interviews after occasion 8
#> # summary() for the occasion-by-occasion profile and the overlap
startup <- gapped$schedule[gapped$schedule$cohort == "startup", ]
xtabs(visit ~ panel + wave, startup, addNA = TRUE)
#>      wave
#> panel  1  2  3  4  5  6 7 8
#>     1  1  2        3  4    
#>     2  1        2  3       
#>     3        1  2          
#>     4     1  2             
#>     5  1  2                
#>     6  1                   

# Quarterly reporting on a life of five quarters, 14 units per PSU, PSUs
# kept and monthly fieldwork: 15 panels, each in its own month
monthly <- design_schedule(
  n_panel(n_prop(p = 0.5, moe = 0.02, deff = 1.8),
          retention = rep(0.9, 4), resp_rate = 0.8,
          design = "rotating", start = "immediate"),
  horizon = 4,
  horizon_policy = "continuing",
  refreshment = "entrant_register",
  rounding = "ceiling",
  take = 14,
  tenures = "open",
  subperiods = 3
)
monthly
#> Longitudinal design schedule (immediate launch, continuing)
#> life: 5 periods over 4 periods of 3 waves, steady state not reached in the window
#> take: 14 units per PSU per tenure
#> tenures: open, PSUs kept through the horizon
#> rounding: ceiling at psu and subperiod level
#> issue: 480 PSUs at startup, no PSU intake from period 2
#> tail commitments: 30 panel-interviews after wave 12
#> # summary() for the occasion-by-occasion profile and the overlap
xtabs(visit ~ panel + wave, monthly$schedule, addNA = TRUE)
#>      wave
#> panel  1  2  3  4  5  6  7  8  9 10 11 12
#>    1   1        2        3        4      
#>    2      1        2        3        4   
#>    3         1        2        3        4
#>    4   1        2        3        4      
#>    5      1        2        3        4   
#>    6         1        2        3        4
#>    7   1        2        3        1      
#>    8      1        2        3        1   
#>    9         1        2        3        1
#>    10  1        2        1        2      
#>    11     1        2        1        2   
#>    12        1        2        1        2
#>    13  1        1        2        3      
#>    14     1        1        2        3   
#>    15        1        1        2        3