Learn R Programming

DMAR (version 1.0.0)

mlmr_mv: Multivariate Maximum Likelihood Regression With Full Information Missing Data Handling

Description

Fits a multivariate multiple regression model by maximum likelihood, with full information maximum likelihood handling of missing values by default. Multiple outcomes are regressed on a shared predictor set simultaneously, with the residual covariance among outcomes estimated as part of the model. The formula interface mirrors lm's multivariate syntax, cbind(y1, y2, y3) ~ x1 + x2, and the returned object supports the same family of S3 methods as a univariate mlmr fit.

Usage

mlmr_mv(
  formula,
  data,
  missing = c("fiml", "ml", "listwise", "pairwise", "available.cases"),
  ci_method = c("profile", "wald", "boot"),
  conf_level = 0.95,
  B = 1000L,
  boot_type = c("ordinary", "bollen.stine"),
  boot_seed = NULL,
  estimator = c("ML", "MLR", "MLM", "GLS"),
  se = NULL,
  fixed_x = FALSE,
  auxiliary = NULL,
  effect_sizes = TRUE,
  enforce_es_bounds = FALSE,
  ...
)

Value

An object of class "mlmr_mv", a list with components similar to a univariate mlmr fit but extended for multiple outcomes:

call, formula, terms, model, xlevels

As in mlmr.

coefficients

A matrix with predictors (and an intercept row, when present) as rows and outcomes as columns, matching coef.mlm.

coef_table

A long data.frame with one row per (outcome, term) combination; columns include outcome, term, estimate, se, z_value, p_value, ci_lower, ci_upper, std_estimate.

vcov

The variance-covariance matrix of the regression coefficients across all outcomes, returned by vcov(). Rows and columns follow the outcome-major order of coef_table (the column-major flattening of coefficients) and are named "outcome:term", for example "mpg:wt", the naming vcov uses for an "mlm" fit. The cross-outcome blocks carry the sampling covariance between coefficients of different outcomes, so joint Wald tests across outcomes compose with coef().

residual_cov

The estimated residual covariance matrix among outcomes (J by J).

R2

Named vector of model implied \(R^2\) per outcome.

adj_R2

Named vector of adjusted \(R^2\) per outcome.

effect_sizes

When effect_sizes = TRUE, a long data.frame with one row per (outcome, predictor) combination giving \(sr^2\) and Cohen's \(f^2\).

fitted.values, residuals

Matrices with rows = observations and columns = outcomes; NA in rows where any predictor is missing.

logLik, N, N_complete

As in mlmr.

lavaan_fit

The underlying lavaan fit.

Arguments

formula

A two-sided formula whose left-hand side is cbind(y1, y2, ...) for two or more numeric outcomes and whose right-hand side names the shared predictor set. Factor predictors, interactions, polynomial terms, and transformations are supported as in mlmr.

data

A data.frame containing the variables in formula.

missing

Character; passed to lavaan. Defaults to "fiml" (equivalently "ml"). See mlmr for the full list of accepted values.

ci_method

Character; confidence interval method for the regression coefficients. "profile" (default), "wald", or "boot". The same trade-offs apply as in mlmr; with J outcomes and K predictors, profile likelihood requires \(O(JK)\) constrained refits. "boot" resamples the rows of data B times (or draws Bollen-Stine model-based resamples), refits on each, drops resamples whose refit does not converge, and reports each coefficient's percentile interval, the empirical quantiles of its resampled estimates; as in mlmr, the percentile interval is the only bootstrap interval offered. The examples ask for the Wald and bootstrap intervals so the help page stays quick; a reported analysis leaves ci_method at its default.

conf_level

Desired level of confidence. Defaults to 0.95.

B

Integer; number of bootstrap resamples when ci_method = "boot". Defaults to 1000.

boot_type

Character; "ordinary" (default) or "bollen.stine".

boot_seed

Integer or NULL. Defaults to NULL, which leaves the user's current RNG state intact; supply an integer for reproducible bootstraps. When set, the seed applies for the duration of the call and the caller's generator state is restored on exit.

estimator

Character; one of "ML" (default), "MLR", "MLM", "GLS".

se

Character or NULL; defaults to NULL, meaning "choose automatically from estimator" (same logic as mlmr).

fixed_x

Logical; defaults to FALSE (jointly model the predictor distribution, required for FIML to use rows with missing predictors).

auxiliary

Character vector of variable names in data to include as auxiliary variables (saturated correlates; Graham, 2003), or NULL (default) for none. Each auxiliary is correlated with every outcome's residual, every predictor, and each other auxiliary, but is never entered as a predictor, so the per-outcome regression coefficients keep their meaning while the full information maximum likelihood draws on the auxiliaries' observed values (the inclusive analysis strategy; Collins, Schafer, & Kam, 2001). A name in auxiliary must be numeric, present in data, absent from formula, and requires fixed_x = FALSE.

effect_sizes

Logical; whether to compute per-outcome standardized betas, semi-partial \(R^2\), and Cohen's \(f^2\). Defaults to TRUE.

enforce_es_bounds

Logical; if TRUE, negative per-outcome \(sr^2\) or \(f^2\) estimates (finite-sample artifacts) are clamped to zero. Defaults to FALSE.

...

Additional arguments forwarded to lavaan.

Author

Ken Kelley [email protected]

Details

Why a separate function from mlmr. A univariate mlmr fit handles the case of one outcome regressed on one or more predictors. mlmr_mv extends to the case of two or more outcomes regressed on the same predictor set, modeling the residual covariance among outcomes explicitly. This is the regression problem in which the FIML advantage over listwise deletion is largest, because rows that are missing on one outcome still contribute information about the other outcomes (via the modeled residual covariance) and about the joint distribution of the predictors. A user who fits separate univariate regressions for each outcome under listwise deletion can discard a great deal of information when the outcomes are correlated and missingness patterns differ.

Same predictor set across outcomes. The formula cbind(y1, y2) ~ x1 + x2 regresses both y1 and y2 on x1 and x2. Per-outcome predictor sets (sometimes called seemingly unrelated regression with heterogeneous predictors) are not supported; users who need that can fit separate mlmr models or call sem directly with a custom model string.

Auxiliary variables. As in mlmr, variables that are not part of the regression but are correlated with an outcome or with the missingness can be supplied through auxiliary and are entered as saturated correlates (Graham, 2003): each is correlated with every outcome's residual, every predictor, and each other auxiliary, but never as a predictor, so the per-outcome coefficients keep their meaning while the likelihood draws on the auxiliaries' observed values (the inclusive analysis strategy of Collins, Schafer, & Kam, 2001).

The bootstrap interval. ci_method = "boot" resamples the rows of data with replacement B times (1000 by default), refits the model on each resample, and reports each coefficient's percentile interval. It is the interval to ask for when the multivariate normality the likelihood assumes is doubtful, since its coverage does not rest on that assumption. The price is B refits of a model that already carries J outcomes, so a bootstrap interval is a deliberate request rather than a default. Bootstrap results vary from run to run; supply boot_seed for reproducibility. The mechanics, including the Bollen-Stine variant, are given in the ci_method argument description and in mlmr.

Caveats. Same as mlmr: the function assumes that, conditional on the predictors, the joint distribution of the outcomes is multivariate normal with constant covariance, and that missingness is at most MAR. Factor predictors and interactions are expanded through model.matrix once and reused for every outcome.

See Also

mlmr for the univariate sibling; lm (and the "mlm" object class) for the OLS multivariate analog; sem for the underlying engine.

Examples

Run this code
# Two outcomes on a shared predictor set. The residual covariance
# between the outcomes is estimated as part of the model, which is
# what separates this from two separate regressions. The fit asks
# for the Wald interval, a choice taken up below, and keeps the
# default effect_sizes = TRUE: the per-outcome effect sizes come
# back on the fit rather than in summary(), one row per outcome and
# predictor, giving the semi-partial R^2 and Cohen's f^2, and they
# are what fills the standardized coefficients in coef_table.
fit <- mlmr_mv(cbind(t6_paragraph_comprehension, t9_word_meaning) ~
                 t5_general_information + t7_sentence,
               data = holzinger_swineford,
               ci_method = "wald")
coef(fit)              # matrix: rows = predictors, cols = outcomes
summary(fit)
fit$R2                 # per-outcome R^2
fit$residual_cov       # residual covariance among outcomes
print(fit$effect_sizes, row.names = FALSE)

# The interval menu is profile, Wald, and bootstrap. The default,
# ci_method = "profile", inverts the likelihood ratio test one
# coefficient at a time, and with two outcomes there are twice as
# many coefficients to profile; it is what a reported interval
# deserves, and leaving ci_method at its default asks for it. The
# fits on this page ask for the Wald or the bootstrap interval
# because those refits take longer than a help page should. The
# bootstrap resamples rows and takes percentile limits; it is what
# to ask for when the multivariate normality the likelihood assumes
# is doubtful. B = 10 keeps the example quick, since every resample
# refits the two-outcome model; a reported interval deserves the
# default B = 1000. boot_seed fixes the resamples, so the limits
# are reproducible rather than moving from run to run. The effect
# sizes cost one constrained refit per outcome and predictor, so this
# fit and the ones after it leave them off.
fit_boot <- mlmr_mv(cbind(t6_paragraph_comprehension, t9_word_meaning) ~
                      t5_general_information + t7_sentence,
                    data = holzinger_swineford,
                    ci_method = "boot", B = 10, boot_seed = 113,
                    effect_sizes = FALSE)
confint(fit_boot)

# FIML versus listwise when one outcome has missing values. The
# revised second-form test t26_flags was administered to only 145
# of the 301 students, so it carries real missingness. A row with
# t26_flags missing still informs the likelihood about the other
# outcome, about the predictors, and, through the residual
# covariance, about t26_flags itself, so no row is discarded. Notice
# the two sample sizes, and that the coefficients of the complete
# outcome differ between the fits: listwise deletion drops 156 of
# its observed rows along with the missing t26_flags values.
fit_fiml <- mlmr_mv(cbind(t6_paragraph_comprehension,
                          t26_flags) ~
                      t7_sentence + t9_word_meaning,
                    data = holzinger_swineford,
                    ci_method = "wald", effect_sizes = FALSE)
fit_lwd  <- mlmr_mv(cbind(t6_paragraph_comprehension,
                          t26_flags) ~
                      t7_sentence + t9_word_meaning,
                    data = holzinger_swineford,
                    missing = "listwise", ci_method = "wald",
                    effect_sizes = FALSE)
c(N_fiml = nobs(fit_fiml), N_listwise = nobs(fit_lwd))
cbind(FIML = coef(fit_fiml)[, "t6_paragraph_comprehension"],
      listwise = coef(fit_lwd)[, "t6_paragraph_comprehension"])

# Auxiliary variable (saturated correlates): the complete speed test
# t13_straight_and_curved_capitals informs the likelihood without
# entering either regression. Continuing from the model above, the
# coefficients of the complete outcome are unchanged to working
# precision, while those of t26_flags move, since the auxiliary
# carries information about the rows where t26_flags is missing.
fit_aux <- mlmr_mv(cbind(t6_paragraph_comprehension,
                         t26_flags) ~
                     t7_sentence + t9_word_meaning,
                   data = holzinger_swineford,
                   ci_method = "wald",
                   auxiliary = "t13_straight_and_curved_capitals",
                   effect_sizes = FALSE)
coef(fit_aux)

Run the code above in your browser using DataLab