easystats / performance

:muscle: Models' quality and performance metrics (R2, ICC, LOO, AIC, BF, ...)
https://easystats.github.io/performance/
GNU General Public License v3.0
965 stars 87 forks source link

R-squared for glmmTMB (binomial) #719

Closed luroy closed 2 months ago

luroy commented 2 months ago

Hello, I would like to obtain the R-squared associated with a binomial regression model (using glmmTMB) with an observation-level random effect (ORLE) to correct for overdispersion. The model is as follows: bm<-glmmTMB(Tx_V~AB+Co1+(1|obs_V), weights=N_V, data = data, family="binomial") And the function performance::r2(bm) returns :

performance::r2(bm)
[1] NA

I get the same result with the typical two-column matrix cbind(successes,failures) ~ form. Altough the following function from MuMIn works (with warning messages) MuMIn::r.squaredGLMM(bm)["delta",]

     R2m        R2c 
0.09347473 0.39887149 
Warning messages:
1: 'r.squaredGLMM' now calculates a revised statistic. See the help page. 
2: In r.squaredGLMM.glmmTMB(bm_c_mod1.2TMB) :
  the effects of zero-inflation and dispersion model are ignored
3: the null model is correct only if all variables used by the original model remain unchanged.

I need the performance::r2 function to work, since it is required to obtain the summary()) of a Piecewise Structural Equation Modeling (package piecewiseSEM)

SEM<-psem(… [other models]…
bm<-glmmTMB(Tx_V~AB+Co1+(1|obs_V), weights=N_V, data = data, family="binomial")
)
summary(SEM,  direction = c("Co1 <- Tmi"))

Error in performance::r2(model)$R2_marginal : 
  $ operator is invalid for atomic vectors

Thank you for your attention to this matter, Léa

strengejacke commented 2 months ago

Do you have a reproducible example?

luroy commented 2 months ago

Do you have a reproducible example?

These data are not published. Can I send them to you by e-mail?

strengejacke commented 2 months ago

Yes, of course. Or simply create a toy example.

luroy commented 2 months ago

Thank you for your quick reply, please find enclosed simulated data to reproduce the following error

glmmTMB_performance_NA.txt

data<-read.table('clipboard', h=T)
> bm<-glmmTMB(Tx_V~AB+Co1+(1|obs_V), weights=N_V, data = data, family="binomial")
> summary(bm)
 Family: binomial  ( logit )
Formula:          Tx_V ~ AB + Co1 + (1 | obs_V)
Data: data
Weights: N_V

     AIC      BIC   logLik deviance df.resid 
   634.2    643.6   -313.1    626.2       73 

Random effects:

Conditional model:
 Groups Name        Variance Std.Dev.
 obs_V  (Intercept) 2.457    1.568   
Number of obs: 77, groups:  obs_V, 77

Conditional model:
              Estimate Std. Error z value Pr(>|z|)
(Intercept) -0.0195336  0.3753013  -0.052    0.958
AB           0.0001774  0.0002368   0.749    0.454
Co1          0.2431589  0.1686284   1.442    0.149

> performance::r2(bm)
[1] NA

Once again, thank you for your help!

bwiernik commented 2 months ago

Does r2_somers() work for you? In general, I recommend Somer's D when working with binomial models

luroy commented 2 months ago

@bwiernik Thanks for your reply. Using my example, it does not work : r2_somers(bm) Somers' Dxy NA

Besides, I "need" the base function (performance::r2) to work, since it's to run my psem :-)

strengejacke commented 2 months ago

I think it's due to a model "mis-specification". You have as many random effects groups as observations (i.e. nobs(bm) is identical to length(unique(d$obs_V))). That's why insight::get_variance() (which is used to calculate R2) can't be calculated and returns NULL.

Removing the weights from your model at least allows to calculate other variances, but not the random effects variances, either. Thus, you only get the marginal R2:

library(glmmTMB)
d <- read.table("c:/Users/mail/Downloads/glmmTMB_performance_NA.txt", header = TRUE)
bm <- glmmTMB(Tx_V ~ AB + Co1 + (1 | obs_V), data = d, family = "binomial")
#> Warning in eval(family$initialize): non-integer #successes in a binomial glm!

performance::r2(bm)
#> Warning: Can't compute random effect variances. Some variance components equal
#>   zero. Your model may suffer from singularity (see `?lme4::isSingular`
#>   and `?performance::check_singularity`).
#>   Solution: Respecify random structure! You may also decrease the
#>   `tolerance` level to enforce the calculation of random effect variances.
#> Random effect variances not available. Returned R2 does not account for random effects.
#> # R2 for Mixed Models
#> 
#>   Conditional R2: NA
#>      Marginal R2: 0.008

Created on 2024-05-02 with reprex v2.1.0

luroy commented 2 months ago

Hello @strengejacke , Thank you for your quick reply, which lets me know that this error is induced by ORLE, which corrects for overdispersion. Thank you very much :-)

strengejacke commented 2 months ago

What's ORLE?

Ah, observation level random effects.