weasel v0.4.4
Wave-based Extraction and Selection for Longitudinal Data

weasel turns wave-and-respondent selection in longitudinal panels into an explicit, reproducible workflow.

weasel is an R package for researchers working with longitudinal panel or repeated-measures data who need to decide which waves and respondents belong in an analysis sample. It maps participation patterns, compares explicit selection scenarios using missing-wave tolerances, endpoint requirements, and interior-gap constraints, and audits the resulting sample with sensitivity and selectivity diagnostics.

Which workflow do you need? Answer one question at a time to reach the right recipe. The address bar follows along, so any step or recipe can be shared as a direct link.

Before using your data

  • Use long data with a respondent identifier and a numeric, integer-valued wave column. The automatic core/full Plan recipes need at least three distinct recorded waves. Map labels or dates to scheduled-wave indices first, preserving a lookup.
  • Participation means a valid (id, wave) row exists. An absent row is a missed wave; a row with missing outcomes still counts as observed. Do not add NA placeholder rows for missed waves.
  • Choose the grid from the study schedule: "consecutive" counts every integer in the window; "observed" counts only distinct wave values recorded in the data. Year labels alone do not determine the correct choice.
  • An observed grid cannot recover a scheduled wave absent from every record. For a known non-consecutive schedule with such absences, map the full schedule to sequential integer indices, retain the lookup, and use "consecutive" with explicit bounds. Inspect the printed span in each recipe before selection.

What the package does

  • Maps wave participation patterns across respondents
  • Compares selection scenarios with explicit structural constraints
  • Produces analysis-ready long-format data frames
  • Generates prose justifications suitable for methods sections

Two core pipelines

Scope Exploratory. Map participation and extract respondents under one configuration, including structural constraints.
Plan Comparative. Compare and record named constraint alternatives, score trade-offs, and extract a reproducible sample.

Reading participation patterns

The figures below use the notation of weasel's own pattern tables: a number is an observed wave (a row exists in the long data), a dot is a missed wave (the row is simply absent).

Observed and missed waves
1 2 3 · 5 6 · 8

Wave-level missingness is row absence: waves 4 and 7 are not NA rows, they simply do not exist in the data. NA values inside observed rows are item nonresponse and never affect selection.

Span and grid
grid = "consecutive"
span 4:9 (L = 6)
1 2 3 4 5 6 7 8 9 10
grid = "observed" (biennial)
span 2010:2016 (4 observed waves)
2008 2010 2012 2014 2016 2018

The span is the analysis window, lower:upper. The grid decides which waves inside it count as scheduled: every integer ("consecutive") or only wave values that occur in the data ("observed"), so 2011 is never a missed wave in a biennial panel.

Endpoints and interior gaps
▾ ▾
· · 3 4 5 · ·
entry
exit
1 2 · · 5 6 7
gap (length 2)

An interior gap is a run of missing waves strictly between a respondent's first and last observed wave. The top row misses both endpoints (▾) yet contains no gap; the bottom row keeps both endpoints and has exactly one gap of length 2.

Constraints select the subset
require_endpoints max_missing = 1 n_gap_max = 1 max_gap_len = 1
1234567
✓ kept
12·4567
✓ kept
12··567
✗ gap of 2
·234567
✗ endpoint missed
planning population 4 → retained 2 (retention 0.50)

The built-in anchored_balanced scenario applied to four respondents observed in the span (the planning population). Retention is always reported against that denominator, here 2 of 4.

Key definitions

  • Observed wave: a row for that (id, wave) pair exists in the long data; a missed wave is an absent row.
  • Span and grid: the analysis window and its scheduled waves; grid = "observed" uses only waves that occur in the data. Use it when those recorded values represent the intended schedule; an entirely absent scheduled wave cannot be inferred.
  • Endpoints: observed at the first and last wave of the span. .. 3 4 5 .. misses both endpoints yet has no interior gap.
  • Interior gap: a run of missing waves strictly between a respondent's first and last observed wave. 1 2 .. 5 6 7 has one gap of length 2; 1 . 3 . 5 . 7 has three gaps of length 1; late entry and early exit are not gaps.
  • Constraints: Scope supports min_present, max_missing, n_gap_max, max_gap_len, and require_endpoints. min_present is Scope-only. Plan scenario tables use exactly five fields: scenario (the name), require_endpoints, max_missing, n_gap_max, and max_gap_len. On a fixed grid of length L, at least M observed waves (integer M, 1 ≤ M ≤ L) is equivalent to max_missing = L - M, with other constraints held equal. L counts grid waves, for example length(p$span), and need not equal upper - lower + 1 on an observed grid.
  • Planning population: respondents observed at least once inside the span; every retention figure is relative to it, and plans report it.
  • Recommendation: the highest composite score under declared, overridable weights; near-ties are flagged, and the score decomposition travels with the table.

Decisions the package does not make

  • What the causal estimand is, or which substantive variables must be observed for your analysis.
  • Whether attrition is ignorable (missing at random) or whether a complete-case restriction biases your estimates; weasel_selectivity() helps you check, it does not decide.
  • Whether an automatically selected core window matches the substantive time period your question needs.
  • Whether the highest-scoring scenario is optimal for your analysis; the score is a transparent heuristic, not a validated decision rule.
  • Whether weighting or imputation should follow selection.
weasel R package · MIT License · remotes::install_github("siardv/weasel") · Run weasel_example() for a quick-start demonstration
GitHub · Report a bug