From f276d2f757249dfe111b4cd039a1cdb17d109f17 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 1 Jul 2026 20:10:56 +0200 Subject: [PATCH] `ci = NULL` suppresses confidence intervals and SE --- DESCRIPTION | 2 +- NEWS.md | 7 ++ R/estimate_means.R | 6 +- R/get_marginalmeans.R | 6 ++ R/get_marginaltrends.R | 6 ++ man/estimate_contrasts.Rd | 4 +- man/estimate_expectation.Rd | 4 +- man/estimate_means.Rd | 4 +- man/estimate_slopes.Rd | 4 +- man/get_emmeans.Rd | 4 +- tests/testthat/test-estimate_means_ci.R | 114 +++++++++++++++++++----- tests/testthat/test-estimate_slopes.R | 6 ++ 12 files changed, 138 insertions(+), 29 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 5007a4bf5..b3a29cb8e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: modelbased Title: Estimation of Model-Based Predictions, Contrasts and Means -Version: 0.16.0 +Version: 0.16.0.1 Authors@R: c(person(given = "Dominique", family = "Makowski", diff --git a/NEWS.md b/NEWS.md index 5d6558b5e..dd02605e5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,10 @@ +# modelbased (devel) + +## Changes + +* `ci = NULL` now suppresses calculation of standard errors and confidence + intervals. + # modelbased 0.16.0 ## Changes diff --git a/R/estimate_means.R b/R/estimate_means.R index b75cbd921..9cfac895d 100644 --- a/R/estimate_means.R +++ b/R/estimate_means.R @@ -115,6 +115,9 @@ #' number, only as many columns as indicated in `keep_iterations` will be added #' to the output. You can reshape them to a long format by running #' [`bayestestR::reshape_iterations()`]. +#' @param ci Confidence Interval (CI) level. Must be numeric between 0 and 1. +#' Defaults to `0.95`. Use `NULL` to suppress calculation of standard errors and +#' confidence intervals. #' @param verbose Use `FALSE` to silence messages and warnings. #' @param ... Other arguments passed, for instance, to [insight::get_datagrid()], #' to functions from the **emmeans** or **marginaleffects** package, or to process @@ -151,9 +154,6 @@ #' `estimate = "population"` without specifying the `offset`, to average #' predictions over the distribution of the offset (if appropriate). #' -#' @inheritParams parameters::model_parameters.default -#' @inheritParams estimate_expectation -#' #' @details #' The [estimate_slopes()], [estimate_means()] and [estimate_contrasts()] #' functions are forming a group, as they are all based on *marginal* diff --git a/R/get_marginalmeans.R b/R/get_marginalmeans.R index 1620e4315..a60b540de 100644 --- a/R/get_marginalmeans.R +++ b/R/get_marginalmeans.R @@ -184,6 +184,12 @@ get_marginalmeans <- function( fun_args$re.form <- NULL } + # missing or NA for conf_level? If so, we want to suppress SE and CI + if (is.null(fun_args$conf_level) || is.na(fun_args$conf_level)) { + fun_args$conf_level <- NULL # for NA + fun_args$vcov <- FALSE + } + # transform reponse? if (isTRUE(transform)) { transform <- insight::get_transformation(model, verbose = FALSE)$inverse diff --git a/R/get_marginaltrends.R b/R/get_marginaltrends.R index 01371971d..15647cb05 100644 --- a/R/get_marginaltrends.R +++ b/R/get_marginaltrends.R @@ -129,6 +129,12 @@ get_marginaltrends <- function( fun_args$type <- predict } + # missing or NA for conf_level? If so, we want to suppress SE and CI + if (is.null(fun_args$conf_level) || is.na(fun_args$conf_level)) { + fun_args$conf_level <- NULL # for NA + fun_args$vcov <- FALSE + } + # Third step: compute marginal slopes --------------------------------------- # --------------------------------------------------------------------------- diff --git a/man/estimate_contrasts.Rd b/man/estimate_contrasts.Rd index 5b756974b..bdbca18fe 100644 --- a/man/estimate_contrasts.Rd +++ b/man/estimate_contrasts.Rd @@ -115,7 +115,9 @@ transformation is selected (which usually is \code{"response"}). See also See also section \emph{Predictions on different scales}.} -\item{ci}{Confidence Interval (CI) level. Default to \code{0.95} (\verb{95\%}).} +\item{ci}{Confidence Interval (CI) level. Must be numeric between 0 and 1. +Defaults to \code{0.95}. Use \code{NULL} to suppress calculation of standard errors and +confidence intervals.} \item{comparison}{Specify the type of contrasts or tests that should be carried out. See also section \emph{Comparison options} below for details. diff --git a/man/estimate_expectation.Rd b/man/estimate_expectation.Rd index 69fc1514b..c626fb69b 100644 --- a/man/estimate_expectation.Rd +++ b/man/estimate_expectation.Rd @@ -83,7 +83,9 @@ you are directly predicting the value of some distributional parameter), and the corresponding functions will then only differ in the default value of their \code{data} argument.} -\item{ci}{Confidence Interval (CI) level. Default to \code{0.95} (\verb{95\%}).} +\item{ci}{Confidence Interval (CI) level. Must be numeric between 0 and 1. +Defaults to \code{0.95}. Use \code{NULL} to suppress calculation of standard errors and +confidence intervals.} \item{transform}{A function applied to predictions and confidence intervals to (back-) transform results, which can be useful in case the regression diff --git a/man/estimate_means.Rd b/man/estimate_means.Rd index a9159e168..092e17c88 100644 --- a/man/estimate_means.Rd +++ b/man/estimate_means.Rd @@ -56,7 +56,9 @@ transformation is selected (which usually is \code{"response"}). See also See also section \emph{Predictions on different scales}.} -\item{ci}{Confidence Interval (CI) level. Default to \code{0.95} (\verb{95\%}).} +\item{ci}{Confidence Interval (CI) level. Must be numeric between 0 and 1. +Defaults to \code{0.95}. Use \code{NULL} to suppress calculation of standard errors and +confidence intervals.} \item{estimate}{The \code{estimate} argument determines how predictions are averaged ("marginalized") over variables not specified in \code{by} or \code{contrast} diff --git a/man/estimate_slopes.Rd b/man/estimate_slopes.Rd index a79e49e27..1a9a8467f 100644 --- a/man/estimate_slopes.Rd +++ b/man/estimate_slopes.Rd @@ -70,7 +70,9 @@ transformation is selected (which usually is \code{"response"}). See also See also section \emph{Predictions on different scales}.} -\item{ci}{Confidence Interval (CI) level. Default to \code{0.95} (\verb{95\%}).} +\item{ci}{Confidence Interval (CI) level. Must be numeric between 0 and 1. +Defaults to \code{0.95}. Use \code{NULL} to suppress calculation of standard errors and +confidence intervals.} \item{estimate}{The \code{estimate} argument determines how predictions are averaged ("marginalized") over variables not specified in \code{by} or \code{contrast} diff --git a/man/get_emmeans.Rd b/man/get_emmeans.Rd index caaafa524..e272c7836 100644 --- a/man/get_emmeans.Rd +++ b/man/get_emmeans.Rd @@ -248,7 +248,9 @@ instance, \verb{by="", length=30}. To calculate average marginal effects over a range of values, use \code{trend=" = seq(1, 3, 0.1)"} (or similar) and omit the variable provided in \code{trend} from the \code{by} argument.} -\item{ci}{Confidence Interval (CI) level. Default to \code{0.95} (\verb{95\%}).} +\item{ci}{Confidence Interval (CI) level. Must be numeric between 0 and 1. +Defaults to \code{0.95}. Use \code{NULL} to suppress calculation of standard errors and +confidence intervals.} \item{estimate}{The \code{estimate} argument determines how predictions are averaged ("marginalized") over variables not specified in \code{by} or \code{contrast} diff --git a/tests/testthat/test-estimate_means_ci.R b/tests/testthat/test-estimate_means_ci.R index 4e613179c..21972e9ec 100644 --- a/tests/testthat/test-estimate_means_ci.R +++ b/tests/testthat/test-estimate_means_ci.R @@ -15,22 +15,56 @@ test_that("estimate_means() - ci frequentist", { x <- capture.output(out) expect_identical(x[5], "setosa | 4.75 | 0.09 | [4.61, 4.89] | 54.34") - out <- estimate_contrasts(mod2, contrast = "Species", backend = "marginaleffects", ci = 0.95) + out <- estimate_contrasts( + mod2, + contrast = "Species", + backend = "marginaleffects", + ci = 0.95 + ) x <- capture.output(out) - expect_identical(x[5], "versicolor | setosa | 1.43 | 0.12 | [1.19, 1.68] | 11.78 | < .001") - - out <- estimate_contrasts(mod2, contrast = "Species", backend = "marginaleffects", ci = 0.89) + expect_identical( + x[5], + "versicolor | setosa | 1.43 | 0.12 | [1.19, 1.68] | 11.78 | < .001" + ) + + out <- estimate_contrasts( + mod2, + contrast = "Species", + backend = "marginaleffects", + ci = 0.89 + ) x <- capture.output(out) - expect_identical(x[5], "versicolor | setosa | 1.43 | 0.12 | [1.24, 1.63] | 11.78 | < .001") + expect_identical( + x[5], + "versicolor | setosa | 1.43 | 0.12 | [1.24, 1.63] | 11.78 | < .001" + ) # Estimate slopes with different CIs - out <- estimate_slopes(mod2, trend = "Sepal.Width", by = "Species", backend = "marginaleffects", ci = 0.95) + out <- estimate_slopes( + mod2, + trend = "Sepal.Width", + by = "Species", + backend = "marginaleffects", + ci = 0.95 + ) x <- capture.output(out) expect_identical(x[5], "setosa | 0.69 | 0.17 | [0.36, 1.02] | 4.17 | < .001") - out <- estimate_slopes(mod2, trend = "Sepal.Width", by = "Species", backend = "marginaleffects", ci = 0.89) + out <- estimate_slopes( + mod2, + trend = "Sepal.Width", + by = "Species", + backend = "marginaleffects", + ci = 0.89 + ) x <- capture.output(out) expect_identical(x[5], "setosa | 0.69 | 0.17 | [0.42, 0.96] | 4.17 | < .001") + + # suppress CI + out <- estimate_means(mod2, by = "Species", backend = "marginaleffects", ci = NULL) + expect_named(out, c("Species", "Mean", "df")) + out <- estimate_means(mod2, by = "Species", backend = "marginaleffects", ci = NA) + expect_named(out, c("Species", "Mean", "df")) }) @@ -48,26 +82,66 @@ test_that("estimate_means() - ci frequentist", { # Estimate means with different CIs out <- estimate_means(mod2, by = "Species", backend = "marginaleffects", ci = 0.95) x <- capture.output(out) - expect_identical(x[5], "setosa | 4.76 | [4.59, 4.93] | 100% | [-0.10, 0.10] | 0%") + expect_identical( + x[5], + "setosa | 4.76 | [4.59, 4.93] | 100% | [-0.10, 0.10] | 0%" + ) out <- estimate_means(mod2, by = "Species", backend = "marginaleffects", ci = 0.89) x <- capture.output(out) - expect_identical(x[5], "setosa | 4.76 | [4.62, 4.90] | 100% | [-0.10, 0.10] | 0%") - - out <- estimate_contrasts(mod2, contrast = "Species", backend = "marginaleffects", ci = 0.95) + expect_identical( + x[5], + "setosa | 4.76 | [4.62, 4.90] | 100% | [-0.10, 0.10] | 0%" + ) + + out <- estimate_contrasts( + mod2, + contrast = "Species", + backend = "marginaleffects", + ci = 0.95 + ) x <- capture.output(out) - expect_identical(x[5], "versicolor | setosa | 1.43 | [1.18, 1.67] | 100% | [-0.10, 0.10] | 0%") - - out <- estimate_contrasts(mod2, contrast = "Species", backend = "marginaleffects", ci = 0.89) + expect_identical( + x[5], + "versicolor | setosa | 1.43 | [1.18, 1.67] | 100% | [-0.10, 0.10] | 0%" + ) + + out <- estimate_contrasts( + mod2, + contrast = "Species", + backend = "marginaleffects", + ci = 0.89 + ) x <- capture.output(out) - expect_identical(x[5], "versicolor | setosa | 1.43 | [1.23, 1.63] | 100% | [-0.10, 0.10] | 0%") + expect_identical( + x[5], + "versicolor | setosa | 1.43 | [1.23, 1.63] | 100% | [-0.10, 0.10] | 0%" + ) # Estimate slopes with different CIs - out <- estimate_slopes(mod2, trend = "Sepal.Width", by = "Species", backend = "marginaleffects", ci = 0.95) + out <- estimate_slopes( + mod2, + trend = "Sepal.Width", + by = "Species", + backend = "marginaleffects", + ci = 0.95 + ) x <- capture.output(out) - expect_identical(x[5], "setosa | 0.67 | [0.35, 0.99] | 100% | [-0.10, 0.10] | 0%") - - out <- estimate_slopes(mod2, trend = "Sepal.Width", by = "Species", backend = "marginaleffects", ci = 0.89) + expect_identical( + x[5], + "setosa | 0.67 | [0.35, 0.99] | 100% | [-0.10, 0.10] | 0%" + ) + + out <- estimate_slopes( + mod2, + trend = "Sepal.Width", + by = "Species", + backend = "marginaleffects", + ci = 0.89 + ) x <- capture.output(out) - expect_identical(x[5], "setosa | 0.67 | [0.41, 0.93] | 100% | [-0.10, 0.10] | 0%") + expect_identical( + x[5], + "setosa | 0.67 | [0.41, 0.93] | 100% | [-0.10, 0.10] | 0%" + ) }) diff --git a/tests/testthat/test-estimate_slopes.R b/tests/testthat/test-estimate_slopes.R index b0198d9e0..0f6a650b6 100644 --- a/tests/testthat/test-estimate_slopes.R +++ b/tests/testthat/test-estimate_slopes.R @@ -88,6 +88,12 @@ test_that("estimate_slopes", { ) expect_named(estim2, c("Petal.Length", "Slope", "SE", "CI_low", "CI_high", "z", "p")) + # suppress CI + out <- suppressMessages(estimate_slopes(model, ci = NULL)) + expect_named(out, "Slope") + out <- suppressMessages(estimate_slopes(model, ci = NA)) + expect_named(out, "Slope") + model <- lm(Petal.Length ~ poly(Sepal.Width, 4), data = iris) estim1 <- suppressMessages(estimate_slopes(