|
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