diff --git a/DESCRIPTION b/DESCRIPTION index d4f19a476..8df947361 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: marginaleffects Title: Predictions, Comparisons, Slopes, Marginal Means, and Hypothesis Tests -Version: 0.22.0.3 +Version: 0.22.0.4 Authors@R: c(person(given = "Vincent", family = "Arel-Bundock", @@ -119,6 +119,7 @@ Suggests: numDeriv, nycflights13, optmatch, + ordbetareg, ordinal, parameters, parsnip, diff --git a/NEWS.md b/NEWS.md index e94bf46b9..d5b408271 100644 --- a/NEWS.md +++ b/NEWS.md @@ -8,6 +8,7 @@ Bugs: * `multinom_weightit` models with `insight` version 0.20.4 and greater would produce an error. Thanks to Noah Greifer. * `hypotheses(joint = TRUE)` would throw an error if sample sizes could not be computed, even if they were not needed. Thanks to Noah Greifer. * `hypotheses(joint = TRUE)` respects the `vcov` argument. Thanks to @kennchua for report #1214. +* `ordbetareg` models in `glmmTMB` are now supported. Thanks to @jgeller112 for code contribution #1221. Breaking change: diff --git a/R/methods_glmmTMB.R b/R/methods_glmmTMB.R index 76f65f6ae..89422dd3d 100755 --- a/R/methods_glmmTMB.R +++ b/R/methods_glmmTMB.R @@ -41,7 +41,35 @@ get_predict.glmmTMB <- function(model, #' @rdname get_vcov #' @export get_vcov.glmmTMB <- function(model, ...) { + # Extract the full covariance matrix out <- stats::vcov(model, full = TRUE) + + # Extract the fixed-effect coefficient names from get_coef + coef_names <- names(get_coef.glmmTMB(model)) + + # Handle dispersion and conditional terms + cleaned_coef_names <- gsub("^cond~", "", coef_names) # Remove cond~ for conditional terms + cleaned_coef_names <- gsub("^disp~", "d~", cleaned_coef_names) # Map disp~ to d~ for dispersion terms + + # The 'upper cutoff' and 'lower cutoff' will remain in both, so no removal + + # Get the current row and column names from the covariance matrix + current_names <- rownames(out) + + # Match cleaned coef_names with current names in the covariance matrix + matched_indices <- match(current_names, cleaned_coef_names) + + # Replace row/column names only where there is a valid match + valid_indices <- which(!is.na(matched_indices)) + + if (length(valid_indices) > 0) { + # Apply the correct names from coef_names to matched rows/columns in the covariance matrix + rownames(out)[valid_indices] <- coef_names[matched_indices[valid_indices]] + colnames(out)[valid_indices] <- coef_names[matched_indices[valid_indices]] + } else { + warning("No matching terms found between the covariance matrix and fixed-effect coefficients.") + } + return(out) } @@ -50,8 +78,13 @@ get_vcov.glmmTMB <- function(model, ...) { #' @rdname get_coef #' @export get_coef.glmmTMB <- function(model, ...) { + # Extract the fixed-effect coefficients out <- unlist(glmmTMB::fixef(model)) + + # Apply the gsub logic to rename terms (cond~, disp~, etc.) names(out) <- gsub("^(cond|zi|disp)\\.", "\\1~", names(out)) + + # No removal of "lower cutoff" and "upper cutoff" - they remain in place return(out) } diff --git a/inst/tinytest/test-pkg-glmmTMB.R b/inst/tinytest/test-pkg-glmmTMB.R index c1a7f81f4..3b9a32e80 100644 --- a/inst/tinytest/test-pkg-glmmTMB.R +++ b/inst/tinytest/test-pkg-glmmTMB.R @@ -259,6 +259,18 @@ expect_false(anyNA(s$std.error)) +# Issue 1221 +ord_fit <- glmmTMB(formula=therm/100 ~ F_EDUCCAT2_FINAL + F_INCOME_FINAL + (1|F_INCOME_FINAL), + data=pew, + family = ordbeta) +p <- avg_predictions(ord_fit, re.form = NA) +expect_false(anyNA(p$estimate)) +expect_false(anyNA(p$std.error)) + + + + + source("helpers.R") rm(list = ls())