diff --git a/DESCRIPTION b/DESCRIPTION index 55c88c712..6f74d2378 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: effectsize Title: Indices of Effect Size and Standardized Parameters -Version: 0.5-1 +Version: 0.5-2 Authors@R: c(person(given = "Mattan S.", family = "Ben-Shachar", diff --git a/NAMESPACE b/NAMESPACE index 3cbff1176..87bd18fcf 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -21,6 +21,8 @@ S3method(interpret,performance_lavaan) S3method(interpret_parameters,lm) S3method(odds_to_probs,data.frame) S3method(odds_to_probs,numeric) +S3method(oddsratio_to_riskratio,default) +S3method(oddsratio_to_riskratio,glm) S3method(plot,effectsize_table) S3method(plot,equivalence_test_effectsize) S3method(print,effectsize_anova) @@ -215,6 +217,7 @@ importFrom(stats,aov) importFrom(stats,as.formula) importFrom(stats,ave) importFrom(stats,chisq.test) +importFrom(stats,coef) importFrom(stats,complete.cases) importFrom(stats,contrasts) importFrom(stats,delete.response) diff --git a/NEWS.md b/NEWS.md index 661d732fa..71c504bfa 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,6 +7,7 @@ ## New features +- `oddsratio_to_riskratio()` can now convert OR coefficients to RR coefficients from a logistic GLM. - All effect-size functions gain an `alternative` argument which can be used to make one- or two-sided CIs. - `interpret()` now accepts as input the results from `cohens_d()`, `eta_squared()`, `rank_biserial()`, etc. - `interpret_pd()` for the interpretation of the [*Probability of Direction*](https://easystats.github.io/bayestestR/reference/p_direction.html). diff --git a/R/convert_between_OR_to_RR.R b/R/convert_between_OR_to_RR.R index e455fe841..e6a335fe1 100644 --- a/R/convert_between_OR_to_RR.R +++ b/R/convert_between_OR_to_RR.R @@ -1,11 +1,13 @@ #' Convert between Odds ratios and Risk ratios #' #' @param OR,RR Risk ratio of `p1/p0` or Odds ratio of `odds(p1)/odds(p0)`, -#' possibly log-ed. +#' possibly log-ed. `OR` can also be a logistic regression model. #' @param p0 Baseline risk +#' @param ... Arguments passed to and from other methods. #' @inheritParams oddsratio_to_d #' -#' @return Converted index. +#' @return Converted index, or if `OR` is a logistic regression model, a +#' parameter table with the converted indices. #' #' @family convert between effect sizes #' @@ -18,6 +20,10 @@ #' #' riskratio_to_oddsratio(RR, p0 = p0) #' oddsratio_to_riskratio(OR, p0 = p0) +#' +#' m <- glm(am ~ factor(cyl), data = mtcars, +#' family = binomial()) +#' oddsratio_to_riskratio(m) #' @references #' #' Grant, R. L. (2014). Converting an odds ratio to a range of plausible @@ -25,7 +31,12 @@ #' f7450. #' #' @export -oddsratio_to_riskratio <- function(OR, p0, log = FALSE) { +oddsratio_to_riskratio <- function(OR, p0, log = FALSE, ...) { + UseMethod("oddsratio_to_riskratio") +} + +#' @export +oddsratio_to_riskratio.default <- function(OR, p0, log = FALSE, ...) { if (log) OR <- exp(OR) RR <- OR / (1 - p0 + (p0 * OR)) @@ -34,6 +45,41 @@ oddsratio_to_riskratio <- function(OR, p0, log = FALSE) { return(RR) } +#' @export +#' @importFrom stats coef +oddsratio_to_riskratio.glm <- function(OR, p0, log = FALSE, ...) { + mi <- insight::model_info(OR) + if (!mi$is_binomial || !mi$is_logit) stop("Model must a binomial model with logit-link (logistic regression)") + + if (used_intercept <- missing(p0)) { + p0 <- plogis(stats::coef(OR)["(Intercept)"]) + warning("'p0' not provided.", + "RR is relative to the intercept (p0 = ", + insight::format_value(p0), + ") - make sure your intercept is meaningful.") + } + + RR <- parameters::model_parameters(OR, exponentiate = !log, ...) + RR$SE <- NULL + RR$z <- NULL + RR$df_error <- NULL + RR$p <- NULL + + RR[,colnames(RR) %in% c("Coefficient", "CI_low", "CI_high")] <- + lapply(RR[,colnames(RR) %in% c("Coefficient", "CI_low", "CI_high")], + oddsratio_to_riskratio, p0 = p0, log = log) + + RR[RR$Parameter=="(Intercept)", "Coefficient"] <- p0 + RR[RR$Parameter=="(Intercept)", c("CI_low", "CI_high")] <- NA + + if (!used_intercept) { + RR[RR$Parameter=="(Intercept)", "Parameter"] <- "(p0)" + } + + attr(RR, "coefficient_name") <- if (log) "Log-RR" else "Risk Ratio" + return(RR) +} + #' @rdname oddsratio_to_riskratio @@ -46,3 +92,4 @@ riskratio_to_oddsratio <- function(RR, p0, log = FALSE) { if (log) OR <- log(OR) return(OR) } + diff --git a/man/format_standardize.Rd b/man/format_standardize.Rd index ba272831a..08ebecabc 100644 --- a/man/format_standardize.Rd +++ b/man/format_standardize.Rd @@ -28,7 +28,7 @@ be \code{"signif"} to return significant figures or \code{"scientific"} to return scientific notation. Control the number of digits by adding the value as suffix, e.g. \code{digits = "scientific4"} to have scientific notation with 4 decimal places, or \code{digits = "signif5"} for 5 -significant figures (see also \code{\link{signif}}).} +significant figures (see also \code{\link[=signif]{signif()}}).} \item{protect_integers}{Should integers be kept as integers (i.e., without decimals)?} diff --git a/man/oddsratio_to_riskratio.Rd b/man/oddsratio_to_riskratio.Rd index d566fc6e1..66c93edb1 100644 --- a/man/oddsratio_to_riskratio.Rd +++ b/man/oddsratio_to_riskratio.Rd @@ -5,20 +5,23 @@ \alias{riskratio_to_oddsratio} \title{Convert between Odds ratios and Risk ratios} \usage{ -oddsratio_to_riskratio(OR, p0, log = FALSE) +oddsratio_to_riskratio(OR, p0, log = FALSE, ...) riskratio_to_oddsratio(RR, p0, log = FALSE) } \arguments{ \item{OR, RR}{Risk ratio of \code{p1/p0} or Odds ratio of \code{odds(p1)/odds(p0)}, -possibly log-ed.} +possibly log-ed. \code{OR} can also be a logistic regression model.} \item{p0}{Baseline risk} \item{log}{Take in or output the log of the ratio (such as in logistic models).} + +\item{...}{Arguments passed to and from other methods.} } \value{ -Converted index. +Converted index, or if \code{OR} is a logistic regression model, a +parameter table with the converted indices. } \description{ Convert between Odds ratios and Risk ratios @@ -32,6 +35,10 @@ p1 <- 0.7 riskratio_to_oddsratio(RR, p0 = p0) oddsratio_to_riskratio(OR, p0 = p0) + +m <- glm(am ~ factor(cyl), data = mtcars, + family = binomial()) +oddsratio_to_riskratio(m) } \references{ Grant, R. L. (2014). Converting an odds ratio to a range of plausible diff --git a/man/print.effectsize_table.Rd b/man/print.effectsize_table.Rd index 512cce19a..3f41b7667 100644 --- a/man/print.effectsize_table.Rd +++ b/man/print.effectsize_table.Rd @@ -28,7 +28,7 @@ be \code{"signif"} to return significant figures or \code{"scientific"} to return scientific notation. Control the number of digits by adding the value as suffix, e.g. \code{digits = "scientific4"} to have scientific notation with 4 decimal places, or \code{digits = "signif5"} for 5 -significant figures (see also \code{\link{signif}}).} +significant figures (see also \code{\link[=signif]{signif()}}).} \item{append_CL}{Should the Common Language Effect Sizes be printed as well? Only applicable to Cohen's \emph{d}, Hedges' \emph{g} for independent samples of diff --git a/tests/testthat/test-convert_between.R b/tests/testthat/test-convert_between.R index b6a5ad5ab..34e200b78 100644 --- a/tests/testthat/test-convert_between.R +++ b/tests/testthat/test-convert_between.R @@ -28,6 +28,20 @@ if (require("testthat") && require("effectsize")) { expect_equal(riskratio_to_oddsratio(log(RR), p0 = p0, log = TRUE), log(OR)) expect_equal(oddsratio_to_riskratio(log(OR), p0 = p0, log = TRUE), log(RR)) + + + m <- glm(am ~ factor(cyl), data = mtcars, + family = binomial()) + + expect_warning(RR <- oddsratio_to_riskratio(m)) + expect_true("(Intercept)" %in% RR$Parameter) + expect_false("(p0)" %in% RR$Parameter) + expect_equal(RR$Coefficient, c(0.7272, 0.5892, 0.1964), tolerance = 0.001) + + RR <- oddsratio_to_riskratio(m, p0 = 0.05) + expect_true("(p0)" %in% RR$Parameter) + expect_false("(Intercept)" %in% RR$Parameter) + expect_equal(RR$Coefficient, c(0.05, 0.29173, 0.06557), tolerance = 0.001) }) test_that("odds_to_probs", {