This function performs a Mann-Whitney test (or Wilcoxon rank sum test for unpaired samples). Unlike the underlying base R function wilcox.test(), this function allows for weighted tests and automatically calculates effect sizes. For paired (dependent) samples, or for one-sample tests, please use the wilcoxon_test() function.

A Mann-Whitney test is a non-parametric test for the null hypothesis that two independent samples have identical continuous distributions. It can be used for ordinal scales or when the two continuous variables are not normally distributed. For large samples, or approximately normally distributed variables, the t_test() function can be used.

mann_whitney_test(
  data,
  select = NULL,
  by = NULL,
  weights = NULL,
  mu = 0,
  alternative = "two.sided",
  ...
)

Arguments

data

A data frame.

select

Name(s) of the continuous variable(s) (as character vector) to be used as samples for the test. select can be one of the following:

  • select can be used in combination with by, in which case select is the name of the continous variable (and by indicates a grouping factor).

  • select can also be a character vector of length two or more (more than two names only apply to kruskal_wallis_test()), in which case the two continuous variables are treated as samples to be compared. by must be NULL in this case.

  • If select select is of length two and paired = TRUE, the two samples are considered as dependent and a paired test is carried out.

  • If select specifies one variable and by = NULL, a one-sample test is carried out (only applicable for t_test() and wilcoxon_test())

  • For chi_squared_test(), if select specifies one variable and both by and probabilities are NULL, a one-sample test against given probabilities is automatically conducted, with equal probabilities for each level of select.

by

Name of the variable indicating the groups. Required if select specifies only one variable that contains all samples to be compared in the test. If by is not a factor, it will be coerced to a factor. For chi_squared_test(), if probabilities is provided, by must be NULL.

weights

Name of an (optional) weighting variable to be used for the test.

mu

The hypothesized difference in means (for t_test()) or location shift (for wilcoxon_test() and mann_whitney_test()). The default is 0.

alternative

A character string specifying the alternative hypothesis, must be one of "two.sided" (default), "greater" or "less". See ?t.test and ?wilcox.test.

...

Additional arguments passed to wilcox.test() (for unweighted tests, i.e. when weights = NULL).

Value

A data frame with test results. The function returns p and Z-values as well as effect size r and group-rank-means.

Details

This function is based on wilcox.test() and coin::wilcox_test() (the latter to extract effect sizes). The weighted version of the test is based on survey::svyranktest().

Interpretation of the effect size r, as a rule-of-thumb:

  • small effect >= 0.1

  • medium effect >= 0.3

  • large effect >= 0.5

r is calcuated as \(r = \frac{|Z|}{\sqrt{n1 + n2}}\).

Which test to use

The following table provides an overview of which test to use for different types of data. The choice of test depends on the scale of the outcome variable and the number of samples to compare.

SamplesScale of OutcomeSignificance Test
1binary / nominalchi_squared_test()
1continuous, not normalwilcoxon_test()
1continuous, normalt_test()
2, independentbinary / nominalchi_squared_test()
2, independentcontinuous, not normalmann_whitney_test()
2, independentcontinuous, normalt_test()
2, dependentbinary (only 2x2)chi_squared_test(paired=TRUE)
2, dependentcontinuous, not normalwilcoxon_test()
2, dependentcontinuous, normalt_test(paired=TRUE)
>2, independentcontinuous, not normalkruskal_wallis_test()
>2, independentcontinuous, normaldatawizard::means_by_group()
>2, dependentcontinuous, not normalnot yet implemented (1)
>2, dependentcontinuous, normalnot yet implemented (2)

(1) More than two dependent samples are considered as repeated measurements. For ordinal or not-normally distributed outcomes, these samples are usually tested using a friedman.test(), which requires the samples in one variable, the groups to compare in another variable, and a third variable indicating the repeated measurements (subject IDs).

(2) More than two dependent samples are considered as repeated measurements. For normally distributed outcomes, these samples are usually tested using a ANOVA for repeated measurements. A more sophisticated approach would be using a linear mixed model.

References

  • Ben-Shachar, M.S., Patil, I., Thériault, R., Wiernik, B.M., Lüdecke, D. (2023). Phi, Fei, Fo, Fum: Effect Sizes for Categorical Data That Use the Chi‑Squared Statistic. Mathematics, 11, 1982. doi:10.3390/math11091982

  • Bender, R., Lange, S., Ziegler, A. Wichtige Signifikanztests. Dtsch Med Wochenschr 2007; 132: e24–e25

  • du Prel, J.B., Röhrig, B., Hommel, G., Blettner, M. Auswahl statistischer Testverfahren. Dtsch Arztebl Int 2010; 107(19): 343–8

See also

  • t_test() for parametric t-tests of dependent and independent samples.

  • mann_whitney_test() for non-parametric tests of unpaired (independent) samples.

  • wilcoxon_test() for Wilcoxon rank sum tests for non-parametric tests of paired (dependent) samples.

  • kruskal_wallis_test() for non-parametric tests with more than two independent samples.

  • chi_squared_test() for chi-squared tests (two categorical variables, dependent and independent).

Examples

data(efc)
# Mann-Whitney-U tests for elder's age by elder's sex.
mann_whitney_test(efc, "e17age", by = "e16sex")
#> # Mann-Whitney test
#> 
#>   Group 1: male   (n = 294, rank mean = 147.50)
#>   Group 2: female (n = 596, rank mean = 298.50)
#>   Alternative hypothesis: true location shift is not equal to 0
#> 
#>   W = 59684 , r = 0.26, Z = -7.75, p < .001
#> 
# base R equivalent
wilcox.test(e17age ~ e16sex, data = efc)
#> 
#> 	Wilcoxon rank sum test with continuity correction
#> 
#> data:  e17age by e16sex
#> W = 59684, p-value = 9.348e-15
#> alternative hypothesis: true location shift is not equal to 0
#> 

# when data is in wide-format, specify all relevant continuous
# variables in `select` and omit `by`
set.seed(123)
wide_data <- data.frame(scale1 = runif(20), scale2 = runif(20))
mann_whitney_test(wide_data, select = c("scale1", "scale2"))
#> # Mann-Whitney test
#> 
#>   Group 1: scale1 (n = 20, rank mean = 10.50)
#>   Group 2: scale2 (n = 20, rank mean = 10.50)
#>   Alternative hypothesis: true location shift is not equal to 0
#> 
#>   W = 188 , r = 0.05, Z = -0.32, p = 0.758
#> 
# base R equivalent
wilcox.test(wide_data$scale1, wide_data$scale2)
#> 
#> 	Wilcoxon rank sum exact test
#> 
#> data:  wide_data$scale1 and wide_data$scale2
#> W = 188, p-value = 0.7584
#> alternative hypothesis: true location shift is not equal to 0
#> 
# same as if we had data in long format, with grouping variable
long_data <- data.frame(
  scales = c(wide_data$scale1, wide_data$scale2),
  groups = as.factor(rep(c("A", "B"), each = 20))
)
mann_whitney_test(long_data, select = "scales", by = "groups")
#> # Mann-Whitney test
#> 
#>   Group 1: A (n = 20, rank mean = 10.50)
#>   Group 2: B (n = 20, rank mean = 10.50)
#>   Alternative hypothesis: true location shift is not equal to 0
#> 
#>   W = 188 , r = 0.05, Z = -0.32, p = 0.758
#> 
# base R equivalent
wilcox.test(scales ~ groups, long_data)
#> 
#> 	Wilcoxon rank sum exact test
#> 
#> data:  scales by groups
#> W = 188, p-value = 0.7584
#> alternative hypothesis: true location shift is not equal to 0
#>