---
title: "panel-comparisons"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{panel-comparisons}
  %\VignetteEncoding{UTF-8}
  %\VignetteEngine{knitr::rmarkdown}
editor_options: 
  markdown: 
    wrap: 72
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

```{r setup}
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:

- compare multiple wave pairs (e.g., 2023Q1–2023Q2, 2023Q2–2023Q3),

- for multiple metrics,

- and often by groups (e.g., business unit, level, critical talent).

This vignette shows how to move from individual comparisons to **batch
panel comparisons** using `compare_waves_batch()`.

We assume a long panel with:

- one row per `id`–`wave`–`metric`,

- optional metric identifiers and grouping columns.

# Example panel

For illustration, we create a small synthetic panel with:

- 100 employees,

- 3 waves (0, 1, 2),

- 2 metrics:

  - `engagement_score`

  - `pay_index`

- a simple `group` column.

```{r}
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:

```{r}
wave_pairs <- data.frame(
  wave_0 = c(0, 1),
  wave_1 = c(1, 2)
)

wave_pairs
```

This will run comparisons for:

- wave 0 vs 1, and

- wave 1 vs 2.

# Basic batch comparison

To run batch comparisons across all metrics and both groups:

```{r}
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:

- `wave_0`, `wave_1`

- `metric_id`

- `group`

with associated estimate, standard error, interval, and diagnostics.

# Interpreting batch output

A typical minimal view is:

```{r}
batch_res_min <- batch_res[, c(
  "wave_0", "wave_1",
  "metric_id", "group",
  "estimate", "se",
  "ci_lower", "ci_upper",
  "method"
)]

head(batch_res_min)
```

- `estimate`: estimated change in the metric between `wave_0` and
  `wave_1`.

- `se`: standard error of that change.

- `ci_lower`, `ci_upper`: normal-approximation confidence interval.

- `method`: which estimator was actually used (`linked`, `reliability`,
  or `bounds`).

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:

```{r}
eng_changes <- subset(batch_res_min, metric_id == "engagement_score")
eng_changes 
```

To see differences for `Group A` vs `Group B`:

```{r}
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

- Use `compare_waves()` when you need a single, well-understood scalar
  comparison.

- Use `compare_waves_batch()` when you need many comparisons across wave
  pairs, metrics, and groups, with a consistent, tabular result.

Both functions share the same underlying panel summary and variance
logic, so batch results are method-consistent with the scalar API.
