Skip to content

Commit 5fc6468

Browse files
authored
Add support for vcovHC for package glmmTMB (#1152)
* Add support for `vcovHC` for package glmmTMB Fixes #1151 * fix * fix * fixes * fix * add test * fix * add test
1 parent dbf3eea commit 5fc6468

File tree

6 files changed

+124
-39
lines changed

6 files changed

+124
-39
lines changed

DESCRIPTION

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Type: Package
22
Package: parameters
33
Title: Processing of Model Parameters
4-
Version: 0.28.0.1
4+
Version: 0.28.0.2
55
Authors@R:
66
c(person(given = "Daniel",
77
family = "Lüdecke",
@@ -80,7 +80,7 @@ Depends:
8080
Imports:
8181
bayestestR (>= 0.16.1),
8282
datawizard (>= 1.2.0),
83-
insight (>= 1.3.1),
83+
insight (>= 1.4.0),
8484
graphics,
8585
methods,
8686
stats,
@@ -138,7 +138,7 @@ Suggests:
138138
geepack,
139139
ggplot2,
140140
GLMMadaptive,
141-
glmmTMB (>= 1.1.10),
141+
glmmTMB (>= 1.1.12),
142142
glmtoolbox,
143143
GPArotation,
144144
gt,
@@ -212,7 +212,7 @@ Suggests:
212212
svylme,
213213
testthat (>= 3.2.1),
214214
tidyselect,
215-
tinytable (>= 0.1.0),
215+
tinytable (>= 0.13.0),
216216
TMB,
217217
truncreg,
218218
vdiffr,
@@ -231,3 +231,4 @@ Config/testthat/parallel: true
231231
Config/Needs/website: easystats/easystatstemplate
232232
Config/Needs/check: stan-dev/cmdstanr
233233
Config/rcmdcheck/ignore-inconsequential-notes: true
234+
Remotes: easystats/insight

R/4_standard_error.R

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ standard_error.default <- function(model,
113113
...
114114
)
115115
se <- sqrt(diag(.vcov))
116+
117+
# for glmmTMB, we need to remove theta-rows
118+
if (inherits(model, "glmmTMB")) {
119+
# remove theta-rows
120+
theta_rows <- startsWith(names(se), "theta_")
121+
se <- se[!theta_rows]
122+
}
116123
}
117124

118125
# classical SE from summary()

R/methods_glmmTMB.R

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ model_parameters.glmmTMB <- function(model,
179179
group_level = FALSE,
180180
exponentiate = FALSE,
181181
p_adjust = NULL,
182+
vcov = NULL,
183+
vcov_args = NULL,
182184
wb_component = FALSE,
183185
include_info = getOption("parameters_mixed_info", FALSE),
184186
include_sigma = FALSE,
@@ -188,14 +190,6 @@ model_parameters.glmmTMB <- function(model,
188190
...) {
189191
insight::check_if_installed("glmmTMB")
190192

191-
# validation check, warn if unsupported argument is used.
192-
dot_args <- .check_dots(
193-
dots = list(...),
194-
not_allowed = c("vcov", "vcov_args"),
195-
class(model)[1],
196-
verbose = verbose
197-
)
198-
199193
# p-values, CI and se might be based on different df-methods
200194
ci_method <- .check_df_method(ci_method)
201195

@@ -280,14 +274,14 @@ model_parameters.glmmTMB <- function(model,
280274
keep_parameters = NULL,
281275
drop_parameters = NULL,
282276
verbose = verbose,
283-
vcov = NULL,
284-
vcov_args = NULL,
277+
vcov = vcov,
278+
vcov_args = vcov_args,
285279
keep_component_column = component != "conditional",
286280
include_sigma = include_sigma,
287281
wb_component = wb_component,
288282
include_info = include_info
289283
)
290-
fun_args <- c(fun_args, dot_args)
284+
fun_args <- c(fun_args, list(...))
291285
params <- do.call(".extract_parameters_generic", fun_args)
292286
}
293287

@@ -501,7 +495,6 @@ model_parameters.glmmTMB <- function(model,
501495

502496
# ci -----
503497

504-
505498
#' @export
506499
ci.glmmTMB <- function(x,
507500
ci = 0.95,
@@ -524,15 +517,6 @@ ci.glmmTMB <- function(x,
524517
return(NULL)
525518
}
526519

527-
# validation check, warn if unsupported argument is used.
528-
dot_args <- .check_dots(
529-
dots = list(...),
530-
not_allowed = c("vcov", "vcov_args"),
531-
class(x)[1],
532-
function_name = "ci",
533-
verbose = verbose
534-
)
535-
536520
# profiled CIs
537521
if (method == "profile") {
538522
if (length(ci) > 1) {
@@ -560,6 +544,8 @@ ci.glmmTMB <- function(x,
560544
standard_error.glmmTMB <- function(model,
561545
effects = "fixed",
562546
component = "all",
547+
vcov = NULL,
548+
vcov_args = NULL,
563549
verbose = TRUE,
564550
...) {
565551
component <- insight::validate_argument(
@@ -571,16 +557,10 @@ standard_error.glmmTMB <- function(model,
571557
c("fixed", "random")
572558
)
573559

574-
dot_args <- .check_dots(
575-
dots = list(...),
576-
not_allowed = c("vcov", "vcov_args"),
577-
class(model)[1],
578-
function_name = "standard_error",
579-
verbose = verbose
580-
)
581-
582560
if (effects == "random") {
583561
.se_random_effects_glmmTMB(model)
562+
} else if (!is.null(vcov)) {
563+
.se_robust_glmmTMB(model, component, vcov, vcov_args, verbose, ...)
584564
} else {
585565
.se_fixed_effects_glmmTMB(model, component, verbose)
586566
}
@@ -591,7 +571,7 @@ standard_error.glmmTMB <- function(model,
591571

592572

593573
# extract standard errors for fixed effects parameters
594-
.se_fixed_effects_glmmTMB <- function(model, component, verbose) {
574+
.se_fixed_effects_glmmTMB <- function(model, component, verbose = TRUE) {
595575
if (is.null(.check_component(model, component, verbose = verbose))) {
596576
return(NULL)
597577
}
@@ -614,6 +594,24 @@ standard_error.glmmTMB <- function(model,
614594
}
615595

616596

597+
# extract robust standard errors for fixed effects parameters
598+
.se_robust_glmmTMB <- function(model,
599+
component = "all",
600+
vcov,
601+
vcov_args = NULL,
602+
verbose = TRUE,
603+
...) {
604+
fun_args <- list(
605+
model,
606+
component = component,
607+
vcov = vcov,
608+
vcov_args = vcov_args
609+
)
610+
fun_args <- c(fun_args, list(...))
611+
do.call("standard_error.default", fun_args)
612+
}
613+
614+
617615
# extract standard errors for random effects parameters
618616
.se_random_effects_glmmTMB <- function(model) {
619617
if (!all(insight::check_if_installed(c("TMB", "glmmTMB"), quietly = TRUE))) {

man/model_parameters.glmmTMB.Rd

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/_snaps/glmmTMB.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,3 +215,40 @@
215215
----------------------------------------------------
216216
SD (Intercept: persons) | 1.17 | [0.54, 2.57]
217217

218+
# robust SE/VCOV
219+
220+
Code
221+
print(out, table_width = Inf)
222+
Output
223+
# Fixed Effects (Count Model)
224+
225+
Parameter | Log-Mean | SE | 95% CI | z | p
226+
---------------------------------------------------------------
227+
(Intercept) | 1.26 | 0.46 | [ 0.36, 2.17] | 2.74 | 0.006
228+
child | -1.14 | 0.30 | [-1.73, -0.55] | -3.80 | < .001
229+
camper [1] | 0.73 | 0.41 | [-0.06, 1.53] | 1.80 | 0.072
230+
231+
# Fixed Effects (Zero-Inflation Component)
232+
233+
Parameter | Log-Odds | SE | 95% CI | z | p
234+
---------------------------------------------------------------
235+
(Intercept) | -0.39 | 0.58 | [-1.52, 0.75] | -0.67 | 0.501
236+
child | 2.05 | 0.39 | [ 1.30, 2.81] | 5.33 | < .001
237+
camper [1] | -1.01 | 0.39 | [-1.77, -0.24] | -2.59 | 0.010
238+
239+
# Random Effects Variances
240+
241+
Parameter | Coefficient | 95% CI
242+
----------------------------------------------------
243+
SD (Intercept: persons) | 0.93 | [0.46, 1.89]
244+
245+
# Random Effects (Zero-Inflation Component)
246+
247+
Parameter | Coefficient | 95% CI
248+
----------------------------------------------------
249+
SD (Intercept: persons) | 1.17 | [0.54, 2.57]
250+
Message
251+
252+
Uncertainty intervals (equal-tailed) and p-values (two-tailed) computed
253+
using a Wald z-distribution approximation.
254+

tests/testthat/test-glmmTMB.R

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@ withr::with_options(
3030
data = Salamanders
3131
))
3232

33-
test_that("unsupported args", {
34-
expect_message(model_parameters(m1, vcov = "HC3", effects = "fixed", component = "conditional"))
35-
expect_message(model_parameters(m1, vcov = "HC3"))
36-
})
37-
3833
test_that("ci", {
3934
expect_equal(
4035
ci(m1)$CI_low,
@@ -766,5 +761,21 @@ withr::with_options(
766761
expect_identical(nrow(out), 46L)
767762
expect_equal(out$Coefficient, unlist(glmmTMB::ranef(m)), ignore_attr = TRUE, tolerance = 1e-4)
768763
})
764+
765+
test_that("robust SE/VCOV", {
766+
skip_if_not_installed("sandwich")
767+
skip_if(packageVersion("insight") <= "1.4.0")
768+
769+
out1 <- standard_error(m1)
770+
out2 <- sqrt(diag(insight::get_varcov(m1, component = "all")))
771+
expect_equal(out1$SE, out2[1:6], ignore_attr = TRUE, tolerance = 1e-4)
772+
773+
out1 <- standard_error(m1, vcov = "HC0")
774+
out2 <- sqrt(diag(insight::get_varcov(m1, vcov = "HC0", component = "all")))
775+
expect_equal(out1$SE, out2[1:6], ignore_attr = TRUE, tolerance = 1e-4)
776+
777+
out <- model_parameters(m1, vcov = "HC0")
778+
expect_snapshot(print(out, table_width = Inf))
779+
})
769780
}
770781
)

0 commit comments

Comments
 (0)