Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New repeated_measures_d() #618

Merged
merged 29 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -211,11 +211,13 @@ export(rb_to_common_language)
export(rb_to_p_superiority)
export(rb_to_vda)
export(rb_to_wmw_odds)
export(repeated_measures_d)
export(riskratio)
export(riskratio_to_arr)
export(riskratio_to_logoddsratio)
export(riskratio_to_nnt)
export(riskratio_to_oddsratio)
export(rm_d)
export(rules)
export(sd_pooled)
export(standardise)
Expand Down
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

- This release changes the licensing model of `{effectsize}` to an MIT license.

## New features

- `repeated_measures_d()` to compute standardized mean differences (SMD) for repeated measures data.
- Also supported in `effectsize(<t.test(paired = TRUE)>)`

# effectsize 0.8.7

## New features
Expand Down
23 changes: 18 additions & 5 deletions R/cohens_d.R
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#' variance). Else the mean SD from both groups is used instead.
#' @param paired If `TRUE`, the values of `x` and `y` are considered as paired.
#' This produces an effect size that is equivalent to the one-sample effect
#' size on `x - y`.
#' size on `x - y`. See also [repeated_measures_d()] for more options.
#' @param ... Arguments passed to or from other methods. When `x` is a formula,
#' these can be `subset` and `na.action`.
#' @inheritParams chisq_to_phi
Expand All @@ -48,7 +48,7 @@
#' `Glass_delta`) and their CIs (`CI_low` and `CI_high`).
#'
#' @family standardized differences
#' @seealso [sd_pooled()], [t_to_d()], [r_to_d()]
#' @seealso [rm_d()], [sd_pooled()], [t_to_d()], [r_to_d()]
#'
#' @examples
#' \donttest{
Expand Down Expand Up @@ -91,10 +91,12 @@
#'
#' # same as:
#' # cohens_d(sleep$extra[sleep$group == 1], sleep$extra[sleep$group == 2], paired = TRUE)
#' # cohens_d(sleep$extra[sleep$group == 1] - sleep$extra[sleep$group == 2])
#' # rm_d(sleep$extra[sleep$group == 1], sleep$extra[sleep$group == 2], method = "z", adjust = FALSE)
#'
#' # More options:
#' cohens_d(Pair(extra[group == 1], extra[group == 2]) ~ 1, data = sleep, mu = -1)
#' hedges_g(Pair(extra[group == 1], extra[group == 2]) ~ 1, data = sleep)
#' cohens_d(Pair(extra[group == 1], extra[group == 2]) ~ 1, data = sleep, mu = -1, verbose = FALSE)
#' hedges_g(Pair(extra[group == 1], extra[group == 2]) ~ 1, data = sleep, verbose = FALSE)
#'
#'
#' # Interpretation -----------------------
Expand Down Expand Up @@ -208,6 +210,12 @@ glass_delta <- function(x, y = NULL, data = NULL,
y <- out[["y"]]
paired <- out[["paired"]]

if (verbose && paired && !is.null(y)) {
insight::format_alert(
"For paired samples, 'repeated_measures_d()' provides more options."
)
}

if (is.null(y)) {
if (type == "delta") {
insight::format_error("For Glass' Delta, please provide data from two samples.")
Expand Down Expand Up @@ -287,7 +295,7 @@ glass_delta <- function(x, y = NULL, data = NULL,


if (type == "g") {
J <- exp(lgamma(df / 2) - log(sqrt(df / 2)) - lgamma((df - 1) / 2)) # exact method
J <- .J(df)

out[, colnames(out) %in% c("Hedges_g", "CI_low", "CI_high")] <-
out[, colnames(out) %in% c("Hedges_g", "CI_low", "CI_high")] * J
Expand All @@ -300,3 +308,8 @@ glass_delta <- function(x, y = NULL, data = NULL,
)
return(out)
}

#' @keywords internal
.J <- function(df) {
exp(lgamma(df / 2) - log(sqrt(df / 2)) - lgamma((df - 1) / 2)) # exact method
}
7 changes: 7 additions & 0 deletions R/common_language.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#' any reported [`stats::t.test()`] or [`stats::wilcox.test()`].
#'
#' @inheritParams cohens_d
#' @param paired If `TRUE`, the values of `x` and `y` are considered as paired.
#' This produces an effect size that is equivalent to the one-sample effect
#' size on `x - y`.
#' @param parametric Use parametric estimation (see [cohens_d()]) or
#' non-parametric estimation (see [rank_biserial()]). See details.
#' @param iterations The number of bootstrap replicates for computing confidence
Expand Down Expand Up @@ -126,6 +129,10 @@
paired <- data[["paired"]]

if (parametric) {
if (paired) {
x <- x - y
y <- NULL
}
d <- cohens_d(
x = x,
y = y,
Expand Down Expand Up @@ -446,7 +453,7 @@
out <- data.frame(ES = est(d))

if (.test_ci(ci) &&
insight::check_if_installed("boot", "for estimating CIs", stop = FALSE)) {

Check warning on line 456 in R/common_language.R

View workflow job for this annotation

GitHub Actions / lint / lint

file=R/common_language.R,line=456,col=6,[indentation_linter] Indentation should be 10 spaces but is 6 spaces.
ci.level <- .adjust_ci(ci, alternative)

out$CI <- ci
Expand All @@ -468,7 +475,7 @@

class(out) <- c("effectsize_table", class(out))
# TODO
# class(out) <- c("effectsize_difference", "effectsize_table", "see_effectsize_table", class(out))

Check warning on line 478 in R/common_language.R

View workflow job for this annotation

GitHub Actions / lint / lint

file=R/common_language.R,line=478,col=7,[commented_code_linter] Commented code should be removed.
.someattributes(out) <- .nlist(
mu, ci, ci_method, alternative,
approximate = TRUE,
Expand Down
30 changes: 30 additions & 0 deletions R/datasets.R
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,36 @@
#'
NULL

#' Jeff Rouder's Example Dataset for Repeated Measures
#'
#' A dataset "with 25 people each observing 50 trials in 2 conditions",
#' published as `effectSizePuzzler.txt` by Jeff Rouder on March 24, 2016
#' (_http://jeffrouder.blogspot.com/2016/03/the-effect-size-puzzler.html_).
#' \cr\cr
#' The data is used in examples and tests of [rm_d()].
#'
#' @docType data
#'
#' @name rouder2016
#'
#' @keywords data
#'
#' @format A data frame with 2500 rows and 3 variables:
#' \describe{
#' \item{id}{participant: 1...25}
#' \item{cond}{condition: 1,2}
#' \item{rt}{response time in seconds}
#' }
#'
#' ```{r}
#' data("rouder2016")
#' head(rouder2016, n = 5)
#' ```
#' @family effect size datasets
#'
NULL


#' Results from 2 Screening Tests
#'
#' A sample (simulated) dataset, used in tests and some examples.
Expand Down
8 changes: 8 additions & 0 deletions R/effectsize.R
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,23 @@
#'
#' @details
#'
#' - For an object of class `htest`, data is extracted via [insight::get_data()], and passed to the relevant function according to:

Check warning on line 15 in R/effectsize.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/effectsize.R,line=15,col=121,[line_length_linter] Lines should not be more than 120 characters. This line is 131 characters.
#' - A **t-test** depending on `type`: `"cohens_d"` (default), `"hedges_g"`, or one of `"p_superiority"`, `"u1"`, `"u2"`, `"u3"`, `"overlap"`.

Check warning on line 16 in R/effectsize.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/effectsize.R,line=16,col=121,[line_length_linter] Lines should not be more than 120 characters. This line is 144 characters.
#' - For a **Paired t-test**: depending on `type`: `"rm"`, `"av"`, `"b"`, `"d"`, `"z"`.
#' - A **Chi-squared tests of independence** or **Fisher's Exact Test**, depending on `type`: `"cramers_v"` (default), `"tschuprows_t"`, `"phi"`, `"cohens_w"`, `"pearsons_c"`, `"cohens_h"`, `"oddsratio"`, `"riskratio"`, `"arr"`, or `"nnt"`.

Check warning on line 18 in R/effectsize.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/effectsize.R,line=18,col=121,[line_length_linter] Lines should not be more than 120 characters. This line is 242 characters.
#' - A **Chi-squared tests of goodness-of-fit**, depending on `type`: `"fei"` (default) `"cohens_w"`, `"pearsons_c"`
#' - A **One-way ANOVA test**, depending on `type`: `"eta"` (default), `"omega"` or `"epsilon"` -squared, `"f"`, or `"f2"`.

Check warning on line 20 in R/effectsize.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/effectsize.R,line=20,col=121,[line_length_linter] Lines should not be more than 120 characters. This line is 125 characters.
#' - A **McNemar test** returns *Cohen's g*.
#' - A **Wilcoxon test** depending on `type`: returns "`rank_biserial`" correlation (default) or one of `"p_superiority"`, `"vda"`, `"u2"`, `"u3"`, `"overlap"`.

Check warning on line 22 in R/effectsize.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/effectsize.R,line=22,col=121,[line_length_linter] Lines should not be more than 120 characters. This line is 162 characters.
#' - A **Kruskal-Wallis test** depending on `type`: `"epsilon"` (default) or `"eta"`.
#' - A **Friedman test** returns *Kendall's W*.
#' (Where applicable, `ci` and `alternative` are taken from the `htest` if not otherwise provided.)
#' - For an object of class `BFBayesFactor`, using [bayestestR::describe_posterior()],
#' - A **t-test** depending on `type`: `"cohens_d"` (default) or one of `"p_superiority"`, `"u1"`, `"u2"`, `"u3"`, `"overlap"`.

Check warning on line 27 in R/effectsize.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/effectsize.R,line=27,col=121,[line_length_linter] Lines should not be more than 120 characters. This line is 129 characters.
#' - A **correlation test** returns *r*.
#' - A **contingency table test**, depending on `type`: `"cramers_v"` (default), `"phi"`, `"tschuprows_t"`, `"cohens_w"`, `"pearsons_c"`, `"cohens_h"`, `"oddsratio"`, or `"riskratio"`, `"arr"`, or `"nnt"`.

Check warning on line 29 in R/effectsize.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/effectsize.R,line=29,col=121,[line_length_linter] Lines should not be more than 120 characters. This line is 207 characters.
#' - A **proportion test** returns *p*.
#' - Objects of class `anova`, `aov`, `aovlist` or `afex_aov`, depending on `type`: `"eta"` (default), `"omega"` or `"epsilon"` -squared, `"f"`, or `"f2"`.

Check warning on line 31 in R/effectsize.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/effectsize.R,line=31,col=121,[line_length_linter] Lines should not be more than 120 characters. This line is 155 characters.
#' - Other objects are passed to [parameters::standardize_parameters()].
#'
#' **For statistical models it is recommended to directly use the listed
Expand All @@ -50,6 +51,13 @@
#' Tt <- t.test(1:10, y = c(7:20), alternative = "less")
#' effectsize(Tt)
#'
#' Tt <- t.test(
#' x = c(1.83, 0.50, 1.62, 2.48, 1.68, 1.88, 1.55, 3.06, 1.30),
#' y = c(0.878, 0.647, 0.598, 2.05, 1.06, 1.29, 1.06, 3.14, 1.29),
#' paired = TRUE
#' )
#' effectsize(Tt, type = "rm_b")
#'
#' Aov <- oneway.test(extra ~ group, data = sleep, var.equal = TRUE)
#' effectsize(Aov)
#' effectsize(Aov, type = "omega")
Expand Down
9 changes: 7 additions & 2 deletions R/effectsize.htest.R
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@
dots$alternative <- model$alternative
dots$ci <- attr(model$conf.int, "conf.level")
dots$mu <- model$null.value
dots$paired <- !grepl("Two", model$method, fixed = TRUE)
dots$paired <- grepl("Paired", model$method, fixed = TRUE)
dots$verbose <- verbose

if (!type %in% c("d", "g")) {
.fail_if_approx(approx, "cles")
.fail_if_approx(approx, if (startsWith(type, "rm")) "rm_d" else "cles")
}

if (approx) {
Expand Down Expand Up @@ -81,6 +81,11 @@
d = cohens_d,
g = hedges_g
)
} else if (dots$paired && startsWith(type, "rm")) {
args[c("x", "y")] <- split(args$x, args$y)
dots$paired <- args$pooled_sd <- NULL
args$method <- gsub("^rm\\_", "", type)
f <- rm_d
} else {
if (!dots$paired && !args$pooled_sd) {
insight::format_error("Common language effect size only applicable to Cohen's d with pooled SD.")
Expand Down Expand Up @@ -270,7 +275,7 @@

dots <- list(...)

if ((approx <- grepl("not assuming", model$method, fixed = TRUE)) && verbose) {

Check warning on line 278 in R/effectsize.htest.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/effectsize.htest.R,line=278,col=8,[implicit_assignment_linter] Avoid implicit assignments in function calls. For example, instead of `if (x <- 1L) { ... }`, write `x <- 1L; if (x) { ... }`.
insight::format_alert("`var.equal = FALSE` - effect size is an {.b approximation.}")
}

Expand Down
1 change: 0 additions & 1 deletion R/mahalanobis_D.R
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
#' @family standardized differences
#'
#' @references
#' - Del Giudice, M. (2017). Heterogeneity coefficients for Mahalanobis' D as a multivariate effect size. Multivariate Behavioral Research, 52(2), 216-221.

Check warning on line 41 in R/mahalanobis_D.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/mahalanobis_D.R,line=41,col=121,[line_length_linter] Lines should not be more than 120 characters. This line is 155 characters.
#' - Mahalanobis, P. C. (1936). On the generalized distance in statistics. National Institute of Science of India.
#' - Reiser, B. (2001). Confidence intervals for the Mahalanobis distance. Communications in Statistics-Simulation and Computation, 30(1), 37-45.
#'
Expand Down Expand Up @@ -85,7 +85,6 @@
pooled_cov = TRUE, mu = 0,
ci = 0.95, alternative = "greater",
verbose = TRUE, ...) {
# TODO add one sample case DV1 + DV2 ~ 1
# TODO add paired samples case DV1 + DV2 ~ 1 | ID
alternative <- .match.alt(alternative, FALSE)
data <- .get_data_multivariate(x, y, data, verbose = verbose, ...)
Expand Down
3 changes: 2 additions & 1 deletion R/print.effectsize_table.R
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@ print.effectsize_difference <- function(x, digits = 2, append_CLES = NULL, ...)

#' @export
format.effectsize_difference <- function(x, digits = 2, ...) {
caption <- subtitle <- footer <- NULL
caption <- subtitle <- NULL
footer <- attr(x, "table_footer")

## Add footer
mu <- attr(x, "mu")
Expand Down
1 change: 1 addition & 0 deletions R/rank_diff.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#' to the [Common Language Effect Sizes][cohens_u3]. Pair with any reported
#' [`stats::wilcox.test()`].
#'
#' @inheritParams p_superiority
#' @inheritParams cohens_d
#' @param x,y A numeric or ordered vector, or a character name of one in `data`.
#' Any missing values (`NA`s) are dropped from the resulting vector. `x` can
Expand Down
Loading
Loading