Skip to content

Commit

Permalink
Draft R2 Ferrari (#743)
Browse files Browse the repository at this point in the history
  • Loading branch information
strengejacke authored Jul 6, 2024
1 parent fd868b4 commit b68e32f
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 4 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Type: Package
Package: performance
Title: Assessment of Regression Models Performance
Version: 0.12.0.5
Version: 0.12.0.6
Authors@R:
c(person(given = "Daniel",
family = "Lüdecke",
Expand Down
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,8 @@ S3method(r2_coxsnell,survreg)
S3method(r2_coxsnell,svycoxph)
S3method(r2_coxsnell,truncreg)
S3method(r2_efron,default)
S3method(r2_ferrari,default)
S3method(r2_ferrari,glmmTMB)
S3method(r2_kullback,default)
S3method(r2_kullback,glm)
S3method(r2_loo_posterior,BFBayesFactor)
Expand Down Expand Up @@ -599,6 +601,7 @@ export(r2)
export(r2_bayes)
export(r2_coxsnell)
export(r2_efron)
export(r2_ferrari)
export(r2_kullback)
export(r2_loo)
export(r2_loo_posterior)
Expand Down
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
bootstrapped confidence intervals. The function gains following new arguments:
`ci`, `ci_method` and `iterations`.

* New function `r2_ferrari()` to compute Ferrari & Cribari-Neto's R2 for
generalized linear models, in particular beta-regression.

# performance 0.12.0

## Breaking
Expand Down
3 changes: 3 additions & 0 deletions R/r2.R
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,9 @@ r2.glmmTMB <- function(model, ci = NULL, tolerance = 1e-5, verbose = TRUE, ...)
} else if (info$is_zero_inflated) {
# zero-inflated models use the default method
out <- r2_zeroinflated(model)
} else if (info$is_beta) {
# beta-regression
out <- r2_ferrari(model)
} else {
insight::format_error("`r2()` does not support models of class `glmmTMB` without random effects and this link-function.") # nolint
}
Expand Down
64 changes: 64 additions & 0 deletions R/r2_ferarri.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#' @title Ferrari's and Cribari-Neto's R2
#' @name r2_ferrari
#'
#' @description Calculates Ferrari's and Cribari-Neto's pseudo R2 (for
#' beta-regression models).
#'
#' @param model Generalized linear, in particular beta-regression model.
#' @param ... Currently not used.
#'
#' @return A list with the pseudo R2 value.
#'
#' @references
#' - Ferrari, S., and Cribari-Neto, F. (2004). Beta Regression for Modelling Rates
#' and Proportions. Journal of Applied Statistics, 31(7), 799–815.
#' \doi{10.1080/0266476042000214501}
#'
#' @examplesIf require("betareg")
#' data("GasolineYield", package = "betareg")
#' model <- betareg::betareg(yield ~ batch + temp, data = GasolineYield)
#' r2_ferrari(model)
#' @export
r2_ferrari <- function(model, ...) {
UseMethod("r2_ferrari")
}

#' @export
r2_ferrari.default <- function(model, ...) {
# coefficients, but remove phi parameter
x <- stats::coef(model)
x <- x[names(x) != "(phi)"]
.r2_ferrari(model, x)
}

#' @export
r2_ferrari.glmmTMB <- function(model, ...) {
insight::check_if_installed("lme4")
# coefficients, but remove phi parameter
x <- .collapse_cond(lme4::fixef(model))
x <- x[names(x) != "(phi)"]
.r2_ferrari(model, x)
}


# helper -----------------------------

.r2_ferrari <- function(model, x) {
# model matrix, check dimensions / length
mm <- insight::get_modelmatrix(model)

if (length(x) != ncol(mm)) {
insight::format_warning("Model matrix and coefficients do not match.")
return(NULL)
}

# linear predictor for the mean
eta <- as.vector(x %*% t(mm))
y <- insight::get_response(model)

ferrari <- stats::cor(eta, insight::link_function(model)(y))^2
out <- list(R2 = c(`Ferrari's R2` = ferrari))

attr(out, "model_type") <- "Generalized Linear"
structure(class = "r2_generic", out)
}
7 changes: 4 additions & 3 deletions R/r2_mcfadden.R
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,16 @@ r2_mcfadden.glm <- function(model, verbose = TRUE, ...) {
if (is.null(info)) {
info <- suppressWarnings(insight::model_info(model, verbose = FALSE))
}

if (info$is_binomial && !info$is_bernoulli && class(model)[1] == "glm") {
if (verbose) {
insight::format_warning("Can't calculate accurate R2 for binomial models that are not Bernoulli models.")
}
return(NULL)
} else {
l_null <- insight::get_loglikelihood(stats::update(model, ~1))
.r2_mcfadden(model, l_null)
}

l_null <- insight::get_loglikelihood(stats::update(model, ~1))
.r2_mcfadden(model, l_null)
}

#' @export
Expand Down
3 changes: 3 additions & 0 deletions inst/WORDLIST
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Chisq
CochransQ
CompQuadForm
Concurvity
Cribari
Cronbach's
Crujeiras
Csaki
Expand Down Expand Up @@ -154,6 +155,8 @@ Nagelkerke
Nagelkerke's
Nakagawa
Nakagawa's
Neto
Neto's
Nondegenerate
Nordhausen
Normed
Expand Down
34 changes: 34 additions & 0 deletions man/r2_ferrari.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions tests/testthat/test-r2_ferrari.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
test_that("r2_ferarri", {
skip_if_not_installed("betareg")
data("GasolineYield", package = "betareg")
model <- betareg::betareg(yield ~ batch + temp, data = GasolineYield)
out <- r2_ferrari(model)
expect_equal(out$R2, summary(model)$pseudo.r.squared, tolerance = 1e-3, ignore_attr = TRUE)
})


test_that("r2_ferarri", {
skip_if_not_installed("betareg")
skip_if_not_installed("glmmTMB")
data("GasolineYield", package = "betareg")
model <- glmmTMB::glmmTMB(
yield ~ batch + temp,
data = GasolineYield,
family = glmmTMB::beta_family()
)
out <- r2_ferrari(model)
expect_equal(out$R2, c(`Ferrari's R2` = 0.96173), tolerance = 1e-3, ignore_attr = TRUE)
})

0 comments on commit b68e32f

Please sign in to comment.