Nothing
#' @title Extract various information from mixed models
#' @name get_mixed_info
#'
#' @description Small helper function that returns essential information on
#' coefficients, model matrix, variance and correlation parameters, as well as
#' random effects parameters of mixed effects models as list. Mainly used for
#' internal purposes.
#'
#' @param model A mixed effects model.
#' @param verbose Toggle off warnings.
#' @param component For `glmmTMB` and `MixMod` models, this argument specifies
#' the component of the model to extract. Possible values are `"conditional"`
#' (default) and `"zero_inflated"` (or `"zi"`).
#' @param ... Not used.
#'
#' @return This function returns a list that has the same structure for any
#' mixed models with the following components:
#' - `beta` (contains fixed effects, as returned by `lme4::fixef(model)`)
#' - `X` (contains the model matrix, as returned by `lme4::getME(model, "X")`)
#' - `vc` (contains the variance and correlation parameters, as returned by
#' `lme4::VarCorr(model)`)
#' - `re` (random effects parameters, as returned by `lme4::ranef(model)`)
#'
#' @export
get_mixed_info <- function(model, ...) {
# sanity check
if (is.null(model)) {
return(NULL)
}
check_if_installed("lme4")
UseMethod("get_mixed_info")
}
#' @rdname get_mixed_info
#' @export
get_mixed_info.default <- function(model, verbose = TRUE, ...) {
mixed_effects_info <- list(
beta = lme4::fixef(model),
X = lme4::getME(model, "X"),
vc = lme4::VarCorr(model),
re = lme4::ranef(model)
)
.fix_mm_rank_deficiency(mixed_effects_info)
}
# helper ---------------------
.fix_mm_rank_deficiency <- function(mixed_effects_info) {
# fix rank deficiency
rankdef <- is.na(mixed_effects_info$beta)
if (any(rankdef)) {
rankdef_names <- names(mixed_effects_info$beta)[rankdef]
mixed_effects_info$beta <- mixed_effects_info$beta[setdiff(names(mixed_effects_info$beta), rankdef_names)]
}
mixed_effects_info
}
# methods ----------------------------
#' @rdname get_mixed_info
#' @export
get_mixed_info.glmmTMB <- function(model, component = "conditional", verbose = TRUE, ...) {
check_if_installed("glmmTMB")
component <- validate_argument(component, c("conditional", "zero_inflated", "zi"))
mixed_effects_info <- list(
beta = lme4::fixef(model),
X = lme4::getME(model, "X"),
vc = lme4::VarCorr(model),
re = lme4::ranef(model)
)
# extract requested component
if (component == "conditional") {
mixed_effects_info <- lapply(mixed_effects_info, .collapse_cond)
} else {
mixed_effects_info <- lapply(mixed_effects_info, .collapse_zi)
}
# for glmmTMB, tell user that dispersion model is ignored
if (!is.null(find_formula(model, verbose = FALSE)[["dispersion"]]) && verbose) {
format_warning("Effects of dispersion model are ignored.")
}
.fix_mm_rank_deficiency(mixed_effects_info)
}
#' @export
get_mixed_info.stanreg <- function(model, verbose = TRUE, ...) {
check_if_installed("rstanarm")
mixed_effects_info <- list(
beta = lme4::fixef(model),
X = rstanarm::get_x(model),
vc = lme4::VarCorr(model),
re = lme4::ranef(model)
)
.fix_mm_rank_deficiency(mixed_effects_info)
}
#' @export
get_mixed_info.lme <- function(model, verbose = TRUE, ...) {
check_if_installed("nlme")
re_names <- find_random(model, split_nested = TRUE, flatten = TRUE)
comp_x <- get_modelmatrix(model)
rownames(comp_x) <- seq_len(nrow(comp_x))
if (.is_nested_lme(model)) {
vals_vc <- .get_nested_lme_varcorr(model)
vals_re <- lme4::ranef(model)
} else {
vals_vc <- list(nlme::getVarCov(model))
vals_re <- list(lme4::ranef(model))
}
mixed_effects_info <- list(
beta = lme4::fixef(model),
X = comp_x,
vc = vals_vc,
re = vals_re
)
names(mixed_effects_info$re) <- re_names
names(mixed_effects_info$vc) <- re_names
# need specific class attribute for nlme, because it has a different structure
class(mixed_effects_info$vc) <- "VarCorr.lme"
.fix_mm_rank_deficiency(mixed_effects_info)
}
#' @export
get_mixed_info.MixMod <- function(model, component = "conditional", verbose = TRUE, ...) {
check_if_installed("GLMMadaptive")
component <- validate_argument(component, c("conditional", "zero_inflated", "zi"))
vc1 <- vc2 <- NULL
re_names <- find_random(model)
vc_cond <- !startsWith(colnames(model$D), "zi_")
if (any(vc_cond)) {
vc1 <- model$D[vc_cond, vc_cond, drop = FALSE]
attr(vc1, "stddev") <- sqrt(diag(vc1))
attr(vc1, "correlation") <- stats::cov2cor(model$D[vc_cond, vc_cond, drop = FALSE])
}
vc_zi <- startsWith(colnames(model$D), "zi_")
if (any(vc_zi)) {
colnames(model$D) <- gsub("^zi_(.*)", "\\1", colnames(model$D))
rownames(model$D) <- colnames(model$D)
vc2 <- model$D[vc_zi, vc_zi, drop = FALSE]
attr(vc2, "stddev") <- sqrt(diag(vc2))
attr(vc2, "correlation") <- stats::cov2cor(model$D[vc_zi, vc_zi, drop = FALSE])
}
model_deviance <- get_deviance(model, verbose = FALSE)
residual_df <- get_df(model, type = "residual", verbose = FALSE)
vc1 <- list(vc1)
names(vc1) <- re_names[[1]]
attr(vc1, "sc") <- sqrt(abs(model_deviance) / residual_df)
attr(vc1, "useSc") <- TRUE
if (!is.null(vc2)) {
vc2 <- list(vc2)
names(vc2) <- re_names[[2]]
attr(vc2, "sc") <- sqrt(abs(model_deviance) / residual_df)
attr(vc2, "useSc") <- FALSE
}
vcorr <- compact_list(list(vc1, vc2))
names(vcorr) <- c("cond", "zi")[seq_along(vcorr)]
mixed_effects_info <- list(
beta = lme4::fixef(model),
X = get_modelmatrix(model),
vc = vcorr,
re = list(lme4::ranef(model))
)
names(mixed_effects_info$re) <- model$id_name
# extract requested component
if (component == "conditional") {
mixed_effects_info <- lapply(mixed_effects_info, .collapse_cond)
} else {
mixed_effects_info <- lapply(mixed_effects_info, .collapse_zi)
}
# for glmmTMB, tell user that dispersion model is ignored
if (!is.null(find_formula(model, verbose = FALSE)[["dispersion"]]) && verbose) {
format_warning("Effects of dispersion model are ignored.")
}
.fix_mm_rank_deficiency(mixed_effects_info)
}
#' @export
get_mixed_info.mjoint <- function(model, verbose = TRUE, ...) {
re_names <- find_random(model, flatten = TRUE)
vcorr <- summary(model)$D
attr(vcorr, "stddev") <- sqrt(diag(vcorr))
attr(vcorr, "correlation") <- stats::cov2cor(vcorr)
vcorr <- list(vcorr)
names(vcorr) <- re_names[1]
attr(vcorr, "sc") <- model$coef$sigma2[[1]]
attr(vcorr, "useSc") <- TRUE
mixed_effects_info <- list(
beta = lme4::fixef(model),
X = matrix(1, nrow = n_obs(model), dimnames = list(NULL, "(Intercept)_1")),
vc = vcorr,
re = list(lme4::ranef(model))
)
names(mixed_effects_info$re) <- re_names[seq_along(mixed_effects_info$re)]
.fix_mm_rank_deficiency(mixed_effects_info)
}
#' @export
get_mixed_info.clmm <- function(model, verbose = TRUE, ...) {
check_if_installed("ordinal")
mm <- get_modelmatrix(model)
mixed_effects_info <- list(
beta = c("(Intercept)" = 1, stats::coef(model)[intersect(names(stats::coef(model)), colnames(mm))]),
X = mm,
vc = ordinal::VarCorr(model),
re = ordinal::ranef(model)
)
attr(mixed_effects_info$vc, "useSc") <- FALSE
.fix_mm_rank_deficiency(mixed_effects_info)
}
#' @export
get_mixed_info.glmmadmb <- function(model, verbose = TRUE, ...) {
check_if_installed("glmmadmb")
mixed_effects_info <- list(
beta = lme4::fixef(model),
X = get_modelmatrix(model),
vc = lme4::VarCorr(model),
re = lme4::ranef(model)
)
.fix_mm_rank_deficiency(mixed_effects_info)
}
#' @export
get_mixed_info.brmsfit <- function(model, verbose = TRUE, ...) {
check_if_installed("brms")
comp_x <- get_modelmatrix(model)
rownames(comp_x) <- seq_len(nrow(comp_x))
vc <- lapply(names(lme4::VarCorr(model)), function(i) {
element <- lme4::VarCorr(model)[[i]]
if (i != "residual__") {
if (is.null(element$cov)) {
out <- as.matrix(drop(element$sd[, 1])^2)
colnames(out) <- rownames(out) <- gsub("Intercept", "(Intercept)", rownames(element$sd), fixed = TRUE)
} else {
out <- as.matrix(drop(element$cov[, 1, ]))
colnames(out) <- rownames(out) <- gsub("Intercept", "(Intercept)", rownames(element$cov), fixed = TRUE)
}
attr(out, "sttdev") <- element$sd[, 1]
} else {
out <- NULL
}
out
})
vc <- compact_list(vc)
names(vc) <- setdiff(names(lme4::VarCorr(model)), "residual__")
attr(vc, "sc") <- lme4::VarCorr(model)$residual__$sd[1, 1]
fixef_params <- lme4::fixef(model)[, 1]
# remove sigma parameters
fixef_params <- fixef_params[!startsWith(names(fixef_params), "sigma_")]
mixed_effects_info <- list(
beta = fixef_params,
X = comp_x,
vc = vc,
re = lapply(lme4::ranef(model), function(re) {
reval <- as.data.frame(drop(re[, 1, ]))
colnames(reval) <- gsub("Intercept", "(Intercept)", dimnames(re)[[3]], fixed = TRUE)
reval
})
)
names(mixed_effects_info$beta) <- gsub("Intercept", "(Intercept)", names(mixed_effects_info$beta), fixed = TRUE)
.fix_mm_rank_deficiency(mixed_effects_info)
}
#' @export
get_mixed_info.cpglmm <- function(model, verbose = TRUE, ...) {
check_if_installed("cplm")
mixed_effects_info <- list(
beta = cplm::fixef(model),
X = cplm::model.matrix(model),
vc = cplm::VarCorr(model),
re = cplm::ranef(model)
)
attr(mixed_effects_info$vc, "useSc") <- FALSE
.fix_mm_rank_deficiency(mixed_effects_info)
}
#' @export
get_mixed_info.coxme <- function(model, verbose = TRUE, ...) {
check_if_installed("coxme")
mixed_effects_info <- list(
beta = coxme::fixef(model),
X = get_modelmatrix(model),
vc = coxme::VarCorr(model),
re = coxme::ranef(model)
)
# make sure we always have a matrix
mixed_effects_info$vc <- lapply(mixed_effects_info$vc, .fix_dimnames)
mixed_effects_info$re <- lapply(mixed_effects_info$re, .fix_dimnames)
# need specific class attribute for coxme, because it has a different structure
class(mixed_effects_info$vc) <- "VarCorr.coxme"
.fix_mm_rank_deficiency(mixed_effects_info)
}
# helper --------------------
.fix_dimnames <- function(x) {
if (!is.matrix(x)) {
x <- as.matrix(x)
}
if (is.null(rownames(x))) {
rownames(x) <- character(nrow(x))
}
if (is.null(colnames(x))) {
colnames(x) <- character(ncol(x))
}
rownames(x)[1] <- "(Intercept)"
colnames(x)[1] <- "(Intercept)"
x
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.