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

CI docs about 1-sided tests + default 90% CI for phi/V #366

Merged
merged 21 commits into from
Aug 18, 2021
Merged
Show file tree
Hide file tree
Changes from 6 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
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@

## Breaking Changes

- Phi, Cohen's *w*, Cramer's *V*, ANOVA effect sizes, rank Epsilon squared, Kendall's *W* - CIs default to 95% one-sided CIs (`alternative = "greater"`).
bwiernik marked this conversation as resolved.
Show resolved Hide resolved
- `adjust()`, `change_scale()`, `normalize()`, `ranktransform()`, `standardize()` (data), and `unstandardize()` have moved to the new [`{datawizard}`](https://easystats.github.io/datawizard) package!

## New features

- 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).

## Bug fixes

- `kendalls_w()` CIs now correctly bootstrap samples from the raw data (previously the rank-transformed data was sampled from).
- `cohens_d()`, `sd_pooled()` and `rank_biserial()` now properly respect when `y` is a grouping character vector.
- `effectsize()` for Chi-squared test of goodness-of-fit now correctly respects non-uniform expected probabilities ( #352 ).

Expand Down
68 changes: 40 additions & 28 deletions R/cohens_d.R
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
#' @param x A formula, a numeric vector, or a character name of one in `data`.
#' @param y A numeric vector, a grouping (character / factor) vector, a or a
#' character name of one in `data`. Ignored if `x` is a formula.
#' @param alternative a character string specifying the alternative hypothesis;
#' Controls the type of CI returned: `"two.sided"` (default, two-sided CI),
#' `"greater"` or `"less"` (one-sided CI). Partial matching is allowed (e.g.,
#' `"g"`, `"l"`, `"two"`...). See *One-Sided CIs* in [effectsize-CIs].
#' @param data An optional data frame containing the variables.
#' @param pooled_sd If `TRUE` (default), a [sd_pooled()] is used (assuming equal
#' variance). Else the mean SD from both groups is used instead.
Expand Down Expand Up @@ -44,7 +48,7 @@
#' @family effect size indices
#'
#' @examples
#'
#' \donttest{
#' data(mtcars)
#' mtcars$am <- factor(mtcars$am)
#'
Expand All @@ -58,6 +62,7 @@
#' # More options:
#' cohens_d(mpg ~ am, data = mtcars, pooled_sd = FALSE)
#' cohens_d(mpg ~ am, data = mtcars, mu = -5)
#' cohens_d(mpg ~ am, data = mtcars, alternative = "less")
#' hedges_g(mpg ~ am, data = mtcars)
#' glass_delta(mpg ~ am, data = mtcars)
#'
Expand Down Expand Up @@ -100,6 +105,8 @@
#' d_to_common_language(1.48)
#' # Or:
#' print(d, append_CL = TRUE)
#' }
#'
#' @references
#' - Algina, J., Keselman, H. J., & Penfield, R. D. (2006). Confidence intervals
#' for an effect size when variances are not equal. Journal of Modern Applied
Expand Down Expand Up @@ -127,27 +134,16 @@ cohens_d <- function(x,
mu = 0,
paired = FALSE,
ci = 0.95,
alternative = "two.sided",
verbose = TRUE,
...) {
if (inherits(x, "htest")) {
if (!grepl("t-test", x$method)) {
stop("'x' is not a t-test!", call. = FALSE)
}
return(effectsize(x, type = "d", ci = ci, verbose = verbose))
} else if (inherits(x, "BFBayesFactor")) {
if (!inherits(x@numerator[[1]], c("BFoneSample", "BFindepSample"))) {
stop("'x' is not a t-test!", call. = FALSE)
}
return(effectsize(x, ci = ci, verbose = verbose))
}


.effect_size_difference(
x,
y = y,
data = data,
type = "d",
pooled_sd = pooled_sd,
alternative = alternative,
mu = mu,
paired = paired,
ci = ci,
Expand All @@ -164,33 +160,23 @@ hedges_g <- function(x,
mu = 0,
paired = FALSE,
ci = 0.95,
alternative = "two.sided",
verbose = TRUE,
...,
correction) {
if (!missing(correction)) {
warning("`correction` argument is deprecated. *Exact* bias correction method is used.",
call. = FALSE, immediate. = TRUE
call. = FALSE, immediate. = TRUE
)
}

if (inherits(x, "htest")) {
if (!grepl("t-test", x$method)) {
stop("'x' is not a t-test!", call. = FALSE)
}
return(effectsize(x, type = "g", ci = ci, verbose = verbose))
} else if (inherits(x, "BFBayesFactor")) {
if (!inherits(x@numerator[[1]], c("BFoneSample", "BFindepSample"))) {
stop("'x' is not a t-test!", call. = FALSE)
}
return(effectsize(x, ci = ci, verbose = verbose))
}

.effect_size_difference(
x,
y = y,
data = data,
type = "g",
pooled_sd = pooled_sd,
alternative = alternative,
mu = mu,
paired = paired,
ci = ci,
Expand All @@ -205,6 +191,7 @@ glass_delta <- function(x,
data = NULL,
mu = 0,
ci = 0.95,
alternative = "two.sided",
verbose = TRUE,
...,
iterations) {
Expand All @@ -218,6 +205,7 @@ glass_delta <- function(x,
x,
y = y,
data = data,
alternative = alternative,
mu = mu,
type = "delta",
ci = ci,
Expand All @@ -234,11 +222,26 @@ glass_delta <- function(x,
data = NULL,
type = "d",
mu = 0,
alternative = "two.sided",
pooled_sd = TRUE,
paired = FALSE,
ci = 0.95,
verbose = TRUE,
...) {
if (type != "delta" && inherits(x, "htest")) {
if (!grepl("t-test", x$method)) {
stop("'x' is not a t-test!", call. = FALSE)
}
return(effectsize(x, type = type, ci = ci, alternative = alternative, verbose = verbose))
} else if (type != "delta" && inherits(x, "BFBayesFactor")) {
if (!inherits(x@numerator[[1]], c("BFoneSample", "BFindepSample"))) {
stop("'x' is not a t-test!", call. = FALSE)
}
return(effectsize(x, ci = ci, verbose = verbose))
}


alternative <- match.arg(alternative, c("two.sided", "less", "greater"))
out <- .deal_with_cohens_d_arguments(x, y, data, verbose)
x <- out$x
y <- out$y
Expand Down Expand Up @@ -313,13 +316,21 @@ glass_delta <- function(x,

# Add cis
out$CI <- ci
ci.level <- if (alternative == "two.sided") ci else 2 * ci - 1

t <- (d - mu) / se
ts <- .get_ncp_t(t, df, ci)
ts <- .get_ncp_t(t, df, ci.level)

out$CI_low <- ts[1] * sqrt(hn)
out$CI_high <- ts[2] * sqrt(hn)
ci_method <- list(method = "ncp", distribution = "t")
if (alternative == "less") {
out$CI_low <- -Inf
} else if (alternative == "greater") {
out$CI_high <- Inf
}
} else {
alternative <- NULL
}


Expand All @@ -338,6 +349,7 @@ glass_delta <- function(x,
attr(out, "ci") <- ci
attr(out, "ci_method") <- ci_method
attr(out, "approximate") <- FALSE
attr(out, "alternative") <- alternative
return(out)
}

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
35 changes: 30 additions & 5 deletions R/convert_chisq.R → R/convert_stat_chisq.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
#' @param nrow,ncol The number of rows/columns in the contingency table (ignored
#' for Phi when `adjust=FALSE` and `CI=NULL`).
#' @param ci Confidence Interval (CI) level
#' @param alternative a character string specifying the alternative hypothesis;
#' Controls the type of CI returned: `"greater"` (default) or `"less"`
#' (one-sided CI), or `"two.sided"` (default, two-sided CI). Partial matching
#' is allowed (e.g., `"g"`, `"l"`, `"two"`...). See *One-Sided CIs* in
#' [effectsize-CIs].
#' @param adjust Should the effect size be bias-corrected? Defaults to `FALSE`.
#' @param ... Arguments passed to or from other methods.
#'
Expand Down Expand Up @@ -36,7 +41,7 @@
#' #
#' # Pearson's Chi-squared test
#' #
#' # data: ctab
#' # data: contingency_table
#' # X-squared = 41.234, df = 4, p-value = 2.405e-08
#'
#' chisq_to_phi(41.234,
Expand All @@ -58,7 +63,8 @@
#' Journal of the Korean Statistical Society, 42(3), 323-328.
#'
#' @export
chisq_to_phi <- function(chisq, n, nrow, ncol, ci = 0.95, adjust = FALSE, ...) {
chisq_to_phi <- function(chisq, n, nrow, ncol, ci = 0.95, alternative = "greater", adjust = FALSE, ...) {
alternative <- match.arg(alternative, c("two.sided", "less", "greater"))
if (adjust || is.numeric(ci)) {
is_goodness <- ncol == 1 || nrow == 1

Expand All @@ -82,12 +88,13 @@ chisq_to_phi <- function(chisq, n, nrow, ncol, ci = 0.95, adjust = FALSE, ...) {
if (is.numeric(ci)) {
stopifnot(length(ci) == 1, ci < 1, ci > 0)
res$CI <- ci
ci.level <- if (alternative == "two.sided") ci else 2 * ci - 1

chisq_ <- phi_to_chisq(res[[1]], n)

chisqs <- t(mapply(
.get_ncp_chi,
chisq_, df, ci
chisq_, df, ci.level
))

res$CI_low <-
Expand All @@ -96,12 +103,20 @@ chisq_to_phi <- function(chisq, n, nrow, ncol, ci = 0.95, adjust = FALSE, ...) {
chisq_to_phi(chisqs[, 2], n, nrow, ncol, ci = NULL, adjust = FALSE)[[1]]

ci_method <- list(method = "ncp", distribution = "chisq")
if (alternative == "less") {
res$CI_low <- 0
} else if (alternative == "greater") {
res$CI_high <- 1
}
} else {
alternative <- NULL
}

class(res) <- c("effectsize_table", "see_effectsize_table", class(res))
attr(res, "ci") <- ci
attr(res, "ci_method") <- ci_method
attr(res, "adjust") <- adjust
attr(res, "alternative") <- alternative
return(res)
}

Expand All @@ -113,7 +128,8 @@ chisq_to_cohens_w <- chisq_to_phi

#' @rdname chisq_to_phi
#' @export
chisq_to_cramers_v <- function(chisq, n, nrow, ncol, ci = 0.95, adjust = FALSE, ...) {
chisq_to_cramers_v <- function(chisq, n, nrow, ncol, ci = 0.95, alternative = "greater", adjust = FALSE, ...) {
alternative <- match.arg(alternative, c("two.sided", "less", "greater"))
is_goodness <- ncol == 1 || nrow == 1


Expand Down Expand Up @@ -150,12 +166,13 @@ chisq_to_cramers_v <- function(chisq, n, nrow, ncol, ci = 0.95, adjust = FALSE,
if (is.numeric(ci)) {
stopifnot(length(ci) == 1, ci < 1, ci > 0)
res$CI <- ci
ci.level <- if (alternative == "two.sided") ci else 2 * ci - 1

chisq_ <- phi_to_chisq(phi, n)

chisqs <- t(mapply(
.get_ncp_chi,
chisq_, df, ci
chisq_, df, ci.level
))

res$CI_low <-
Expand All @@ -164,12 +181,20 @@ chisq_to_cramers_v <- function(chisq, n, nrow, ncol, ci = 0.95, adjust = FALSE,
chisq_to_cramers_v(chisqs[, 2], n, nrow, ncol, ci = NULL, adjust = FALSE)[[1]]

ci_method <- list(method = "ncp", distribution = "chisq")
if (alternative == "less") {
res$CI_low <- 0
} else if (alternative == "greater") {
res$CI_high <- 1
}
} else {
alternative <- NULL
}

class(res) <- c("effectsize_table", "see_effectsize_table", class(res))
attr(res, "ci") <- ci
attr(res, "ci_method") <- ci_method
attr(res, "adjust") <- adjust
attr(res, "alternative") <- alternative
return(res)
}

Expand Down
Loading