Activity: Analysis of Variance
Single-factor ANOVA
Worksheet: One-Way ANOVA
π₯ Crab data π₯ Tools script (.R) π₯ Script skeleton (.R)
The lectureβs dataset: 84 fiddler crabs, 21 in each of four groups, with body temperature above ambient measured in the field. Does the maleβs oversized major claw act as a heat radiator?
intact maleβ the controlmale major removedβ the big claw taken offmale minor removedβ a small claw taken off, the procedural controlfemaleβ never had a major claw
If the claw sheds heat, removing it should make males hotter.
Part 1 Β· Setup and the data
βΆ Run this:
# ββ Part 1.1 Β· Setup and the data βββββββββββββββββββββββββββββββββββββββ
library(tidyverse)
library(car)
source("themes_functions/r_themes_and_functions.R")
crab_df <- read_csv("data/fiddler_crabs.csv") %>%
mutate(crab_type = factor(crab_type))
count(crab_df, crab_type)βΆ Run this β look at the data before you test it:
# ββ Part 1.2 Β· Setup and the data βββββββββββββββββββββββββββββββββββββββ
ggplot(crab_df, aes(crab_type, body_temp_c)) +
geom_boxplot() +
geom_jitter(width = 0.15, alpha = 0.5)βοΈ Your turn: Which group looks warmest, and does the picture match the radiator prediction?
____________________________________________________________
Part 2 Β· Build the sums of squares
βΆ Run this:
# ββ Part 2.1 Β· Build the sums of squares ββββββββββββββββββββββββββββββββ
grand_mean <- mean(crab_df$body_temp_c)
crab_parts <- crab_df %>%
group_by(crab_type) %>%
mutate(group_mean = mean(body_temp_c)) %>%
ungroup()
ss_total <- sum((crab_parts$body_temp_c - grand_mean)^2)
ss_among <- sum((crab_parts$group_mean - grand_mean)^2)
ss_within <- sum((crab_parts$body_temp_c - crab_parts$group_mean)^2)
c(total = ss_total, among = ss_among, within = ss_within)
ss_among + ss_withinβοΈ Your turn: Does the partition add up, and what fraction does the grouping explain?
ss_among + ss_within = __________ ss_total = __________
ss_among / ss_total = __________
Part 3 Β· The ANOVA
βΆ Run this:
# ββ Part 3.1 Β· The ANOVA ββββββββββββββββββββββββββββββββββββββββββββββββ
crab_model <- lm(body_temp_c ~ crab_type, data = crab_df)
anova(crab_model)
summary(crab_model)$r.squaredβοΈ Your turn: Match the table to what you computed in Part 2.
Sum Sq, crab_type = __________ Sum Sq, Residuals = __________
Df = ______ and ______ F = __________ p = __________
R squared = __________ (compare it with ss_among / ss_total)
βοΈ Your turn: Write down exactly what this p-value licenses you to say β and one thing it does not.
It says: ____________________________________________________
It does not say: ____________________________________________
Part 4 Β· Check the assumptions
βΆ Run this:
# ββ Part 4.1 Β· Check the assumptions ββββββββββββββββββββββββββββββββββββ
par(mfrow = c(2, 2))
plot(crab_model)
par(mfrow = c(1, 1))βΆ Run this β the two formal tests:
# ββ Part 4.2 Β· Check the assumptions ββββββββββββββββββββββββββββββββββββ
shapiro.test(residuals(crab_model))
leveneTest(body_temp_c ~ crab_type, data = crab_df)βοΈ Your turn: Both tests have a null hypothesis you want to keep. Fill in.
Shapiro H0 = ________________ p = __________ pass? ______
Levene H0 = ________________ p = __________ pass? ______
βοΈ Your turn: The third assumption is independence. Why can no plot or test on this slide check it?
____________________________________________________________
Part 5 Β· Set the reference level
βΆ Run this β see the order R chose for you:
# ββ Part 5.1 Β· Set the reference level ββββββββββββββββββββββββββββββββββ
levels(crab_df$crab_type)
summary(crab_model)$coefficientsβοΈ Your turn: Which level is the reference, why did R pick it, and what is each coefficient comparing?
Reference: __________ Why: _______________________________
Each coefficient is "degrees hotter than a ______________"
βΆ Run this β put the control first and refit:
# ββ Part 5.2 Β· Set the reference level ββββββββββββββββββββββββββββββββββ
crab_df <- crab_df %>%
mutate(crab_type = fct_relevel(crab_type, "intact male"))
crab_model <- lm(body_temp_c ~ crab_type, data = crab_df)
summary(crab_model)$coefficients
anova(crab_model)βοΈ Your turn: Compare the two coefficient tables, and the two ANOVA tables.
What changed: _______________________________________________
What did not change: ________________________________________
Why does the F-test not care which level is first?
____________________________________________________________
Part 6 Β· Which groups actually differ?
βΆ Run this:
# ββ Part 6.1 Β· Which groups actually differ? ββββββββββββββββββββββββββββ
TukeyHSD(aov(crab_model))βοΈ Your turn: Fill in the adjusted p-values for the three comparisons with the control.
female - intact male = __________
male major removed - intact male = __________
male minor removed - intact male = __________
βοΈ Your turn: The radiator hypothesis predicts that removing the major claw makes males hotter. Does the Tukey output support it? Answer in one sentence, using the number.
____________________________________________________________
βοΈ Your turn: Females are significantly hotter than every male group. Why does that not rescue the hypothesis?
____________________________________________________________
Part 7 Β· Report it
βοΈ Your turn: Write the results sentence you would put in a paper. It needs the test, F with both degrees of freedom, the p-value, RΒ², and the post-hoc method β including the comparison that was not significant.
____________________________________________________________
____________________________________________________________
____________________________________________________________
Part 8 Β· The figure you hand in
βΆ Run this:
# ββ Part 8.1 Β· The figure you hand in βββββββββββββββββββββββββββββββββββ
crab_summary <- crab_df %>%
group_by(crab_type) %>%
reframe(summary_stats(body_temp_c))
final_plot <- ggplot(crab_summary, aes(crab_type, mean)) +
geom_col(fill = "grey70", width = 0.6) +
geom_errorbar(aes(ymin = mean - se, ymax = mean + se), width = 0.15) +
labs(
title = "Female fiddler crabs run warmer than males",
subtitle = "Mean Β± 1 SE; removing the major claw did not raise male temperature",
x = "Crab type",
y = "Body temperature above ambient (C)"
) +
theme_regular(base_size = 12)
final_plot
ggsave(
"figures/crab_anova.pdf",
plot = final_plot,
width = 7,
height = 4.5,
units = "in"
)βοΈ Your turn: Open the PDF and check the bars run in the order you releveled to, not alphabetically.
Review and checkpoint
At this point you can:
π€ What to turn in
12_analysis_of_variance.Rfigures/crab_anova.pdf- This worksheet, with your written answers
Homework
Homework 7 β One-Way ANOVA: A Dose Series R Puts in the Wrong Order
Thirty-two Daphnia across three densities of toxic cyanobacteria. The crab worksheet again, in the same order, with two traps: the design is unbalanced, and the group labels (low, med, high) sort alphabetically into nonsense unless you set the factor levels yourself. There is also a real question about whether a dose series should be a factor at all.
Data: daphnia_resistance.csv β Whitlock & Schluter, Chapter 15, problem 17.