diff --git a/R/estimate_contrasts.R b/R/estimate_contrasts.R index c777e6253..b7af196ea 100644 --- a/R/estimate_contrasts.R +++ b/R/estimate_contrasts.R @@ -71,8 +71,9 @@ #' size will be computed. #' @param es_type Specifies the type of effect-size measure to estimate when #' using `effectsize = "boot"`. One of `"unstandardized"`, `"cohens.d"`, -#' `"hedges.g"`, `"cohens.d.sigma"`, `"r"`, or `"akp.robust.d"`. See` -#' effect.type` argument of [bootES::bootES] for details. +#' `"hedges.g"`, `"cohens.d.sigma"`, `"r"`, or `"akp.robust.d"`. See `effect.type` +#' argument of [`bootES::bootES()`] for details. If not specified, defaults to +#' `"cohens.d"`. #' @param iterations The number of bootstrap resamples to perform. #' @inheritParams estimate_means #' @@ -301,7 +302,7 @@ estimate_contrasts.default <- function( keep_iterations = FALSE, effectsize = NULL, iterations = 200, - es_type = "cohens.d", + es_type = NULL, backend = NULL, verbose = TRUE, ... @@ -317,6 +318,12 @@ estimate_contrasts.default <- function( # validate input estimate <- .validate_estimate_arg(estimate) comparison <- .check_for_inequality_comparison(comparison) + # Validate es_type usage + if (is.null(effectsize) && !is.null(es_type)) { + insight::format_error( + "`es_type` can only be used when `effectsize` is specified. Currently `effectsize = NULL`." + ) + } if (backend == "emmeans") { # Emmeans ---------------------------------------------------------------- diff --git a/R/estimate_contrasts_effectsize.R b/R/estimate_contrasts_effectsize.R index ce683c357..242cb9d7a 100644 --- a/R/estimate_contrasts_effectsize.R +++ b/R/estimate_contrasts_effectsize.R @@ -1,15 +1,23 @@ -.estimate_contrasts_effectsize <- function(model, - estimated, - contrasts_results, - effectsize, - bootstraps, - bootES_type, - backend) { +.estimate_contrasts_effectsize <- function( + model, + estimated, + contrasts_results, + effectsize, + bootstraps, + bootES_type, + backend +) { # Add standardized effect size insight::validate_argument(effectsize, c("none", "emmeans", "marginal", "boot")) if (effectsize == "emmeans" && backend != "emmeans") { - insight::format_error("`effectsize = \"emmeans\"` only possible with `backend = \"emmeans\"`") + insight::format_error( + "`effectsize = \"emmeans\"` only possible with `backend = \"emmeans\"`" + ) + } + + if (!is.null(bootES_type) && effectsize != "boot") { + insight::format_error("`es_type` can only be used when `effectsize = \"boot\"`.") } # Check if the model includes any random effects. Effect size calculations in @@ -36,7 +44,8 @@ )) } - switch(effectsize, + switch( + effectsize, emmeans = { eff <- emmeans::eff_size( estimated, @@ -54,10 +63,16 @@ # d_adj <- contrasts$t * contrasts$SE / sigma(model) * sqrt(1 - R2) # New: d_adj <- difference * (1- R2)/ sigma R2 <- summary(model)$r.squared - d_adj <- contrasts_results$Difference * (1 - R2) / insight::get_sigma(model, verbose = FALSE) + d_adj <- contrasts_results$Difference * + (1 - R2) / + insight::get_sigma(model, verbose = FALSE) contrasts_results <- cbind(contrasts_results, marginal_d = d_adj) }, boot = { + # set default + if (is.null(bootES_type)) { + bootES_type <- "cohens.d" + } insight::check_if_installed("bootES") dat <- insight::get_data(model) resp <- insight::find_response(model) @@ -84,7 +99,11 @@ eff <- do.call(rbind, es.lists) eff <- eff[1:3] - names(eff) <- c(bootES_type, paste0(bootES_type, "_CI_low"), paste0(bootES_type, "_CI_high")) + names(eff) <- c( + bootES_type, + paste0(bootES_type, "_CI_low"), + paste0(bootES_type, "_CI_high") + ) contrasts_results <- cbind(contrasts_results, eff) } diff --git a/R/estimate_means.R b/R/estimate_means.R index 07860b417..223592d12 100644 --- a/R/estimate_means.R +++ b/R/estimate_means.R @@ -306,7 +306,7 @@ #' #' The output from `equivalence_test()` returns a column `SGPV`, the "second #' generation p-value", which is equivalent to the `p (Equivalence)` column when -#' using the `equivalence` argument. It is basically representiv the ROPE coverage +#' using the `equivalence` argument. It is basically representative of the ROPE coverage #' from the confidence interval of the estimate (i.e. the proportion of the #' confidence intervals that lies within the region of practical equivalence). #' @@ -414,16 +414,18 @@ #' estimate_means(model, by = "Sepal.Width", length = 3) #' } #' @export -estimate_means <- function(model, - by = "auto", - predict = NULL, - ci = 0.95, - estimate = NULL, - transform = NULL, - keep_iterations = FALSE, - backend = NULL, - verbose = TRUE, - ...) { +estimate_means <- function( + model, + by = "auto", + predict = NULL, + ci = 0.95, + estimate = NULL, + transform = NULL, + keep_iterations = FALSE, + backend = NULL, + verbose = TRUE, + ... +) { # Process argument --------------------------------------------------------- # -------------------------------------------------------------------------- @@ -469,12 +471,16 @@ estimate_means <- function(model, info <- attributes(estimated) # Table formatting - attr(means, "table_title") <- c(switch(estimate, - specific = "Model-based Predictions", - typical = "Estimated Marginal Means", - average = "Average Predictions", - population = "Average Counterfactual Predictions" - ), "blue") + attr(means, "table_title") <- c( + switch( + estimate, + specific = "Model-based Predictions", + typical = "Estimated Marginal Means", + average = "Average Predictions", + population = "Average Counterfactual Predictions" + ), + "blue" + ) attr(means, "table_footer") <- .table_footer( means, diff --git a/inst/WORDLIST b/inst/WORDLIST index 22430aa17..c1057ba81 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -1,45 +1,39 @@ -’s ANCOVAs -Arel -ATE ATEs ATT ATU +Analysing +Arel Axelsson -BH BLUPs Bundock -cdot -Chatton CJ -coefficients’ -diag -Dickerman -Dom +Chatton DS +Dickerman EFC EMM EMMs EUROFAMCARE Fitzsimons GAMM +GLM's GLMM GLMMs -GLM's GMM GMMs Greifer Heiss -Hernan Hernán ICC's ICCs IPW Intersectional Intersectionality +JOSS +LM Leckie Lenth -LM MAIHDA Mattan McCabe @@ -49,37 +43,34 @@ Merlo Mize Mmmh Modelisation -Modelling -Møller Montiel Mulinari +Møller Neyman -Olea +Nonresponse ORCID +Olea Owww -PCVs PCV +PCVs Plagborg -QoL Psychometrika +QoL RCTs README -Rohrer RStudio RTs Ratcliff -Reproducibility -Rescaling +Rohrer +SSM +SV +SVARs Setosa Shachar Spiller -SSM Subramanian -SV -SVARs Versicolor Virginica -Visualisation Visualising Wagenmakers Weisberg @@ -87,40 +78,30 @@ Wemrell Wiernik al analysing -bc behaviour -blogpost -bocode -bonferroni bootES brglm brms -caregiving +cdot ception codecov -computable +coefficients’ conditionspeed -counterfactuals confounder -confounders coxme d'être -d’être dat datagrid datawizard +diag doi dpar +d’être easystats -edu -effectsize emmeans -emtrends et exchangeability favour -fdr -fmwww foR generalizability geoms @@ -128,75 +109,47 @@ ggplot github glmmTMB glms -grano grey -hochberg -holm -hommel -http https -individuals' -interpretable +individuals’ intersectional intersectionality intra -io jmr joss labelled -lifecycle lme -lme4 loess marginaleffects -marginalizations mattansb modelisation modelled modelling -natively nd nnet ol onwards partialled -patilindrajeets -pscl pre -quartiles +pscl rOpenSci -Remotes raison -recoding -recodings -repec -reproducibility -rescaled -rescales -residualize residualized +residualizes rootSolve rstanarm -salis spinoff ssmph -strengejacke -summarised summarises -terciles -transint -tukey -ultron -uninformativeness +tinyplot unidimensional +uninformativeness unstandardizing usecases versicolor virginica visualisation visualise -visualising walkthrough -Nonresponse -tinyplot ’ +’s diff --git a/man/estimate_contrasts.Rd b/man/estimate_contrasts.Rd index 7bbdfcaa7..c49262e5e 100644 --- a/man/estimate_contrasts.Rd +++ b/man/estimate_contrasts.Rd @@ -20,7 +20,7 @@ estimate_contrasts(model, ...) keep_iterations = FALSE, effectsize = NULL, iterations = 200, - es_type = "cohens.d", + es_type = NULL, backend = NULL, verbose = TRUE, ... @@ -244,7 +244,9 @@ size will be computed.} \item{es_type}{Specifies the type of effect-size measure to estimate when using \code{effectsize = "boot"}. One of \code{"unstandardized"}, \code{"cohens.d"}, -\code{"hedges.g"}, \code{"cohens.d.sigma"}, \code{"r"}, or \code{"akp.robust.d"}. See\code{ effect.type} argument of \link[bootES:bootES]{bootES::bootES} for details.} +\code{"hedges.g"}, \code{"cohens.d.sigma"}, \code{"r"}, or \code{"akp.robust.d"}. See \code{effect.type} +argument of \code{\link[bootES:bootES]{bootES::bootES()}} for details. If not specified, defaults to +\code{"cohens.d"}.} \item{backend}{Whether to use \code{"marginaleffects"} (default) or \code{"emmeans"} as a backend. Results are usually very similar. The major difference will be diff --git a/man/estimate_means.Rd b/man/estimate_means.Rd index 906f04894..8802eee86 100644 --- a/man/estimate_means.Rd +++ b/man/estimate_means.Rd @@ -351,7 +351,7 @@ p-values returned when using the \code{equivalence} argument. The output from \code{equivalence_test()} returns a column \code{SGPV}, the "second generation p-value", which is equivalent to the \code{p (Equivalence)} column when -using the \code{equivalence} argument. It is basically representiv the ROPE coverage +using the \code{equivalence} argument. It is basically representative of the ROPE coverage from the confidence interval of the estimate (i.e. the proportion of the confidence intervals that lies within the region of practical equivalence). } diff --git a/tests/testthat/test-estimate_contrasts_effectsize.R b/tests/testthat/test-estimate_contrasts_effectsize.R index 52346c495..1db8b620a 100644 --- a/tests/testthat/test-estimate_contrasts_effectsize.R +++ b/tests/testthat/test-estimate_contrasts_effectsize.R @@ -10,54 +10,64 @@ data(iris) model <- lm(Sepal.Width ~ Species, data = iris) test_that("estimate_contrasts - emmeans backend", { - expect_snapshot(estimate_contrasts(model, backend = "emmeans"), + expect_snapshot(estimate_contrasts(model, backend = "emmeans"), variant = "windows") + expect_snapshot( + estimate_contrasts(model, effectsize = "none", backend = "emmeans"), variant = "windows" ) - expect_snapshot(estimate_contrasts(model, effectsize = "none", backend = "emmeans"), + expect_snapshot( + estimate_contrasts(model, effectsize = "emmeans", backend = "emmeans"), variant = "windows" ) - expect_snapshot(estimate_contrasts(model, effectsize = "emmeans", backend = "emmeans"), + expect_snapshot( + estimate_contrasts(model, effectsize = "marginal", backend = "emmeans"), variant = "windows" ) - expect_snapshot(estimate_contrasts(model, effectsize = "marginal", backend = "emmeans"), + set.seed(100) + expect_snapshot( + estimate_contrasts(model, effectsize = "boot", backend = "emmeans"), variant = "windows" ) set.seed(100) - expect_snapshot(estimate_contrasts(model, effectsize = "boot", backend = "emmeans"), + expect_snapshot( + estimate_contrasts( + model, + effectsize = "boot", + es_type = "akp.robust.d", + backend = "emmeans" + ), variant = "windows" ) set.seed(100) - expect_snapshot(estimate_contrasts(model, - effectsize = "boot", - es_type = "akp.robust.d", - backend = "emmeans" - ), variant = "windows") - set.seed(100) - expect_snapshot(estimate_contrasts( - model, - effectsize = "boot", - es_type = "hedges.g", - backend = "emmeans" - ), variant = "windows") + expect_snapshot( + estimate_contrasts(model, effectsize = "boot", es_type = "hedges.g", backend = "emmeans"), + variant = "windows" + ) }) test_that("estimate_contrasts - marginaleffects backend", { expect_snapshot(estimate_contrasts(model, backend = "marginaleffects"), variant = "windows") - expect_snapshot(estimate_contrasts(model, effectsize = "none", backend = "marginaleffects"), + expect_snapshot( + estimate_contrasts(model, effectsize = "none", backend = "marginaleffects"), variant = "windows" ) expect_error( estimate_contrasts(model, effectsize = "emmeans", backend = "marginaleffects"), "only possible with" ) - expect_snapshot(estimate_contrasts(model, effectsize = "marginal", backend = "marginaleffects"), + expect_snapshot( + estimate_contrasts(model, effectsize = "marginal", backend = "marginaleffects"), variant = "windows" ) }) test_that("estimate_contrasts - random effects", { sleepstudy <- lme4::sleepstudy - sleepstudy$Days_factor <- cut(sleepstudy$Days, breaks = 3, labels = c("Low", "Medium", "High")) + sleepstudy$Days_factor <- cut( + sleepstudy$Days, + breaks = 3, + labels = c("Low", "Medium", "High") + ) model_random_effects <- lme4::lmer(Reaction ~ Days_factor + (1 | Subject), data = sleepstudy) expect_error( @@ -65,3 +75,59 @@ test_that("estimate_contrasts - random effects", { "We strongly recommend not using" ) }) + +test_that("estimate_contrasts - es_type only with effectsize='boot'", { + # Should error when es_type is used with effectsize != "boot" + expect_error( + estimate_contrasts( + model, + effectsize = "emmeans", + es_type = "hedges.g", + backend = "emmeans" + ), + "can only be used when" + ) + + expect_error( + estimate_contrasts( + model, + effectsize = "marginal", + es_type = "hedges.g", + backend = "emmeans" + ), + "can only be used when" + ) + + expect_error( + estimate_contrasts( + model, + effectsize = "marginal", + es_type = "hedges.g", + backend = "marginaleffects" + ), + "can only be used when" + ) + + # Should error when es_type is used with effectsize = NULL + expect_error( + estimate_contrasts(model, es_type = "hedges.g", backend = "emmeans"), + "can only be used when" + ) + + # Should work when es_type is used with effectsize = "boot" + set.seed(100) + result <- estimate_contrasts( + model, + effectsize = "boot", + es_type = "hedges.g", + backend = "emmeans" + ) + expect_s3_class(result, "estimate_contrasts") + + # Should work when es_type is NOT specified (using default) + result_emmeans <- estimate_contrasts(model, effectsize = "emmeans", backend = "emmeans") + expect_s3_class(result_emmeans, "estimate_contrasts") + + result_marginal <- estimate_contrasts(model, effectsize = "marginal", backend = "emmeans") + expect_s3_class(result_marginal, "estimate_contrasts") +})