Skip to content

Commit d7c296f

Browse files
committed
improved check_singularity
Fixes #796
1 parent f1ffa8c commit d7c296f

File tree

4 files changed

+72
-22
lines changed

4 files changed

+72
-22
lines changed

DESCRIPTION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Type: Package
22
Package: performance
33
Title: Assessment of Regression Models Performance
4-
Version: 0.13.0
4+
Version: 0.13.0.1
55
Authors@R:
66
c(person(given = "Daniel",
77
family = "Lüdecke",

NEWS.md

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
# performance (devel)
2+
3+
## Changes
4+
5+
* Singularity checks with `check_singularity()` are now more efficient and also
6+
include the random effects for the dispersion component (from package *glmmTMB*).
7+
Furthermore, a `check` argument allows to check for general singularity (for
8+
the full model), or can return singularity checks for each random effects term
9+
separately.
10+
111
# performance 0.13.0
212

313
## Breaking changes

R/check_singularity.R

+52-21
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
#'
66
#' @param x A mixed model.
77
#' @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"`).
1012
#' @param ... Currently not used.
1113
#'
1214
#' @return `TRUE` if the model fit is singular.
@@ -95,7 +97,10 @@
9597
#' Reaction ~ Days + (1 | mygrp / mysubgrp) + (1 | Subject),
9698
#' data = sleepstudy
9799
#' )
100+
#' # any singular fits?
98101
#' check_singularity(model)
102+
#' # singular fit for which particular random effects terms?
103+
#' check_singularity(model, check = "terms")
99104
#'
100105
#' \dontrun{
101106
#' # Fixing singularity issues using priors in glmmTMB
@@ -129,35 +134,61 @@ check_singularity <- function(x, tolerance = 1e-5, ...) {
129134

130135

131136
#' @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::compalist(result)
158+
)
140159
}
141160

142161
#' @export
143162
check_singularity.rlmerMod <- check_singularity.merMod
144163

145164

165+
#' @rdname check_singularity
146166
#' @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"))
149169

150-
eigen_values <- list()
170+
check <- insight::validate_argument(check, c("model", "terms"))
171+
result <- list()
151172
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
159186
}
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::compalist(result)
191+
)
161192
}
162193

163194

man/check_singularity.Rd

+9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)