21  One-Way ANOVA

Author
Affiliations

Ashlee Perez & Michaela Larson

Florida International University

Robert Stempel College of Public Health and Social Work

# install.packages("rstatix")
# install.packages("tidyverse")
library(rstatix)
library(tidyverse)

21.1 Introduction to one-way ANOVA

One-way analysis of variance (ANOVA) is an extension of a two-samples t-test for comparing means between three or more independent groups. A single factor variable is employed to categorize the data into several groups.

Hypothesis Testing

Null Hypothesis \((H_0)\) the means between groups are not statistically different (they ARE the same). Alternative Hypothesis \((H_a)\) the means between groups are statistically different (they ARE NOT the same).

21.2 Mathematical definition of one-way ANOVA

\[ Y_{ij} = \mu + \tau_{i} + \epsilon_{ij} \]

Where,

  • \(Y_{ij}\) represents the j-th observation (j = 1, 2, …, \(n_{i}\)) on the i-th treatment (i = 1, 2, …, k levels).
    • So, \(Y_{23}\) represents the third observation for the second factor level.
  • \(\mu\) is the common effect.
  • \(\tau_{i}\) represents the i-th treatment effect.
  • \(\epsilon_{ij}\) represents the random error present in the j-th observation on the i-th treatment.

21.3 Data Description

The PlantGrowth data set is already included in {base R} within the {datasets} package. The PlantGrowth data set includes results from an experiment to compare yield obtained under a control condition and two different treatment conditions. The measurements were obtained through the dried weight of each plant.

# Call the data set into the Global environment
data("PlantGrowth")

# Use the `glimpse()` or `head()` function to skim observations
# glimpse(PlantGrowth)
head(PlantGrowth)
  weight group
1   4.17  ctrl
2   5.58  ctrl
3   5.18  ctrl
4   6.11  ctrl
5   4.50  ctrl
6   4.61  ctrl
# Optional: You can use the `summary()` function to confirm that all variables
# are being read correctly. E.g. the `group` variable is displayed as counts
# for each level
summary(PlantGrowth)
     weight       group   
 Min.   :3.590   ctrl:10  
 1st Qu.:4.550   trt1:10  
 Median :5.155   trt2:10  
 Mean   :5.073            
 3rd Qu.:5.530            
 Max.   :6.310            
# Optional: You can use the `str()` function to view the factor levels and
# confirm the appropriate reference level for analysis
str(PlantGrowth)
'data.frame':   30 obs. of  2 variables:
 $ weight: num  4.17 5.58 5.18 6.11 4.5 4.61 5.17 4.53 5.33 5.14 ...
 $ group : Factor w/ 3 levels "ctrl","trt1",..: 1 1 1 1 1 1 1 1 1 1 ...
# R assigns reference level in alphabetical order. E.g. From our factor levels 
# (ctrl, trt1, trt2) - ctrl will be assigned as the reference level 
# automatically by R.
# Here, we see that `group` is a factor with 3 levels,
# with 1 corresponding to 1 (the first level).

# If you need to re-assign the reference level, you can `relevel()` your factor
# The first variable after `Levels:` is your new reference group.
relevel(PlantGrowth$group, ref = "ctrl")
 [1] ctrl ctrl ctrl ctrl ctrl ctrl ctrl ctrl ctrl ctrl trt1 trt1 trt1 trt1 trt1
[16] trt1 trt1 trt1 trt1 trt1 trt2 trt2 trt2 trt2 trt2 trt2 trt2 trt2 trt2 trt2
Levels: ctrl trt1 trt2

21.4 Assumptions of One-Way ANOVA

The assumptions of one-way ANOVA are as follows:

  • Assumption 1: All observations are independent and randomly selected from the population as defined by the factor variable.
  • Assumption 2: The data within each factor level are approximately normally distributed.
  • Assumption 3: The variance of the data of interest is similar across each factor level (aka: Homogeneity of variance).

21.5 Checking the Assumptions of the One-Way ANOVA

Assumption 2: The data within each factor level are approximately normally distributed.

To check this assumption, we can examine if the data are approximately normally distributed across groups with 2 plots, the Q-Q plot or histograms, or with the Shapiro-Wilk test.

First, we will look at the Q-Q plot:

# Check for missing values to ensure balanced data
colSums(is.na(PlantGrowth))
weight  group 
     0      0 
# No missing datapoints

# Normality assumption: Q-Q plot
qq_plot_plantgrowth <- ggplot(PlantGrowth) +
  aes(sample = weight) +
  facet_wrap(~ group) +
  stat_qq() +
  stat_qq_line()

qq_plot_plantgrowth

The weight variable seems to be approximately normally distributed across each of the three groups based on the Q-Q plots.

Next, we will look at histograms:

# Normality assumption: Histograms
histogram_plantgrowth <- ggplot(PlantGrowth) +
  aes(x = weight) +
  geom_histogram(binwidth = 0.5) +
  facet_wrap(~ group)

histogram_plantgrowth

Again, the weight variable appears to be approximately normally distributed across the groups.

Lastly, we can use the Shapiro-Wilk test to test if the data is approximately normally distributed. P-values greater than 0.05 indicate that the data is likely approximately normally distributed.

# Normality: Shapiro Wilks
shapiro_plantgrowth <- PlantGrowth %>%
  group_by(group) %>%
  summarise(
    statistic = shapiro.test(weight)$statistic,
    p.value = shapiro.test(weight)$p.value
  )

shapiro_plantgrowth
# A tibble: 3 × 3
  group statistic p.value
  <fct>     <dbl>   <dbl>
1 ctrl      0.957   0.747
2 trt1      0.930   0.452
3 trt2      0.941   0.564

The p-value for each of our groups is above 0.05, so we can assume that weight is approximately normally distributed within each group.

Assumption 3: Homogeneity of variance.

We can check this assumption with Levene’s test. A p-value greater than 0.05 indicates that the variance is similar across groups, and we therefore meet the requirements of this assumption.

# Homogeneity of Variance: Levene's test
levenes_plantgrowth <- levene_test(weight ~ group, data = PlantGrowth)
levenes_plantgrowth
# A tibble: 1 × 4
    df1   df2 statistic     p
  <int> <int>     <dbl> <dbl>
1     2    27      1.12 0.341

The p-value is 0.341, so we can therefore assume that our data meets the assumption of homogeneity of variance.

We can also check assumption 3 by visually examining a box plot of the outcome variable across groups:

# Variance assumption: Box plot for weight by group
box_plantgrowth <- ggplot(PlantGrowth) +
  aes(y = weight) +
  geom_boxplot() +
  facet_wrap(~ group)

box_plantgrowth

To compare the box plot visually, we take a look at the interquartile range between each three plots. All three have approximately similar size and length, which satisfies our assumption homogeneity of variance.

21.6 Code to Run One-Way ANOVA

# Include an outcome variable, `weight`, and predictor(s), `group`. as well as 
# which data set to pull variables from with `data = ` argument
anova_fit <- aov(weight ~ group, data = PlantGrowth)

# Call summary statistics from `anova_fit` object
summary(anova_fit)
            Df Sum Sq Mean Sq F value Pr(>F)  
group        2  3.766  1.8832   4.846 0.0159 *
Residuals   27 10.492  0.3886                 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

The summary includes the independent variable group being tested within the model. All variation that is not explained by group is considered residual variance.

  • The Df column tabulates the degrees of freedom for the independent variable, which is the number of levels in the variable minus 1. For example, group has 3 levels (3 - 1 = 2 degrees of freedom).
  • The Sum Sq column tabulates the sum of squares (total variation between group means and overall mean).
  • The Mean Sq column tabulates the mean of the sum of squares, which is calculated by dividing the sum of squares by the degrees of freedom for each parameter.
  • The F value column tabulates the test statistic from the F test, which is the mean square of each independent variable (only one in this case) by the mean square of the residuals.
  • The Pr(>F) column is the resulting p-value of the F statistic. Remember: the p-value shows how likely it is that the calculated F value would have occurred if the null hypothesis were true.

The p value of the fertilizer variable is low (p < 0.01), so it appears that the type of fertilizer used (group) has a real impact on the final crop yield (weight).

21.6.1 Post-Hoc Test for Pairwise Comparisons

To compare the group means directly, we can conduct a post-hoc test to see which group means are different from one another. One post-hoc test is Tukey’s Test.

# perform Tukey's Test for multiple comparisons
anova_post_hoc <- TukeyHSD(anova_fit, conf.level=.95)

anova_post_hoc
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = weight ~ group, data = PlantGrowth)

$group
            diff        lwr       upr     p adj
trt1-ctrl -0.371 -1.0622161 0.3202161 0.3908711
trt2-ctrl  0.494 -0.1972161 1.1852161 0.1979960
trt2-trt1  0.865  0.1737839 1.5562161 0.0120064

In the above output, we can see that:

  • trt1-ctrl: P-value is approximately 0.391 when comparing treatment 1 (trt1) and control (ctrl), which is greater than 0.05. This indicates there is not a statistically significant difference in mean between these groups. Their means are the SAME.
  • trt2-ctrl: P-value is approximately 0.198 when comparing treatment 2 (trt2) and control (ctrl), which is greater than 0.05. This indicates there is not a statistically significant difference in mean between these groups. Their means are the SAME.
  • trt2-trt1: P-value is 0.012 when comparing treatment 1 (trt1) and treatment 2 (trt2), which is less than 0.05. This indicates there is a statistically significant difference in mean between these groups. Their means are NOT the SAME.

21.6.2 Regression for Comparison

To compare the ANOVA results with those of a simple linear regression, we can run a regression model to examine if there are differences between the control group and the two treatment groups.

# Simple linear regression
lm_plantgrowth <- lm(weight ~ group, data = PlantGrowth)

summary(lm_plantgrowth)

Call:
lm(formula = weight ~ group, data = PlantGrowth)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.0710 -0.4180 -0.0060  0.2627  1.3690 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   5.0320     0.1971  25.527   <2e-16 ***
grouptrt1    -0.3710     0.2788  -1.331   0.1944    
grouptrt2     0.4940     0.2788   1.772   0.0877 .  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 0.6234 on 27 degrees of freedom
Multiple R-squared:  0.2641,    Adjusted R-squared:  0.2096 
F-statistic: 4.846 on 2 and 27 DF,  p-value: 0.01591

From the above output, we can see that:

  • The F-statistic is 4.846, which is the same F-statistic produced by the ANOVA.
  • The p-value of the model (0.01591) is the same as the p-value produced by the ANOVA.
  • The degrees of freedom for the ANOVA and linear model are also the same (2 and 27).
  • The Multiple R-squared value from the regression (0.2641) is related to the Sum of Squares for our factor and the Sum of Squares for the residual in the following way: \(R^{2} = \frac{SS_{factor}}{(SS_{factor} + SS_{residuals})}\).
  • The linear model confirms that there is no difference in the treatment groups compared to the control group since the p-values for the treatment groups are larger than 0.05 (0.194 and 0.088 for treatment 1 and treatment 2 versus control, respectively).

21.7 Brief Interpretation of the Output

The resulting p-value of the one-way ANOVA is 0.0159, which is less than our significance level of 0.05. Therefore we must reject our null hypothesis as the data supports that the mean weight between groups is statistically different. In other words, the mean weight(s) are NOT the same between group (ctrl, trt1, trt2).

The Tukey test results illustrate a true difference that only exists between treatment groups 1 and 2 (trt1 and trt2), and not between the control group and either of the treatment groups. This is confirmed by the output from the simple linear regression model.