
Calculate Proportional Change in Between-Stratum Variance (PCV)
Source:R/calculate_pcv.R
calculate_pcv.RdCalculates the proportional change in between-stratum variance (PCV) between two MAIHDA models. The PCV measures how much the between-stratum variance changes when moving from one model to another, and is calculated as: PCV = (Var_model1 - Var_model2) / Var_model1.
Usage
calculate_pcv(
model1,
model2,
bootstrap = FALSE,
n_boot = 1000,
conf_level = 0.95,
estimation = c("fitted", "ML")
)Arguments
- model1
A maihda_model object from
fit_maihda(). This is the reference model (typically a simpler or baseline model).- model2
A maihda_model object from
fit_maihda(). This is the comparison model (typically a more complex model with additional predictors).- bootstrap
Logical indicating whether to compute bootstrap confidence intervals for the PCV. Default is FALSE. lme4 engine only: the parametric bootstrap relies on lme4's
simulate()/refit(), so for the brms, wemix, and ordinal engines the PCV is reported as a point estimate andbootstrap = TRUEis an error (see Details).- n_boot
Number of bootstrap samples if bootstrap = TRUE. Default is 1000. A value below about 200 warns that the interval's tail endpoints are unstable (the hard minimum is 10).
- conf_level
Confidence level for bootstrap intervals. Default is 0.95.
- estimation
Variance-estimation basis for the cross-model comparison, one of
"fitted"(default) or"ML"."fitted"differences each model's own between-stratum variance (the REML estimate for a Gaussianlmerfit);"ML"refits any REMLlmerfit with maximum likelihood first, for a correction-free comparison. The choice affects Gaussianlmerfits only –glmerand the wemix/ordinal engines are already maximum-likelihood, and abrmsfit is a Bayesian posterior (not ML), so"ML"is a no-op for all of them; abrmscomparison is reported on the as-fitted posterior basis rather than as an ML-refit. See Details for the finite-sample tradeoff. Whenever model2 (the adjusted model) sits on the singularity boundary – under anyestimationbasis – the PCV is pinned near 1; this is recorded asadjusted_at_boundary = TRUEand noted byprint(). It is not treated as an error or warned about: a singular fit is indistinguishable from genuinely additive strata (a common, legitimate result).
Value
A list containing:
- pcv
The estimated proportional change in variance
- pvc
Deprecated duplicate of
pcv, kept so code written against the historicalcalculate_pvc()spelling keeps working; it will be removed in a future release- var_model1
Between-stratum variance from model1
- var_model2
Between-stratum variance from model2
- estimation
The variance-estimation basis requested (
"fitted"or"ML")- estimation_used
The basis actually used:
"fitted","ML","mixed", or"posterior"."mixed"arises underestimation = "ML"when a model keeps its REML fit – its between-stratum variance is on the boundary so the ML refit is skipped, orrefitMLfailed – so the comparison is partly REML rather than a pure, correction-free ML one."posterior"is reported for abrmscomparison (a Bayesian posterior, on which"ML"is a no-op).print()states the basis- adjusted_at_boundary
Logical;
TRUEwhen model2's between-stratum variance is on the singularity boundary, so the PCV is pinned near 1 (100%) and its interval/SE are unreliable – consistent with genuinely additive strata as well as a degenerate fit (print()states this)- ml_refit_failed
Logical;
TRUEwhenestimation = "ML"was requested butrefitMLfailed for a model, so its REML fit was used instead (the comparison is then not on a pure ML basis)- ci_lower
Lower bound of confidence interval (if bootstrap = TRUE)
- ci_upper
Upper bound of confidence interval (if bootstrap = TRUE)
- bootstrap
Logical indicating if bootstrap was used
Details
The PCV is the proportional change in between-stratum variance when moving from model1 to model2: a positive value means model2 has lower between-stratum variance, a negative value means higher. It is the share of model1's between-stratum variance explained by model2 only in the canonical nested case, where model2 adds fixed-effect predictors to model1 on the same outcome, analytic sample and strata. The function does not require nesting, so for non-nested models the PCV is simply a model-dependent difference in variance, not an explained proportion.
REML vs ML (the estimation argument). lmer fits Gaussian
models by REML, and two considerations pull in opposite directions when the PCV
differences two such fits. On one hand, the REML likelihood is not
comparable across models with different fixed effects, and REML applies a
model-specific degrees-of-freedom correction that differs between the null and the
adjusted fit; refitting both with maximum likelihood (refitML)
puts the two between-stratum variances on a common, correction-free basis, matching
maihda_ic and anova() on lme4 models. On the other hand,
ML variance-component estimates are downward-biased in finite samples – most
sharply with few strata (the usual MAIHDA regime), and more so for the adjusted
model (more fixed effects, larger REML correction) – which inflates the
reported PCV relative to the REML estimates. Both are defensible point estimates of
each model's between-stratum variance, so estimation selects between them:
"fitted"(default)use each model's own fitted between-stratum variance – the REML estimate for an
lmerGaussian fit. This matches the variancessummary.maihda_modelreports and conventional MAIHDA practice, and avoids ML's finite-sample downward bias."ML"refit any REML
lmerfit with maximum likelihood before reading the variances (and before the parametric bootstrap, so the interval matches), for a correction-free cross-model comparison.
The choice affects Gaussian lmer fits only: GLMM fits (glmer) and the
wemix/ordinal engines are already on the maximum-likelihood scale, so "fitted"
and "ML" coincide there. A brms fit is a Bayesian Stan posterior,
not a maximum-likelihood fit, so "ML" performs no refit and the comparison is
reported on the as-fitted posterior basis (estimation_used = "posterior"), never
as an ML-refit. Single-model VPC/ICC summaries always keep their REML fit, since that
comparison-free quantity is not subject to the cross-model pitfall.
Latent-scale families and rescaling. For families whose level-1
variance is a fixed latent-scale constant – binomial/Bernoulli
(\(\pi^2/3\) logit, 1 probit) and the cumulative (ordinal) model – the
linear predictor is identified only up to scale. Adding predictors that
explain within-stratum (individual-level) variation cannot shrink that
fixed level-1 variance; the latent scale stretches instead, inflating the
coefficients and the between-stratum variance alike (Bauer 2009; Mood 2010).
Part of a null-vs-adjusted change in the between-stratum variance is then
rescaling rather than genuinely explained variance, so latent-scale PCVs tend
to be understated and can turn negative on this account alone. The canonical
MAIHDA adjusted model – which adds the stratum dimensions' main effects,
constant within each stratum – is largely unaffected, but the caveat
is first-order whenever an added predictor varies within strata (an
individual-level covariate, as in the stepwise_pcv steps that
add one). The count families' level-1 variance is not a fixed constant, but
as with any non-identity link the same non-collapsibility logic applies in
attenuated form. Gaussian identity-link PCVs are not subject to this.
When bootstrap = TRUE, the function uses a parametric bootstrap: it simulates
new responses from model2 and refits both models with lme4::refit() for
each simulated response to obtain confidence intervals for the PCV estimate.
For negative-binomial models (glmer.nb) refit() holds the
dispersion parameter theta fixed at its original estimate, so the interval is
conditional on the estimated theta.
A bootstrap draw whose null-model between-stratum variance lands on
the zero boundary has no defined PCV (the denominator is zero); such draws
are excluded, so the percentile interval is conditional on estimating
a positive null variance. Whenever any draws hit the boundary the function
warns, reports the count as n_boot_boundary on the result, and
print() repeats the caveat – a sizeable boundary share signals weak
between-stratum variation, and the PCV itself is then fragile.
The bootstrap is available for the lme4 engine only. For the other
engines the PCV is a point estimate: a brms fit's posterior credible
interval (reported by summary.maihda_model) covers a single
fit's VPC/ICC, not the PCV, which compares two separately fitted models – no
posterior interval for the PCV itself is computed – and a design-based
(wemix) interval would require replicate weights.
References
Bauer, D. J. (2009). A note on comparing the estimates of models for cluster-correlated or longitudinal data with binary or ordinal outcomes. Psychometrika, 74(1), 97-105.
Mood, C. (2010). Logistic regression: why we cannot do what we think we can do, and what we can do about it. European Sociological Review, 26(1), 67-82.
See also
stepwise_pcv for the sequential (one-variable-at-a-time)
PCV, and maihda which computes the canonical null-vs-adjusted
PCV automatically.
Examples
# \donttest{
# Create strata and fit two models
strata_result <- make_strata(maihda_sim_data, c("gender", "race"))
model1 <- fit_maihda(health_outcome ~ age + (1 | stratum), data = strata_result$data)
model2 <- fit_maihda(health_outcome ~ age + gender + (1 | stratum), data = strata_result$data)
# Calculate PCV without bootstrap
pcv_result <- calculate_pcv(model1, model2)
print(pcv_result$pcv)
#> [1] -0.1626748
# Calculate PCV with bootstrap CI
# pcv_boot <- calculate_pcv(model1, model2, bootstrap = TRUE, n_boot = 500)
# print(pcv_boot)
# }