Provides a pipe-friendly framework to perform different types of ANOVA tests, including:

The function is an easy to use wrapper around Anova() and aov(). It makes ANOVA computation handy in R and It's highly flexible: can support model and formula as input. Variables can be also specified as character vector using the arguments dv, wid, between, within, covariate.

The results include ANOVA table, generalized effect size and some assumption checks.

anova_test(
  data,
  formula,
  dv,
  wid,
  between,
  within,
  covariate,
  type = NULL,
  effect.size = "ges",
  error = NULL,
  white.adjust = FALSE,
  observed = NULL,
  detailed = FALSE,
  ci = NULL
)

get_anova_table(x, correction = c("auto", "GG", "HF", "none"))

# S3 method for class 'anova_test'
print(x, ...)

# S3 method for class 'anova_test'
plot(x, ...)

Arguments

data

a data.frame or a model to be analyzed.

formula

a formula specifying the ANOVA model similar to aov. Can be of the form y ~ group where y is a numeric variable giving the data values and group is a factor with one or multiple levels giving the corresponding groups. For example, formula = TP53 ~ cancer_group.

Examples of supported formula include:

  • Between-Ss ANOVA (independent measures ANOVA): y ~ b1*b2

  • Within-Ss ANOVA (repeated measures ANOVA): y ~ w1*w2 + Error(id/(w1*w2))

  • Mixed ANOVA: y ~ b1*b2*w1 + Error(id/w1)

If the formula doesn't contain any within vars, a linear model is directly fitted and passed to the ANOVA function. For repeated designs, the ANOVA variables are parsed from the formula.

dv

(numeric) dependent variable name.

wid

(factor) column name containing individuals/subjects identifier. Should be unique per individual.

between

(optional) between-subject factor variables.

within

(optional) within-subjects factor variables

covariate

(optional) covariate names (for ANCOVA)

type

the type of sums of squares for ANOVA. Allowed values are either 1, 2 or 3. type = 2 is the recommended default because it yields identical ANOVA results to type = 1 when data are balanced, while also producing various assumption tests where appropriate. When the data are unbalanced, type = 3 is the choice used by popular commercial softwares including SPSS.

Default when type is not specified: the chosen default depends on the interface (see Note), so for unbalanced designs the two interfaces can differ. To get reproducible, interface-independent results, set type explicitly (e.g. type = 3 for an unbalanced factorial design with interactions).

effect.size

the effect size to compute and to show in the ANOVA results. Allowed values can be either "ges" (generalized eta squared) or "pes" (partial eta squared) or both. Default is "ges".

error

(optional) for a linear model, an lm model object from which the overall error sum of squares and degrees of freedom are to be calculated. Read more in Anova() documentation.

white.adjust

Default is FALSE. If TRUE, heteroscedasticity correction is applied to the coefficient of covariance matrix. Used only for independent measures ANOVA.

observed

Variables that are observed (i.e, measured) as compared to experimentally manipulated. The default effect size reported (generalized eta-squared) requires correct specification of the observed variables.

detailed

If TRUE, returns extra information (sums of squares columns, intercept row, etc.) in the ANOVA table.

ci

confidence level for a confidence interval on the effect size. If a number between 0 and 1 (e.g. 0.95), two columns conf.low and conf.high are added giving the confidence interval for partial eta squared (effect.size must include "pes"). The interval is computed from the noncentral F distribution (Steiger, 2004) in base R. No interval is provided for generalized eta squared ("ges"), which has no standard closed-form interval. Default is NULL (no interval; output unchanged).

x

an object of class anova_test

correction

character. Used only in repeated measures ANOVA test to specify which correction of the degrees of freedom should be reported for the within-subject factors. Possible values are:

  • "GG": applies Greenhouse-Geisser correction to all within-subjects factors even if the assumption of sphericity is met (i.e., Mauchly's test is not significant, p > 0.05).

  • "HF": applies Hyunh-Feldt correction to all within-subjects factors even if the assumption of sphericity is met,

  • "none": returns the ANOVA table without any correction and

  • "auto": apply automatically GG correction to only within-subjects factors violating the sphericity assumption (i.e., Mauchly's test p-value is significant, p <= 0.05).

...

additional arguments

Value

return an object of class anova_test a data frame containing the ANOVA table for independent measures ANOVA.

However, for repeated/mixed measures ANOVA, a list containing the following components are returned: ANOVA table, Mauchly's Test for Sphericity, Sphericity Corrections. These table are described more in the documentation of the function anova_summary().

The returned object has an attribute called args, which is a list holding the arguments used to fit the ANOVA model, including: data, dv, within, between, type, model, etc.

Details

Contrasts. By default, R uses treatment contrasts (contr.treatment), where each factor level is compared to the first level used as baseline; the current setting can be checked with options('contrasts').

How anova_test() handles contrasts depends on the interface you use:

  • When you use the formula interface (or the dv + between/within arguments), anova_test() fits the model internally with options(contrasts = c('contr.sum', 'contr.poly')), restoring your global option afterwards. This gives orthogonal contrasts, where every level is compared to the overall mean, and type-III results that match the most commonly used commercial softwares, like SPSS.

  • When you instead pass a pre-fitted model (lm() or aov()), anova_test() does not change its contrasts: the model keeps whatever contrasts were in effect when it was fitted (R's default contr.treatment unless you set otherwise). Fitting with the default treatment contrasts and then requesting type = 3 can therefore give different results from the formula interface.

To reproduce the formula-interface (SPSS) result from a pre-fitted model, or to obtain the same result with car::Anova() directly, set options(contrasts = c('contr.sum', 'contr.poly')) before fitting the model and use type = 3.

Functions

  • anova_test(): perform anova test

  • get_anova_table(): extract anova table from an object of class anova_test. When within-subject factors are present, either sphericity corrected or uncorrected degrees of freedom can be reported.

Note

Default sums-of-squares type differs between the two interfaces for unbalanced designs. When type is not supplied:

  • the formula interface (anova_test(data, y ~ a*b)) uses type II for between-subjects designs, regardless of balance;

  • the dv=/between=/within= interface uses type II for balanced between-subjects designs but switches to type III for unbalanced between-subjects designs with more than one factor (both interfaces use type III for repeated-measures designs).

For a balanced design the SS types coincide, so the two interfaces agree. For an unbalanced factorial design they can give different main-effect F/p values unless you pass type explicitly — which is recommended for reproducibility. Example:


 d <- mtcars %>% dplyr::mutate(cyl = factor(cyl), am = factor(am))
 # differ (unbalanced): formula -> type II, dv/between -> type III
 d %>% anova_test(mpg ~ cyl * am)
 d %>% anova_test(dv = mpg, between = c(cyl, am))
 # agree once type is explicit:
 d %>% anova_test(mpg ~ cyl * am, type = 3)
 d %>% anova_test(dv = mpg, between = c(cyl, am), type = 3)
 

Author

Alboukadel Kassambara, alboukadel.kassambara@gmail.com

Examples

# Load data
#:::::::::::::::::::::::::::::::::::::::
data("ToothGrowth")
df <- ToothGrowth

# One-way ANOVA test
#:::::::::::::::::::::::::::::::::::::::::
df %>% anova_test(len ~ dose)
#> ANOVA Table (type II tests)
#> 
#>   Effect DFn DFd       F        p p<.05   ges
#> 1   dose   1  58 105.065 1.23e-14     * 0.644

# Grouped One-way ANOVA test
#:::::::::::::::::::::::::::::::::::::::::
df %>%
  group_by(supp) %>%
  anova_test(len ~ dose)
#> # A tibble: 2 × 8
#>   supp  Effect   DFn   DFd     F        p `p<.05`   ges
#> * <fct> <chr>  <dbl> <dbl> <dbl>    <dbl> <chr>   <dbl>
#> 1 OJ    dose       1    28  36.0 1.82e- 6 *       0.563
#> 2 VC    dose       1    28 118.  1.51e-11 *       0.808

# Two-way ANOVA test
#:::::::::::::::::::::::::::::::::::::::::
df %>% anova_test(len ~ supp*dose)
#> ANOVA Table (type II tests)
#> 
#>      Effect DFn DFd       F        p p<.05   ges
#> 1      supp   1  56  12.317 8.94e-04     * 0.180
#> 2      dose   1  56 133.415 1.91e-16     * 0.704
#> 3 supp:dose   1  56   5.333 2.50e-02     * 0.087

# Two-way repeated measures ANOVA
#:::::::::::::::::::::::::::::::::::::::::
df$id <- rep(1:10, 6) # Add individuals id
# Use formula
# \donttest{
df %>% anova_test(len ~ supp*dose + Error(id/(supp*dose)))
#> ANOVA Table (type III tests)
#> 
#> $ANOVA
#>      Effect DFn DFd       F        p p<.05   ges
#> 1      supp   1   9  34.866 2.28e-04     * 0.224
#> 2      dose   2  18 106.470 1.06e-10     * 0.773
#> 3 supp:dose   2  18   2.534 1.07e-01       0.132
#> 
#> $`Mauchly's Test for Sphericity`
#>      Effect     W     p p<.05
#> 1      dose 0.807 0.425      
#> 2 supp:dose 0.934 0.761      
#> 
#> $`Sphericity Corrections`
#>      Effect   GGe      DF[GG]    p[GG] p[GG]<.05   HFe      DF[HF]    p[HF]
#> 1      dose 0.838 1.68, 15.09 2.79e-09         * 1.008 2.02, 18.15 1.06e-10
#> 2 supp:dose 0.938 1.88, 16.88 1.12e-01           1.176 2.35, 21.17 1.07e-01
#>   p[HF]<.05
#> 1         *
#> 2          
#> 
# }


# or use character vector
df %>% anova_test(dv = len, wid = id, within = c(supp, dose))
#> ANOVA Table (type III tests)
#> 
#> $ANOVA
#>      Effect DFn DFd       F        p p<.05   ges
#> 1      supp   1   9  34.866 2.28e-04     * 0.224
#> 2      dose   2  18 106.470 1.06e-10     * 0.773
#> 3 supp:dose   2  18   2.534 1.07e-01       0.132
#> 
#> $`Mauchly's Test for Sphericity`
#>      Effect     W     p p<.05
#> 1      dose 0.807 0.425      
#> 2 supp:dose 0.934 0.761      
#> 
#> $`Sphericity Corrections`
#>      Effect   GGe      DF[GG]    p[GG] p[GG]<.05   HFe      DF[HF]    p[HF]
#> 1      dose 0.838 1.68, 15.09 2.79e-09         * 1.008 2.02, 18.15 1.06e-10
#> 2 supp:dose 0.938 1.88, 16.88 1.12e-01           1.176 2.35, 21.17 1.07e-01
#>   p[HF]<.05
#> 1         *
#> 2          
#> 

# Extract ANOVA table and apply correction
#:::::::::::::::::::::::::::::::::::::::::
res.aov <- df %>% anova_test(dv = len, wid = id, within = c(supp, dose))
get_anova_table(res.aov, correction = "GG")
#> ANOVA Table (type III tests)
#> 
#>      Effect  DFn   DFd       F        p p<.05   ges
#> 1      supp 1.00  9.00  34.866 2.28e-04     * 0.224
#> 2      dose 1.68 15.09 106.470 2.79e-09     * 0.773
#> 3 supp:dose 1.88 16.88   2.534 1.12e-01       0.132


# Use model as arguments
#:::::::::::::::::::::::::::::::::::::::::
.my.model <- lm(yield ~ block + N*P*K, npk)
anova_test(.my.model)
#> ANOVA Table (type II tests)
#> 
#>   Effect DFn DFd      F     p p<.05   ges
#> 1  block   4  12  4.959 0.014     * 0.623
#> 2      N   1  12 12.259 0.004     * 0.505
#> 3      P   1  12  0.544 0.475       0.043
#> 4      K   1  12  6.166 0.029     * 0.339
#> 5    N:P   1  12  1.378 0.263       0.103
#> 6    N:K   1  12  2.146 0.169       0.152
#> 7    P:K   1  12  0.031 0.863       0.003
#> 8  N:P:K   0  12     NA    NA  <NA>    NA