The wavecov package provides overlap-aware comparisons
of workforce metrics between two waves of data. This vignette shows the
core scalar API, compare_waves(), on a minimal example.
We assume a long panel with one row per employee-wave-metric:
The simplest use case is a single metric between two waves:
res_linked <- compare_waves(
data = dat,
wave_0 = 0,
wave_1 = 1,
id_col = "eeid",
wave_col = "wave",
metric_col = "metric",
method = "linked"
)
res_linked
#> $estimate
#> [1] 0.06666667
#>
#> $se
#> [1] 0.08819171
#>
#> $ci
#> [1] -0.1061859 0.2395192
#>
#> $level
#> [1] 0.95
#>
#> $N0
#> [1] 3
#>
#> $N1
#> [1] 3
#>
#> $nS
#> [1] 3
#>
#> $overlap
#> [1] 1
#>
#> $method
#> [1] "linked"
#>
#> $V0_bar
#> [1] 0.3333333
#>
#> $V1_bar
#> [1] 0.2411111
#>
#> $C01_bar
#> [1] 0.2833333
#>
#> $V0_ind
#> [1] 1
#>
#> $V1_ind
#> [1] 0.7233333
#>
#> $C01_ind
#> [1] 0.85
#>
#> $sigma2
#> NULL
#>
#> $reliability
#> NULL
#>
#> $ci_lower
#> [1] -0.1061859
#>
#> $ci_upper
#> [1] 0.2395192
#>
#> attr(,"class")
#> [1] "wavecov_result"The result is a wavecov_result object with:
estimate: change in the metric between wave 0 and wave
1.se: standard error of the change estimate.ci_lower, ci_upper: lower/upper confidence
limits at the requested level.N0, N1: counts in wave 0 and wave 1.nS: number of “stayers” (ids present in both
waves).method: the estimation method actually used.You can pull individual fields:
If stayer information is unavailable or individual-level data are not
available, the linked method cannot be used. In that case, you can
either specify method = "reliability" directly, or let
method = "auto" choose between linked, reliability, and
bounds. The example below uses a case where individual data is available
at both waves, but information on stayers has been lost (e.g., due to
anonymized records). The user should note that reliability should
reflect temporal stability for this use case.
dat_no_stayers <- data.frame(
eeid = c("a", "b", "c", "d", "e", "f"),
wave = c(0, 0, 0, 1, 1, 1),
metric = c(1.0, 2.0, 3.0,
1.5, 2.2, 3.1)
)
# Auto will fall back to reliability or bounds as needed
res_auto <- compare_waves(
data = dat_no_stayers,
wave_0 = 0,
wave_1 = 1,
id_col = "eeid",
wave_col = "wave",
metric_col = "metric",
method = "auto",
reliability = 0.8
)
res_auto$method
#> [1] "reliability"
res_auto$estimate
#> [1] 0.2666667
c(res_auto$ci_lower, res_auto$ci_upper)
#> [1] -1.183942 1.717275In some cases we neither have stayer information available nor are
willing to assume a reliability. In that setting,
compare_waves() can fall back to Cauchy-based bounds, which
describe a range of possible changes consistent with
the data instead of a single point estimate.
Setting method = "bounds" forces this behaviour:
dat_bounds <- data.frame(
eeid = c("a", "b", "c", "d", "e", "f"),
wave = c(0, 0, 0, 1, 1, 1),
metric = c(1.0, 2.0, 3.0,
1.5, 2.2, 3.1)
)
res_bounds <- compare_waves(
data = dat_bounds,
wave_0 = 0,
wave_1 = 1,
id_col = "eeid",
wave_col = "wave",
metric_col = "metric",
method = "bounds",
cov_sign = "unrestricted",
overlap_mode = "generic"
)
res_bounds
#> $estimate
#> [1] 0.2666667
#>
#> $se_lower
#> [1] 0.1142688
#>
#> $se_upper
#> [1] 1.040432
#>
#> $var_lower
#> [1] 0.01305736
#>
#> $var_upper
#> [1] 1.082498
#>
#> $level
#> [1] 0.95
#>
#> $N0
#> [1] 3
#>
#> $N1
#> [1] 3
#>
#> $nS
#> [1] 0
#>
#> $overlap
#> [1] 0
#>
#> $cov_sign
#> [1] "unrestricted"
#>
#> $overlap_mode
#> [1] "generic"
#>
#> $method
#> [1] "bounds"
#>
#> $ci_lower
#> [1] NA
#>
#> $ci_upper
#> [1] NA
#>
#> attr(,"class")
#> [1] "wavecov_bounds_result"A wavecov_bounds_result object does not commit to a
single change estimate; instead it reports bounds implied by the
observed wave-level variances and any assumptions you specify
(cov_sign, overlap_mode, and optionally
sigma2S). This is appropriate when composition change is
large and we lack enough structure for a defensible point estimate.
Use compare_waves() when you want a single,
well-understood comparison between two waves for one metric and
(optionally) one population slice. The companion
compare_waves_batch() wrapper (see the Panel comparisons
vignette) generalizes this to many groups and metrics.