panel-comparisons"

knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
library(wavecov)

Overview

The compare_waves() function is designed for a single metric and a single pair of waves. In most real applications we want to:

This vignette shows how to move from individual comparisons to batch panel comparisons using compare_waves_batch().

We assume a long panel with:

Example panel

For illustration, we create a small synthetic panel with:

set.seed(123)

n_id   <- 100
waves  <- 0:2
ids    <- sprintf("ee%03d", 1:n_id)

base_panel <- expand.grid(
  eeid  = ids,
  wave  = waves,
  KEEP.OUT.ATTRS = FALSE,
  stringsAsFactors = FALSE
)

# Simple group assignment (one group per id-wave, then reused)
base_panel$group <- sample(c("Group A", "Group B"),
                           nrow(base_panel), replace = TRUE)

# Engagement metric block
eng_panel <- base_panel
eng_panel$metric_id <- "engagement_score"
eng_panel$metric <-
  3.5 +
  0.2 * eng_panel$wave +
  ifelse(eng_panel$group == "Group A", 0.1, -0.1) +
  rnorm(nrow(eng_panel), sd = 0.4)

# Pay index metric block
pay_panel <- base_panel
pay_panel$metric_id <- "pay_index"
pay_panel$metric <-
  1.0 +
  0.05 * pay_panel$wave +
  ifelse(pay_panel$group == "Group A", 0.05, -0.05) +
  rnorm(nrow(pay_panel), sd = 0.1)

# Stack into one long panel
panel <- rbind(eng_panel, pay_panel)

head(panel)
nrow(panel)  # should be 100 ids * 3 waves * 2 metrics = 600

Defining wave pairs

compare_waves_batch() expects an explicit set of wave pairs. A simple case is adjacent waves:

wave_pairs <- data.frame(
  wave_0 = c(0, 1),
  wave_1 = c(1, 2)
)

wave_pairs

This will run comparisons for:

Basic batch comparison

To run batch comparisons across all metrics and both groups:

batch_res <- compare_waves_batch(
  data          = panel,
  wave_pairs    = wave_pairs,
  id_col        = "eeid",
  wave_col      = "wave",
  metric_col    = "metric",
  metric_id_col = "metric_id",
  group_cols    = "group",
  method        = "auto",
  reliability   = 0.8
)

head(batch_res)

Each row corresponds to one combination of:

with associated estimate, standard error, interval, and diagnostics.

Interpreting batch output

A typical minimal view is:

batch_res_min <- batch_res[, c(
  "wave_0", "wave_1",
  "metric_id", "group",
  "estimate", "se",
  "ci_lower", "ci_upper",
  "method"
)]

head(batch_res_min)

You can use standard dplyr / ggplot2 tooling to filter or visualize by metric, group, or wave pair.

Filtering by metric or group

To focus on engagement only:

eng_changes <- subset(batch_res_min, metric_id == "engagement_score")
eng_changes 

To see differences for Group A vs Group B:

subset(batch_res_min,        metric_id == "engagement_score" &        wave_0 == 0 & wave_1 == 1)

When bounds are used

If there information on stayers is not available and no reliability estimate exists, method = "auto" may fall back to bounds. In that case, estimate / se are not available in the same way, and the result will use the bounds structure instead. In this example we supplied a reliability, so most comparisons will use linked or reliability.

For more detail on the scalar API and methods, see the Getting Started vignette

Summary

Both functions share the same underlying panel summary and variance logic, so batch results are method-consistent with the scalar API.



Try the wavecov package in your browser

Any scripts or data that you put into this service are public.

wavecov documentation built on Nov. 3, 2026, 5:07 p.m.