I’ve been analysing some future thinking data and playing around with packages that can do repeated ANOVA (I know, I should do LMM). There is more than one way to skin a cat and the differences come down to two things.

- the intuitiveness of the function arguments
- the readibility of the output

Some checks to do before you start

- all of these packages assume that you within and between subjects variables are factors, but also that your participant id is a factor

This code comes from the ANOVA cookbook

http://www.cookbook-r.com/Statistical_analysis/ANOVA/#more-anovas-with-within-subjects-variables

For a mixed RM with 1 between and 2 within you would use…

```
# for mixed RM with 1 between and 2 within
aov1 <- aov(outcome ~ b1 * w1 * w2 + Error(participant/(w1 *w2)) + b1, data = data_long)
```

The output from `aov()`

is an object that you then run `summary()`

on. Its a good idea to use `options(scipen = 999)`

to get nonscientific notation, and `options(digits = 4)`

to get fewer dps in that chunk.

The standard `aov()`

output isnt that pretty but you can use the `broom`

package to pull the output into a tidy df.

https://cran.r-project.org/web/packages/broom/vignettes/broom.html

- tidy() constructs a data frame
- augment() add columns to the original data that was modeled
- glance() constructs a concise one-row summary of the model

ezANOVA easy wrapper for car package aov function

The ezANOVA() function asks you to specify…

- data=
- dv=
- wid = participants id
- within = if more than 1 use list .(factor1 , factor2)
- between =
- type = type 2 is best when design is unbalanced, spss does type 3 by default-not recommended.
- detailed = TRUE
- return_aov = TRUE

```
ez1 <- ezANOVA(data = data_long,
dv = outcome,
wid = participant,
within = .(w1, w2),
between = b1,
type = 2,
detailed = TRUE,
return_aov = TRUE)
```

The output is a list, which include a dataframe of ANOVA details. It gives a nice warning if your design is unbalanced and uses type 2 sums of squares by default (recommended for unbalanced).

You can call ez1$ANOVA to have it print the ANOVA dataframe and write_csv() to save it.

Including return_aov = TRUE also gives an aov object which might be useful in getting partial eta squared from the etasquared() function from the `heplots`

package.

For some reason, when I tried using tidy() from broom on the ez1 object, it didn’t work.

afex = Analysis of Factorial Experiments

https://github.com/singmann/afex

https://cran.r-project.org/web/packages/afex/vignettes/afex_anova_example.html

afex is nice because it includes generalised eta sq in output table. It also has plotting of ANOVA analysis embedded in the package via the afex_plot() function

```
afex1 <- aov_ez("participant", "outcome",
data_long,
between = "b1",
within = c("w1", "w2"))
afex1
```

You can print the output by simply typing afex1, or get a “nice” table using nice(afex1), you can also turn that nice table into a df, and them use kable to make it really nice :)

```
nice(afex1) #make a nice table
niceafex <- nice(afex1) #make it a dataframe
kable(niceafex) %>%
kable_styling() #print it in table format
```

The `emmeans`

(estimated marginal means) package is useful for following up effects with planned constrasts.

Get marginal means for a main effect by running the `emmeans`

function on your anova object and specifying the effect with a tilde. Then get paired contrasts by running the `pairs`

function on the emms

```
emm <- emmeans(afex1, ~ maineffect)
pairs(emmm)
```

```
emm2 <- emmeans(afex1, "effect1", by = "effect2")
pairs(emm2)
```

Find more complex interaction contrasts in the emmeans vignette

afex package also allows for ANOVA plotting

Need to specify…

- x = what you want on x axis
- trace = what you want connected by lines
- panel = what you want as subplots

```
afex_plot(afex1, x = "b1", trace= "b1", panel= "w2")
```

```
aov1 <- aov(outcome ~ b1 * w1 * w2 + Error(participant/(w1 *w2)) + b1, data = data_long)
ez1 <- ezANOVA(data = data_long,
dv = outcome,
wid = participant,
within = .(w1, w2),
between = b1,
type = 2,
detailed = TRUE,
return_aov = TRUE)
afex1 <- aov_ez("participant", "outcome",
data_long,
between = "b1",
within = c("w1", "w2"))
```

The old school aov() is best if you want to be consistent in the way formulas are set up for linear models, but for new users it is not very intuiative. I like ezANOVA, especially because it makes the user specify everything and it includes generalised eta sq in the output by default. It does move away from the standard linear model function construction, which might may it hard for new learners to transfer R skills across methods, but it emulates SPSS more closely, asking for within, between etc which is probably good for students new to R.

afex also doesn’t adhere to the lm formula style, but it is really simple. The output is the same as ezANOVA but additional plotting functionality embedded is definitely helpful. I REALLY like the nice() function for formatting things.

take home: afex is the favourite :)