Nothing
#' @title Nagelkerke's R2
#' @name r2_nagelkerke
#'
#' @description Calculate Nagelkerke's pseudo-R2.
#'
#' @param model A generalized linear model, including cumulative links resp.
#' multinomial models.
#' @param ... Currently not used.
#'
#' @return A named vector with the R2 value.
#'
#' @examples
#' model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial")
#' r2_nagelkerke(model)
#' @references
#' Nagelkerke, N. J. (1991). A note on a general definition of the coefficient
#' of determination. Biometrika, 78(3), 691-692.
#'
#' @export
r2_nagelkerke <- function(model, ...) {
UseMethod("r2_nagelkerke")
}
# helper ---------------------------
.r2_nagelkerke <- function(model, l_base) {
L.full <- insight::get_loglikelihood(model)
D.full <- -2 * L.full
D.base <- -2 * l_base
# Is it still necessary?
if (inherits(model, c("vglm", "vgam", "clm2"))) {
n <- insight::n_obs(model)
} else {
n <- attr(L.full, "nobs")
if (is.null(n)) n <- insight::n_obs(model, disaggregate = TRUE)
}
r2_nagelkerke <- as.vector((1 - exp((D.full - D.base) / n)) / (1 - exp(-D.base / n)))
names(r2_nagelkerke) <- "Nagelkerke's R2"
r2_nagelkerke
}
# Nagelkerke's R2 based on Cox&Snell's R2 ----------------
#' @export
r2_nagelkerke.glm <- function(model, verbose = TRUE, ...) {
info <- list(...)$model_info
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)
}
r2cox <- r2_coxsnell(model)
if (is.na(r2cox) || is.null(r2cox)) {
return(NULL)
}
r2_nagelkerke <- r2cox / (1 - exp(-model$null.deviance / insight::n_obs(model, disaggregate = TRUE)))
names(r2_nagelkerke) <- "Nagelkerke's R2"
r2_nagelkerke
}
#' @export
r2_nagelkerke.BBreg <- r2_nagelkerke.glm
#' @export
r2_nagelkerke.glmmTMB <- function(model, verbose = TRUE, ...) {
info <- list(...)$model_info
if (is.null(info)) {
info <- suppressWarnings(insight::model_info(model, verbose = FALSE))
}
if (info$is_binomial && !info$is_bernoulli) {
if (verbose) {
insight::format_warning("Can't calculate accurate R2 for binomial models that are not Bernoulli models.")
}
return(NULL)
}
dev <- stats::deviance(model)
# if no deviance, return NA
if (is.null(dev)) {
return(NULL)
}
null_mod <- suppressWarnings(insight::null_model(model))
null_dev <- stats::deviance(null_mod)
r2cox <- (1 - exp((dev - null_dev) / insight::n_obs(model, disaggregate = TRUE)))
if (is.na(r2cox) || is.null(r2cox)) {
return(NULL)
}
r2_nagelkerke <- r2cox / (1 - exp(-null_dev / insight::n_obs(model, disaggregate = TRUE)))
names(r2_nagelkerke) <- "Nagelkerke's R2"
r2_nagelkerke
}
#' @export
r2_nagelkerke.nestedLogit <- function(model, ...) {
n <- insight::n_obs(model, disaggregate = TRUE)
stats::setNames(
lapply(names(model$models), function(i) {
m <- model$models[[i]]
# if no deviance, return NA
if (is.null(m$deviance)) {
return(NA)
}
r2_nagelkerke <- (1 - exp((m$deviance - m$null.deviance) / n[[i]])) / (1 - exp(-m$null.deviance / n[[i]]))
names(r2_nagelkerke) <- "Nagelkerke's R2"
r2_nagelkerke
}),
names(model$models)
)
}
#' @export
r2_nagelkerke.bife <- function(model, ...) {
r2_nagelkerke <- r2_coxsnell(model) / (1 - exp(-model$null_deviance / insight::n_obs(model)))
names(r2_nagelkerke) <- "Nagelkerke's R2"
r2_nagelkerke
}
# mfx models ---------------------
#' @export
r2_nagelkerke.logitmfx <- function(model, ...) {
r2_nagelkerke(model$fit, ...)
}
#' @export
r2_nagelkerke.logitor <- r2_nagelkerke.logitmfx
#' @export
r2_nagelkerke.poissonirr <- r2_nagelkerke.logitmfx
#' @export
r2_nagelkerke.poissonmfx <- r2_nagelkerke.logitmfx
#' @export
r2_nagelkerke.probitmfx <- r2_nagelkerke.logitmfx
#' @export
r2_nagelkerke.negbinirr <- r2_nagelkerke.logitmfx
#' @export
r2_nagelkerke.negbinmfx <- r2_nagelkerke.logitmfx
# Nagelkerke's R2 based on LogLik ----------------
#' @export
r2_nagelkerke.multinom <- function(model, ...) {
l_base <- insight::get_loglikelihood(stats::update(model, ~1, trace = FALSE))
.r2_nagelkerke(model, l_base)
}
#' @export
r2_nagelkerke.clm2 <- function(model, ...) {
l_base <- insight::get_loglikelihood(stats::update(model, location = ~1, scale = ~1))
.r2_nagelkerke(model, l_base)
}
#' @export
r2_nagelkerke.clm <- function(model, ...) {
l_base <- insight::get_loglikelihood(stats::update(model, ~1))
# if no loglik, return NA
if (length(as.numeric(l_base)) == 0) {
return(NULL)
}
.r2_nagelkerke(model, l_base)
}
#' @export
r2_nagelkerke.polr <- r2_nagelkerke.clm
#' @export
r2_nagelkerke.serp <- r2_nagelkerke.clm
#' @export
r2_nagelkerke.cpglm <- r2_nagelkerke.clm
#' @export
r2_nagelkerke.bracl <- r2_nagelkerke.clm
#' @export
r2_nagelkerke.glmx <- r2_nagelkerke.clm
#' @export
r2_nagelkerke.brmultinom <- r2_nagelkerke.clm
#' @export
r2_nagelkerke.censReg <- r2_nagelkerke.clm
#' @export
r2_nagelkerke.truncreg <- r2_nagelkerke.clm
#' @export
r2_nagelkerke.DirichletRegModel <- r2_coxsnell.clm
# Nagelkerke's R2 based on LogLik stored in model object ----------------
#' @export
r2_nagelkerke.coxph <- function(model, ...) {
l_base <- model$loglik[1]
.r2_nagelkerke(model, l_base)
}
#' @export
r2_nagelkerke.survreg <- r2_nagelkerke.coxph
#' @export
r2_nagelkerke.crch <- r2_nagelkerke.coxph
#' @export
r2_nagelkerke.svycoxph <- function(model, ...) {
l_base <- model$ll[1]
.r2_nagelkerke(model, l_base)
}
# other ---------------------
#' @export
r2_nagelkerke.mclogit <- function(model, ...) {
insight::check_if_installed("mclogit", reason = "to calculate R2")
s <- mclogit::getSummary.mclogit(model)
r2_nagelkerke <- s$sumstat["Nagelkerke"]
names(r2_nagelkerke) <- "Nagelkerke's R2"
r2_nagelkerke
}
#' @export
r2_nagelkerke.mblogit <- function(model, ...) {
insight::check_if_installed("mclogit", reason = "to calculate R2")
s <- mclogit::getSummary.mblogit(model)
r2_nagelkerke <- s$sumstat["Nagelkerke"]
names(r2_nagelkerke) <- "Nagelkerke's R2"
r2_nagelkerke
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.