From eb9a3c4a24f5a8f64e10718f28185356dd54115f Mon Sep 17 00:00:00 2001 From: Vincent Arel-Bundock Date: Fri, 30 Aug 2024 22:06:59 -0400 Subject: [PATCH] Support `glmtoolbox::glmgee()` (#1207) * support glmtoolbox::glmgee() * fixup test * test fixup * supported models --- DESCRIPTION | 4 +++- NAMESPACE | 3 +++ NEWS.md | 12 ++++++++---- R/methods_glmtoolbox.R | 29 +++++++++++++++++++++++++++++ R/sanity_model.R | 1 + R/type_dictionary.R | 1 + data-raw/supported_models.csv | 1 + inst/tinytest/test-pkg-glmtoolbox.R | 14 ++++++++++++++ man/get_coef.Rd | 10 +++++++--- man/get_predict.Rd | 15 +++++++++------ man/set_coef.Rd | 12 ++++++++---- 11 files changed, 84 insertions(+), 18 deletions(-) create mode 100644 R/methods_glmtoolbox.R create mode 100644 inst/tinytest/test-pkg-glmtoolbox.R diff --git a/DESCRIPTION b/DESCRIPTION index 4c69d38aa..c6617ea30 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: marginaleffects Title: Predictions, Comparisons, Slopes, Marginal Means, and Hypothesis Tests -Version: 0.21.0.21 +Version: 0.21.0.22 Authors@R: c(person(given = "Vincent", family = "Arel-Bundock", @@ -92,6 +92,7 @@ Suggests: ggplot2, ggrepel, glmmTMB, + glmtoolbox, glmx, haven, here, @@ -237,6 +238,7 @@ Collate: 'methods_flexsurv.R' 'methods_gamlss.R' 'methods_glmmTMB.R' + 'methods_glmtoolbox.R' 'methods_glmx.R' 'methods_lme4.R' 'methods_mclogit.R' diff --git a/NAMESPACE b/NAMESPACE index a6095fb17..9c2e7b48f 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -14,6 +14,7 @@ S3method(get_coef,data.frame) S3method(get_coef,default) S3method(get_coef,gam) S3method(get_coef,gamlss) +S3method(get_coef,glmgee) S3method(get_coef,glmmTMB) S3method(get_coef,lmerMod) S3method(get_coef,lmerModLmerTest) @@ -62,6 +63,7 @@ S3method(get_predict,flexsurvreg) S3method(get_predict,gamlss) S3method(get_predict,glimML) S3method(get_predict,glm) +S3method(get_predict,glmgee) S3method(get_predict,glmmPQL) S3method(get_predict,glmmTMB) S3method(get_predict,gsm) @@ -143,6 +145,7 @@ S3method(set_coef,flexsurvreg) S3method(set_coef,gamlss) S3method(set_coef,glimML) S3method(set_coef,glm) +S3method(set_coef,glmgee) S3method(set_coef,glmmPQL) S3method(set_coef,glmmTMB) S3method(set_coef,glmx) diff --git a/NEWS.md b/NEWS.md index 5e26b184d..f6c393975 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,13 +7,17 @@ Breaking changes: * `type="invlink(link)"` is no longer default in `avg_predictions()` or when calling `predictions()` with the `by` argument. It is still default in `predictions()` without the `by` argument. The backtransform strategy is still available with by setting `type="invlink(link)"` explicitly. * The `type` argument in `plot_comparisons()` now defaults to `NULL`, which is now consistent with `comparisons()` and `avg_comparisons()`. Before, the default was `type="response"`. Thanks to @giakhang1906 for report #1202. -New: +New models supported: + +* `stpm2`, `pstpm2`, `gsm`, and `aft` models from `rstpm2`. Thanks to @aghaynes and @mclements. +* `glm_weightit`, `coxph_weightit`, `multinom_weightit`, and `ordinal_weightit` models from `Weightit`. Thanks to @ngreifer. +* `glmmgee` from the `glmtoolbox` package. Thanks to @adrianolszewski for the request and @lhvanegasp for help with implementation. + +New feautres: -* `hypotheses(joint=TRUE)`: do not call `stats::nobs()` unless necessary. -* Added support for `stpm2`, `pstpm2`, `gsm`, and `aft` models from `rstpm2`. Thanks to @aghaynes and @mclements. -* Added support for `glm_weightit`, `coxph_weightit`, `multinom_weightit`, and `ordinal_weightit` models from `Weightit`. Thanks to @ngreifer. * Parallel computation with `future` is more efficient by chunking tasks to avoid passing large objects to every worker for every future. Issue #1158. * All columns of `newdata` are passed to the `hypothesis` function when `newdata` is supplied explicitly. Thanks to @gravesti for report #1175. +* `hypotheses(joint=TRUE)`: do not call `stats::nobs()` unless necessary. * `hypotheses()` supports formulas in the `hypothesis` argument: `hypotheses(model, hypothesis = ratio ~ reference)` * Global option: `options("marginaleffects_print_omit" = "s.value")` * Round significant digits for labels in `plot_predictions(mod, condition = list(x = "fivenum"))` diff --git a/R/methods_glmtoolbox.R b/R/methods_glmtoolbox.R new file mode 100644 index 000000000..9db3d4bdf --- /dev/null +++ b/R/methods_glmtoolbox.R @@ -0,0 +1,29 @@ +#' @include get_coef.R +#' @rdname get_coef +#' @export +get_coef.glmgee <- function(model, ...) { + b <- model$coefficients + b <- setNames(as.vector(b), row.names(b)) + return(b) +} + +#' @include set_coef.R +#' @rdname set_coef +#' @export +set_coef.glmgee <- function(model, coefs, ...) { + out <- model + idx <- match(row.names(out$coefficients), names(coefs)) + out$coefficients[, 1] <- coefs[idx] + return(out) +} + +#' @include get_predict.R +#' @rdname get_predict +#' @export +get_predict.glmgee <- function(model, newdata, ...) { + Yhat <- predict(model, newdata = newdata, type = "response") + out <- data.frame( + rowid = seq_len(nrow(Yhat)), + estimate = as.vector(Yhat)) + return(out) +} \ No newline at end of file diff --git a/R/sanity_model.R b/R/sanity_model.R index dbee0cee6..09655cda5 100644 --- a/R/sanity_model.R +++ b/R/sanity_model.R @@ -58,6 +58,7 @@ sanity_model_supported_class <- function(model) { "glmerMod", "glmrob", "glmmTMB", + "glmgee", c("glmmPQL", "lme"), "glimML", "glmx", diff --git a/R/type_dictionary.R b/R/type_dictionary.R index 12e6dff61..b6192c6cc 100644 --- a/R/type_dictionary.R +++ b/R/type_dictionary.R @@ -85,6 +85,7 @@ glm,response glm,link glmerMod,response glmerMod,link +glmgee,response glmrob,response glmrob,link glmmTMB,response diff --git a/data-raw/supported_models.csv b/data-raw/supported_models.csv index 5ff572658..5877edb05 100644 --- a/data-raw/supported_models.csv +++ b/data-raw/supported_models.csv @@ -42,6 +42,7 @@ gam,gam,TRUE,TRUE,,,U,U,TRUE,TRUE gamlss,gamlss,TRUE,TRUE,,,U,U,TRUE,TRUE geepack,geeglm,TRUE,TRUE,,,U,U,TRUE,TRUE glmmTMB,glmmTMB,TRUE,FALSE,,,U,U,TRUE,TRUE +glmtoolbox,glmgee,TRUE,TRUE,,, ,,, glmx,glmx,TRUE,TRUE,,,TRUE,U,U,U ivreg,ivreg,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,U,U lme4,glmer,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE diff --git a/inst/tinytest/test-pkg-glmtoolbox.R b/inst/tinytest/test-pkg-glmtoolbox.R new file mode 100644 index 000000000..baff81244 --- /dev/null +++ b/inst/tinytest/test-pkg-glmtoolbox.R @@ -0,0 +1,14 @@ +source("helpers.R") +using("marginaleffects") +requiet("glmtoolbox") + +data(spruces) +mod <- size ~ poly(days,4) + treat +fit <- glmgee(mod, id=tree, family=Gamma(log), corstr="AR-M-dependent(1)", data=spruces) + +s <- avg_slopes(fit) +expect_inherits(s, "slopes") +p <- avg_predictions(fit, by = "treat") +expect_inherits(p, "predictions") +k <- avg_comparisons(fit) +expect_inherits(k, "comparisons") diff --git a/man/get_coef.Rd b/man/get_coef.Rd index 33b1fc456..ab041b218 100644 --- a/man/get_coef.Rd +++ b/man/get_coef.Rd @@ -2,9 +2,10 @@ % Please edit documentation in R/get_coef.R, R/methods_MASS.R, R/methods_afex.R, % R/methods_betareg.R, R/methods_nnet.R, R/methods_brglm2.R, R/methods_brms.R, % R/methods_dataframe.R, R/methods_gamlss.R, R/methods_glmmTMB.R, -% R/methods_lme4.R, R/methods_mclogit.R, R/methods_mgcv.R, R/methods_mlm.R, -% R/methods_sampleSelection.R, R/methods_scam.R, R/methods_stats.R, -% R/methods_survey.R, R/methods_tidymodels.R +% R/methods_glmtoolbox.R, R/methods_lme4.R, R/methods_mclogit.R, +% R/methods_mgcv.R, R/methods_mlm.R, R/methods_sampleSelection.R, +% R/methods_scam.R, R/methods_stats.R, R/methods_survey.R, +% R/methods_tidymodels.R \name{get_coef} \alias{get_coef} \alias{get_coef.default} @@ -18,6 +19,7 @@ \alias{get_coef.data.frame} \alias{get_coef.gamlss} \alias{get_coef.glmmTMB} +\alias{get_coef.glmgee} \alias{get_coef.merMod} \alias{get_coef.lmerModLmerTest} \alias{get_coef.lmerMod} @@ -55,6 +57,8 @@ get_coef(model, ...) \method{get_coef}{glmmTMB}(model, ...) +\method{get_coef}{glmgee}(model, ...) + \method{get_coef}{merMod}(model, ...) \method{get_coef}{lmerModLmerTest}(model, ...) diff --git a/man/get_predict.Rd b/man/get_predict.Rd index 14a1c3052..9275573d9 100644 --- a/man/get_predict.Rd +++ b/man/get_predict.Rd @@ -4,12 +4,12 @@ % R/methods_betareg.R, R/methods_bife.R, R/methods_biglm.R, R/methods_nnet.R, % R/methods_brglm2.R, R/methods_brms.R, R/methods_crch.R, R/methods_dbarts.R, % R/methods_fixest.R, R/methods_flexsurv.R, R/methods_gamlss.R, -% R/methods_glmmTMB.R, R/methods_lme4.R, R/methods_mclogit.R, -% R/methods_mhurdle.R, R/methods_mlogit.R, R/methods_mlr3.R, -% R/methods_ordinal.R, R/methods_quantreg.R, R/methods_rms.R, -% R/methods_robustlmm.R, R/methods_rstanarm.R, R/methods_rstpm2.R, -% R/methods_stats.R, R/methods_survey.R, R/methods_survival.R, -% R/methods_tidymodels.R, R/methods_tobit1.R +% R/methods_glmmTMB.R, R/methods_glmtoolbox.R, R/methods_lme4.R, +% R/methods_mclogit.R, R/methods_mhurdle.R, R/methods_mlogit.R, +% R/methods_mlr3.R, R/methods_ordinal.R, R/methods_quantreg.R, +% R/methods_rms.R, R/methods_robustlmm.R, R/methods_rstanarm.R, +% R/methods_rstpm2.R, R/methods_stats.R, R/methods_survey.R, +% R/methods_survival.R, R/methods_tidymodels.R, R/methods_tobit1.R \name{get_predict} \alias{get_predict} \alias{get_predict.default} @@ -30,6 +30,7 @@ \alias{get_predict.flexsurvreg} \alias{get_predict.gamlss} \alias{get_predict.glmmTMB} +\alias{get_predict.glmgee} \alias{get_predict.merMod} \alias{get_predict.lmerModLmerTest} \alias{get_predict.lmerMod} @@ -103,6 +104,8 @@ get_predict(model, newdata, type, ...) ... ) +\method{get_predict}{glmgee}(model, newdata, ...) + \method{get_predict}{merMod}(model, newdata = insight::get_data(model), type = "response", ...) \method{get_predict}{lmerModLmerTest}(model, newdata = insight::get_data(model), type = "response", ...) diff --git a/man/set_coef.Rd b/man/set_coef.Rd index a33ebe8cc..32349355f 100644 --- a/man/set_coef.Rd +++ b/man/set_coef.Rd @@ -3,10 +3,11 @@ % R/methods_Rchoice.R, R/methods_afex.R, R/methods_aod.R, R/methods_betareg.R, % R/methods_nnet.R, R/methods_crch.R, R/methods_dataframe.R, % R/methods_flexsurv.R, R/methods_gamlss.R, R/methods_glmmTMB.R, -% R/methods_glmx.R, R/methods_lme4.R, R/methods_mlm.R, R/methods_nlme.R, -% R/methods_pscl.R, R/methods_robustlmm.R, R/methods_rstpm2.R, -% R/methods_sampleSelection.R, R/methods_scam.R, R/methods_stats.R, -% R/methods_survey.R, R/methods_survival.R, R/methods_tidymodels.R +% R/methods_glmtoolbox.R, R/methods_glmx.R, R/methods_lme4.R, +% R/methods_mlm.R, R/methods_nlme.R, R/methods_pscl.R, R/methods_robustlmm.R, +% R/methods_rstpm2.R, R/methods_sampleSelection.R, R/methods_scam.R, +% R/methods_stats.R, R/methods_survey.R, R/methods_survival.R, +% R/methods_tidymodels.R \name{set_coef} \alias{set_coef} \alias{set_coef.default} @@ -25,6 +26,7 @@ \alias{set_coef.flexsurvreg} \alias{set_coef.gamlss} \alias{set_coef.glmmTMB} +\alias{set_coef.glmgee} \alias{set_coef.glmx} \alias{set_coef.merMod} \alias{set_coef.lmerModLmerTest} @@ -83,6 +85,8 @@ set_coef(model, coefs, ...) \method{set_coef}{glmmTMB}(model, coefs, ...) +\method{set_coef}{glmgee}(model, coefs, ...) + \method{set_coef}{glmx}(model, coefs, ...) \method{set_coef}{merMod}(model, coefs, ...)