|
5 | 5 | #'
|
6 | 6 | #' @param x A mixed model.
|
7 | 7 | #' @param tolerance Indicates up to which value the convergence result is
|
8 |
| -#' accepted. The larger `tolerance` is, the stricter the test |
9 |
| -#' will be. |
| 8 | +#' accepted. The larger `tolerance` is, the stricter the test |
| 9 | +#' will be. |
| 10 | +#' @param check Indicates whether singularity check should be carried out for |
| 11 | +#' the full model (`"model"`, the default), or per random effects term (`"terms"`). |
10 | 12 | #' @param ... Currently not used.
|
11 | 13 | #'
|
12 | 14 | #' @return `TRUE` if the model fit is singular.
|
|
95 | 97 | #' Reaction ~ Days + (1 | mygrp / mysubgrp) + (1 | Subject),
|
96 | 98 | #' data = sleepstudy
|
97 | 99 | #' )
|
| 100 | +#' # any singular fits? |
98 | 101 | #' check_singularity(model)
|
| 102 | +#' # singular fit for which particular random effects terms? |
| 103 | +#' check_singularity(model, check = "terms") |
99 | 104 | #'
|
100 | 105 | #' \dontrun{
|
101 | 106 | #' # Fixing singularity issues using priors in glmmTMB
|
@@ -129,35 +134,61 @@ check_singularity <- function(x, tolerance = 1e-5, ...) {
|
129 | 134 |
|
130 | 135 |
|
131 | 136 | #' @export
|
132 |
| -check_singularity.merMod <- function(x, tolerance = 1e-5, ...) { |
133 |
| - insight::check_if_installed("lme4") |
134 |
| - |
135 |
| - theta <- lme4::getME(x, "theta") |
136 |
| - # diagonal elements are identifiable because they are fitted |
137 |
| - # with a lower bound of zero ... |
138 |
| - diag.element <- lme4::getME(x, "lower") == 0 |
139 |
| - any(abs(theta[diag.element]) < tolerance) |
| 137 | +check_singularity.merMod <- function(x, tolerance = 1e-5, check = "model", ...) { |
| 138 | + insight::check_if_installed(c("lme4", "reformulas")) |
| 139 | + |
| 140 | + check <- insight::validate_argument(check, c("model", "terms")) |
| 141 | + result <- list() |
| 142 | + vv <- lme4::VarCorr(x) |
| 143 | + |
| 144 | + re_names <- vapply( |
| 145 | + reformulas::findbars(stats::formula(x)), |
| 146 | + insight::safe_deparse, |
| 147 | + FUN.VALUE = character(1) |
| 148 | + ) |
| 149 | + result <- vapply( |
| 150 | + vv, |
| 151 | + function(x) det(x) < tolerance, |
| 152 | + FUN.VALUE = logical(1) |
| 153 | + ) |
| 154 | + |
| 155 | + switch(check, |
| 156 | + model = any(unlist(result, use.names = FALSE)), |
| 157 | + insight::compact_list(result) |
| 158 | + ) |
140 | 159 | }
|
141 | 160 |
|
142 | 161 | #' @export
|
143 | 162 | check_singularity.rlmerMod <- check_singularity.merMod
|
144 | 163 |
|
145 | 164 |
|
| 165 | +#' @rdname check_singularity |
146 | 166 | #' @export
|
147 |
| -check_singularity.glmmTMB <- function(x, tolerance = 1e-5, ...) { |
148 |
| - insight::check_if_installed("lme4") |
| 167 | +check_singularity.glmmTMB <- function(x, tolerance = 1e-5, check = "model", ...) { |
| 168 | + insight::check_if_installed(c("lme4", "reformulas")) |
149 | 169 |
|
150 |
| - eigen_values <- list() |
| 170 | + check <- insight::validate_argument(check, c("model", "terms")) |
| 171 | + result <- list() |
151 | 172 | vv <- lme4::VarCorr(x)
|
152 |
| - for (component in c("cond", "zi")) { |
153 |
| - for (i in seq_along(vv[[component]])) { |
154 |
| - eigen_values <- c( |
155 |
| - eigen_values, |
156 |
| - list(eigen(vv[[component]][[i]], only.values = TRUE)$values) |
157 |
| - ) |
158 |
| - } |
| 173 | + |
| 174 | + for (component in c("cond", "zi", "disp")) { |
| 175 | + re_names <- vapply( |
| 176 | + reformulas::findbars(stats::formula(x, component = component)), |
| 177 | + insight::safe_deparse, |
| 178 | + FUN.VALUE = character(1) |
| 179 | + ) |
| 180 | + result[[component]] <- vapply( |
| 181 | + vv[[component]], |
| 182 | + function(x) det(x) < tolerance, |
| 183 | + FUN.VALUE = logical(1) |
| 184 | + ) |
| 185 | + names(result[[component]]) <- re_names |
159 | 186 | }
|
160 |
| - any(vapply(eigen_values, min, numeric(1), na.rm = TRUE) < tolerance) |
| 187 | + |
| 188 | + switch(check, |
| 189 | + model = any(unlist(result, use.names = FALSE)), |
| 190 | + insight::compact_list(result) |
| 191 | + ) |
161 | 192 | }
|
162 | 193 |
|
163 | 194 |
|
|
0 commit comments