Profile Plots in Two-Way ANOVA

Introduction

  • Recall that ANOVA allows us to compare the means of three or more groups.

  • In one-way ANOVA, we are only considering one factor (grouping variable).

  • In this module, we discuss two-way ANOVA, which allows us to consider a second factor (grouping variable).

  • In this lecture, we discuss profile plots, a way to visualize treatment group means.

R Setup

library(tidyverse)
library(ssstats)
exam_scores <- read_csv("https://raw.githubusercontent.com/samanthaseals/SDSI/refs/heads/main/files/data/lectures/5-1-exam_scores.csv")
fatigue_scores <- read_csv("https://raw.githubusercontent.com/samanthaseals/SDSI/refs/heads/main/files/data/lectures/5-2-fatigue_scores.csv")

Two-Way ANOVA: Profile Plots

  • We can construct profile plots to display treatment group means.

    • y-axis: always the average outcome

    • x-axis: either factor A or B

    • “lines” on the plot: the factor that was not selected for the x-axis

  • Note that this is just a graph of the means!

    • It’s valid to construct a profile plot regardless of significance.

Two-Way ANOVA: Profile Plots (R)

  • We will use the profile_plot() function from library(ssstats) to construct basic profile plots.
dataset_name |> profile_plot(continuous = continuous_variable,
                              xaxis = variable_on_x,
                              lines = variable_for_lines)

Example 1

  • Recall the two-way ANOVA results for the fatigue_scores data,

  • Does the effect of shift on fatigue depend on which unit an officer works in?

fatigue_scores |> anovas(outcome = fatigue_score,
                         A = shift,
                         B = unit)
Two-way ANOVA (with interaction)

Source       df          SS        MS       F  p-value 
───────────────────────────────────────────────── 
shift         1    998.2845  998.2845  10.274    0.002 
unit          2     51.7080   25.8540   0.266    0.767 
shift:unit    2    729.3173  364.6587   3.753    0.025 
Residuals   174  16906.4077   97.1633                  
───────────────────────────────────────────────── 


Hypotheses (shift:unit):
H₀: There is no interaction between shift and unit
H₁: There is an interaction between shift and unit
Test statistic: F(2, 174) = 3.753
p-value: 0.025
Conclusion: Reject the null hypothesis (p = 0.025 < α = 0.050)

Example 1

  • Let’s remind ourselves what’s “in” the variables:
fatigue_scores |> n_pct(shift, unit)
shift Desk K9 Patrol
Day 30 (50.0%) 30 (50.0%) 30 (50.0%)
Night 30 (50.0%) 30 (50.0%) 30 (50.0%)
  • Neither of the factors has a natural “order”

  • Let’s have unit on the x-axis and define the lines by shift.

Example 1

  • Constructing the profile plot,
fatigue_scores |> profile_plot(outcome = fatigue_score,
                              xaxis = unit,
                              lines = shift)

Example 2

  • Recall the two-way ANOVA results for the exam_scores data,

  • Does the effect of training method depend on experience level?

exam_scores |> anovas(outcome = exam_score,
                      A = training_method,
                      B = experience_level,
                      interaction = TRUE)
Two-way ANOVA (with interaction)

Source                             df          SS        MS      F  p-value 
────────────────────────────────────────────────────────────────────── 
training_method                     2   1339.2191  669.6096  7.584  < 0.001 
experience_level                    1     88.9014   88.9014  1.007    0.317 
training_method:experience_level    2      4.8084    2.4042  0.027    0.973 
Residuals                         174  15362.8583   88.2923                 
────────────────────────────────────────────────────────────────────── 


Hypotheses (training_method:experience_level):
H₀: There is no interaction between training_method and experience_level
H₁: There is an interaction between training_method and experience_level
Test statistic: F(2, 174) = 0.027
p-value: 0.973
Conclusion: Fail to reject the null hypothesis (p = 0.973 ≥ α = 0.050)

Example 2

  • Recall the two-way ANOVA results for the exam_scores data,

  • Are there main effects of training method or experience level?

exam_scores |> anovas(outcome = exam_score,
                      A = training_method,
                      B = experience_level,
                      interaction = FALSE)
Two-way ANOVA (no interaction)

Source             df          SS        MS      F  p-value 
────────────────────────────────────────────────────── 
training_method     2   1339.2191  669.6096  7.669  < 0.001 
experience_level    1     88.9014   88.9014  1.018    0.314 
Residuals         176  15367.6668   87.3163                 
────────────────────────────────────────────────────── 


Hypotheses (training_method):
H₀: All means across levels of training_method are equal
H₁: At least one mean across levels of training_method differs
Test statistic: F(2, 176) = 7.669
p-value: < 0.001
Conclusion: Reject the null hypothesis (p = < 0.001 < α = 0.050)

Hypotheses (experience_level):
H₀: All means across levels of experience_level are equal
H₁: At least one mean across levels of experience_level differs
Test statistic: F(1, 176) = 1.018
p-value: 0.314
Conclusion: Fail to reject the null hypothesis (p = 0.314 ≥ α = 0.050)

Example 2

  • Let’s remind ourselves what’s “in” the variables:
exam_scores |> n_pct(training_method, experience_level)
training_method Rookie Veteran
Enhanced 30 (33.3%) 30 (33.3%)
Peer-Led 30 (33.3%) 30 (33.3%)
Standard 30 (33.3%) 30 (33.3%)
  • Neither of the factors has a natural “order”

  • Let’s have training_method on the x-axis and define the lines by experience_level.

Example 2

  • Constructing the profile plot,
exam_scores |> profile_plot(outcome = exam_score,
                            xaxis = training_method,
                            lines = experience_level)

Wrap Up

  • In this lecture, we have covered profile plots in two-way ANOVA.

  • This lecture concludes the two-way ANOVA module.

  • Next module: categorical analysis.