One-way Repeated Measures ANOVA

This guide covers how to conduct one-way repeated measures ANOVA with the jmv and rstatix packages. Repeated measures ANOVAs are used in cases where an observation from the same subject is taken multiple times. For example, an experimenter may wish to examine the changes in scores from a cognitive assessment gathered from the same participants at multiple ages.

The data set

The chapter_11_table_5 dataset from the AMCP package is from a hypothetical study that tracked the age-normed general cognitive scores from the McCarthy Scales of Children’s Abilities (MSCA) of 12 children at 4 different time points, .

library(AMCP)
library(kableExtra)
# Load data
data("chapter_11_table_5")

# Inspect data
kable(head(chapter_11_table_5))
Months30Months36Months42Months48
10896110122
103117127133
96107106107
84859299
118125125116
1101079691

Perform ANOVA tests


With the jmv package, coding repeated measures ANOVA is a bit more cumbersome compared to one- and two-way ANOVAS. We will have to set the rm option which takes a “list of lists”. For the one-way repeated measures design, we will need a list of one list that contains a label which will be “Age-in-months”, and a character vector of the levels of the age factor (i.e. 30, 60, 42, 48). Next, we will work on the rmCells by making another list of lists. This list will be made up of 4 lists, one for each level, and each list will have a measure that corresponds to the name of the column of the dataframe containing the data, and a cell that corresponds to each level. Now we can move on to specifying the repeated measure terms in “rmTerms.” For our purposes we will set spherCorr = 'none', but in practice you may want to apply a correction for sphericity depending on your data. We will then set effectSize = 'omega', and set emMeans = TRUE to produce the marginal means by months so that we can plot the data when emmPlots = TRUE.

library(jmv)

# Repeated measures anova with jmv
anovaRM(
  data = chapter_11_table_5,
  rm = list(
    list(
      label = "Age-in-months", 
      levels = c("30", "36", "42", "48"))),
  rmCells = list(
    list(
      measure = "Months30", 
      cell = "30"),
    list(
      measure = "Months36", 
      cell = "36"),
    list(
      measure = "Months42", 
      cell = "42"),
    list(
      measure = "Months48", 
      cell = "48")),
  rmTerms = list(
    "Age-in-months"),
  spherCorr = 'none',
  effectSize = 'partEta',
  emMeans = ~ `Age-in-months`,
  emmPlots = TRUE,
  postHocCorr = "none",
  postHoc = "Age-in-months",
  depLabel = "Mean MSCA Scores")
## 
##  REPEATED MEASURES ANOVA
## 
##  Within Subjects Effects                                                                        
##  ────────────────────────────────────────────────────────────────────────────────────────────── 
##                     Sum of Squares    df    Mean Square    F           p            η²-p        
##  ────────────────────────────────────────────────────────────────────────────────────────────── 
##    Age-in-months          552.0000     3      184.00000    3.026919    0.0432186    0.2157936   
##    Residual              2006.0000    33       60.78788                                         
##  ────────────────────────────────────────────────────────────────────────────────────────────── 
##    Note. Type 3 Sums of Squares
## 
## 
##  Between Subjects Effects                                                           
##  ────────────────────────────────────────────────────────────────────────────────── 
##                Sum of Squares    df    Mean Square    F    p            η²-p        
##  ────────────────────────────────────────────────────────────────────────────────── 
##    Residual          6624.000    11       602.1818                                  
##  ────────────────────────────────────────────────────────────────────────────────── 
##    Note. Type 3 Sums of Squares
## 
## 
##  POST HOC TESTS
## 
##  Post Hoc Comparisons - Age-in-months                                                                          
##  ───────────────────────────────────────────────────────────────────────────────────────────────────────────── 
##    Age-in-months         Age-in-months    Mean Difference    SE          df          t             p           
##  ───────────────────────────────────────────────────────────────────────────────────────────────────────────── 
##    30               -    36                     -4.000000    2.579053    11.00000    -1.5509568    0.1491893   
##                     -    42                     -7.000000    3.045115    11.00000    -2.2987635    0.0421235   
##                     -    48                     -9.000000    3.692745    11.00000    -2.4372115    0.0329854   
##    36               -    42                     -3.000000    2.757909    11.00000    -1.0877807    0.2999517   
##                     -    48                     -5.000000    4.316985    11.00000    -1.1582156    0.2713044   
##    42               -    48                     -2.000000    2.232677    11.00000    -0.8957855    0.3895495   
##  ─────────────────────────────────────────────────────────────────────────────────────────────────────────────
anovaRM plot of means by group.

Figure 1: anovaRM plot of means by group.


To perform a repeated measures ANOVA with rstatix, first create a new data frame with the subject id coded by a number. Next, convert the data from wide to long format. Next, convert the subject id and the age information to factor. Then, create the rm_aov object with the anova_test() function. This is the same function that was used in the one- and two-way ANOVA guides, but modified slightly. The modifications are found in the options wid = id to specify the subjects id factor, within = age to specify that our within subjects factor is age, and effect.size = "pes" to correspond with the jmv function. Finally, we will run the get_anova_table() function on our rm_aov object with correction = "none". In practice, you may want to change the correction setting even if your data do not violate the assumption of sphericity.

library(tidyverse)
library(rstatix)
library(ggpubr)

# Create a new data frame with a subject id
rm_data <- cbind(id = c(1:12), chapter_11_table_5)

# Convert from wide to long format then convert id and age to factor
rm_data <- rm_data %>% 
  gather(., age, score, Months30:Months48) %>%
  convert_as_factor(id, age)

# Inspect data
kable(head(rm_data))
idagescore
1Months30108
2Months30103
3Months3096
4Months3084
5Months30118
6Months30110

Conduct repeated measures ANOVA

rm_aov <- anova_test(data = rm_data, 
                     dv = score, 
                     wid = id, 
                     within = age, 
                     effect.size = "pes", 
                     detailed = TRUE)

# Print anova table
kable(get_anova_table(rm_aov, correction = "none"))
EffectDFnDFdSSnSSdFpp<.05pes
(Intercept)1115598726624929.7390.000*0.988
age33355220063.0270.043*0.216

Pairwise comparisons with pairwise_t_test

pwc <- rm_data %>%
  pairwise_t_test(score ~ age, 
                  paired = TRUE, 
                  p.adjust.method = "none")
kable(pwc)
.y.group1group2n1n2statisticdfpp.adjp.adj.signif
scoreMonths30Months361212-1.5509568110.1490.149ns
scoreMonths30Months421212-2.2987635110.0420.042*
scoreMonths30Months481212-2.4372115110.0330.033*
scoreMonths36Months421212-1.0877807110.3000.300ns
scoreMonths36Months481212-1.1582156110.2710.271ns
scoreMonths42Months481212-0.8957855110.3900.390ns

Plot the data

To plot the data, we can use the ggerrorplot() function. We will use the converted long-form rm_data rather than the wide chapter_11_table_5 dataframe. Then we just need to specify what to plot on the x and y axes, set add = "mean", desc_stat = "mean_ci", error.plot = “errorbar”, and width = .1.

ggerrorplot(rm_data,
            x = "age",
            y = "score",
            add = "mean",
            desc_stat = "mean_ci",
            error.plot = "errorbar",
            width = .1)
ggerrorplot plot of means and 95% confidence intervals by group.

Figure 2: ggerrorplot plot of means and 95% confidence intervals by group.

Back to tabs

Interpretation

For the omnibus test, we obtain a significant effect of Age [F(33,3) = 3.03, p < 0.05] which suggests that the means of the 4 ages are not equal. The omega squared value is 0.04 which suggest the about 4% of the variance in scores is accounted for by age in the ages studied.

Wrap up

For one-way repeated measures ANOVA, using the jmv package in R will become tedious as each column will need to specified in the rmCells = list(... argument. This will become even more burdensome in two-way repeated measures ANOVA.

References

Kassambara, Alboukadel. 2020a. Ggpubr: ’Ggplot2’ Based Publication Ready Plots. https://CRAN.R-project.org/package=ggpubr.

———. 2020b. Rstatix: Pipe-Friendly Framework for Basic Statistical Tests. https://CRAN.R-project.org/package=rstatix.

Maxwell, Scott, Harold Delaney, and Ken Kelley. 2020. AMCP: A Model Comparison Perspective. https://CRAN.R-project.org/package=AMCP.

Maxwell, Scott E, Harold D Delaney, and Ken Kelley. 2017. Designing Experiments and Analyzing Data: A Model Comparison Perspective. Routledge.

Selker, Ravi, Jonathon Love, and Damian Dropmann. 2020. Jmv: The ’Jamovi’ Analyses. https://CRAN.R-project.org/package=jmv.

Wickham, Hadley. 2019. Tidyverse: Easily Install and Load the ’Tidyverse’. https://CRAN.R-project.org/package=tidyverse.

Previous
Next