Activity 10 — T-Tests II: Running, Reporting & Extension
Running Welch’s t-test, reading the output, and writing it up
Hands-on companion to T-Tests II: run a Welch’s two-sample t-test in R, decode the output, make a decision, and write up the results.
In-class Activity 10: Running & Reporting the Test
Recap from Activity 09 (T-Tests I)
- Stated H₀ and Hₐ formally (two-tailed, α = 0.05)
- Checked normality with a histogram and Shapiro-Wilk
- Checked variance with Levene’s test
- Decided: proceed with Welch’s t-test (
var.equal = FALSE)
Today’s Objectives
- Run a Welch’s two-sample t-test (
var.equal = FALSE, two-tailed) - Read and decode every line of the
t.test()output - Make a formal statistical decision and state a conclusion
- Write a results sentence in proper scientific format
How this activity works
You keep building the script from Activity 09 — add today’s code to the bottom of
scripts/09_t_tests_1.R, or startscripts/10_t_tests_2.Rand reload the libraries and data at its top. Either way, you turn the script in.
- Every line you run goes in that script — not the Console, not this page. Type it, don’t paste it.
- Start every code chunk with a short
#comment saying what it does.- Code marked ▶ Run this is typed in exactly as shown. Code marked ✏️ Your turn is a change you make and run.
- The Extension at the end is done out of class (~30–40 min) and turned in with the script.
🔮 Predict before you run
Before you run
t.test(), write down a guess for the p-value — above or below 0.05? Then run it and see how close you were.
🧩 Chunk 1 — Run & interpret (after lecture Chunk 1)
Parts 1–3: run the test, decode the output, and decide.
Part 1 · Load libraries and data, and recap assumptions
Same leaf file as Activity 09 — it should already be in your project’s data/ folder. If not: 2026_09_03_data_sci_leaf_area.xlsx → put it in data/.
▶ Run this at the top of your script:
# ---- Libraries -----------------------------------------
library(readxl) # read Excel files
library(tidyverse) # dplyr + ggplot2
library(janitor) # clean_names()
library(car) # Levene's test for variance# ---- Load data and re-run last lecture's checks --------
leaf_df <- read_excel("data/2026_09_03_data_sci_leaf_area.xlsx") %>%
clean_names()
recap_df <- leaf_df %>%
group_by(shade) %>%
summarize(
n = sum(!is.na(mass_g)),
mean_mass = round(mean(mass_g, na.rm = TRUE), 3),
sd_mass = round(sd(mass_g, na.rm = TRUE), 3),
se_mass = round(sd_mass / sqrt(n), 3)
)
recap_df✏️ Your turn: From Activity 09, what was your decision about normality and variance? Were you clear to proceed with Welch’s?
Normality decision:
Variance (Levene's) decision:
Proceed with Welch's? Y / N
Part 2 · Run the Welch’s t-test
🔮 Predict first: Write down a guess for the p-value now — above or below 0.05? Then run
t.test()and see how close you were.
▶ Run this:
# Welch's two-sample t-test --------------------------
leaf_ttest_model <- t.test(
mass_g ~ shade, # response ~ grouping variable
data = leaf_df,
var.equal = FALSE, # Welch's — no pooled variance
alternative = "two.sided" # two-tailed test
)
leaf_ttest_model✏️ Your turn: Copy the full output below:
Paste or write the t.test() output here:
Part 3 · Decode the output and decide
▶ Run this to extract individual values:
# Pull specific values from the model object ---------
cat("t-statistic:", round(leaf_ttest_model$statistic, 3), "\n")
cat("df (Welch): ", round(leaf_ttest_model$parameter, 2), "\n")
cat("p-value: ", signif(leaf_ttest_model$p.value, 3), "\n")
cat("95% CI: ", round(leaf_ttest_model$conf.int[1], 3),
"to", round(leaf_ttest_model$conf.int[2], 3), "g\n")
cat("Mean shady: ", round(leaf_ttest_model$estimate[1], 3), "g\n")
cat("Mean sunny: ", round(leaf_ttest_model$estimate[2], 3), "g\n")✏️ Your turn: Match each piece of output to its meaning:
t-statistic = _____
→ This is large/small (circle one) because the difference in means
is large/small relative to the variability (circle one).
df = _____
→ This is a non-integer. Why? (hint: Welch-Satterthwaite equation)
p-value = _____
→ In plain language, this means: if H₀ were true, the probability
of seeing a t-statistic this extreme just by chance is _____.
95% CI = _____ to _____ g
→ This CI is for the ________________ (the true difference in means).
It does / does not include zero (circle one).
What does it mean when the CI includes zero?
✏️ Your turn: State your decision and conclusion. Use the formal language of hypothesis testing.
Our p-value:
Our α:
Decision (circle one): REJECT H₀ / FAIL TO REJECT H₀
In one sentence, what does this mean biologically?
💡 Key idea: We never say “H₀ is true” or “H₀ is false.” We say “we reject H₀” (evidence was strong enough) or “we fail to reject H₀” (evidence was not strong enough). Failing to reject H₀ is not proof there is no difference — only that this sample did not show one.
🧩 Chunk 2 — Visualize & report (after lecture Chunk 2)
Parts 4–5: build the figure with the statistics embedded, then write the results sentence.
Part 4 · Visualize the result
Boxplot with test statistics in the subtitle
▶ Run this:
# Boxplot with t and p embedded in subtitle ----------
leaf_box_10_plot <- leaf_df %>%
ggplot(aes(x = shade, y = mass_g, fill = shade)) +
geom_boxplot(alpha = 0.5, outlier.shape = NA) +
geom_point(
position = position_jitter(width = 0.15, seed = 42),
alpha = 0.6, size = 2.5
) +
labs(
title = "Leaf Mass by Shade",
subtitle = paste0("Welch's t-test: t = ",
round(leaf_ttest_model$statistic, 2),
", p = ",
signif(leaf_ttest_model$p.value, 2)),
x = "Shade",
y = "Leaf Mass (g)"
) +
theme_minimal() +
theme(legend.position = "none")
leaf_box_10_plot✏️ Your turn: The subtitle line uses paste0() to build the label from the model object. Why is this better than typing the numbers into subtitle = "..." yourself?
Your answer:
Save the plot
▶ Run this:
ggsave("figures/leaf_mass_boxplot_ttest.png",
plot = leaf_box_10_plot,
width = 5,
height = 5,
units = "in",
dpi = 300)Part 5 · Write a scientific results sentence
✏️ Your turn: Write a complete results sentence as you would in a lab report or paper. Report what the test actually showed — whether or not it was significant. Include:
- The test name, t-statistic, df, and p-value in parentheses
- Mean ± SE for both groups with units
- If significant: which group was larger, with the word “significantly”
- If not significant: say the means “did not differ significantly”
Use whichever template fits your result:
"[Group] leaves were significantly [heavier / lighter] than [group] leaves
(Welch's two-sample t-test: t(___) = ___, p = ___).
Mean ± SE: [side 1] = ___ ± ___ g, [side 2] = ___ ± ___ g."
— or —
"Mean leaf mass did not differ significantly between shady and sunny sides
(Welch's two-sample t-test: t(___) = ___, p = ___).
Mean ± SE: shady = ___ ± ___ g, sunny = ___ ± ___ g."
Write your sentence here:
Your results sentence:
💡 Key idea: Never write
p = 0.000. Writep < 0.001instead. A p-value is never exactly zero — it is just too small to display.
Part 6 · Review and checkpoint
At this point you should be able to:
✏️ Your turn: Run your entire script from top to bottom with Ctrl/Cmd + Shift + Enter (Source). Does it run without errors?
Ran cleanly? Y / N
If not, what error appeared:
Extension — out of class (~30–40 min)
Add this to the bottom of your script and turn it in. Put your written answers in # comments under the code they go with. In class we ran a two-tailed test on leaf mass. The extension changes two things: a new variable you choose and a one-tailed (directional) hypothesis — which behaves differently and is easy to misuse.
E1 · A directional test on a new variable (3 pts)
Pick one variable you did not test in class: petiole_mm or thickness_mm. Write down which you picked and, before running anything, a directional hypothesis — e.g. “shady leaves are larger”, i.e. Hₐ: μ_shady > μ_sunny.
# Replace ___ with "petiole_mm" or "thickness_mm".
# alternative is "greater"/"less" for the FIRST group alphabetically
# ("shady" comes before "sunny"), so "shady larger" = "greater".
one_tail_model <- t.test(
___ ~ shade,
data = leaf_df,
var.equal = FALSE,
alternative = "greater" # <- directional; change if your Ha points the other way
)
one_tail_model
# For comparison, the two-tailed version of the SAME test
t.test(___ ~ shade, data = leaf_df, var.equal = FALSE)$p.valueRecord (in comments):
Variable chosen:
Directional Ha (in symbols):
One-tailed p-value:
Two-tailed p-value:
Ratio (two-tailed / one-tailed) ≈
Decision at alpha = 0.05:
E2 · Predict, then check (3 pts)
Before running E1, in comments:
- Predict the relationship between the one-tailed and two-tailed p-values for the same data. Which is smaller, and roughly by how much?
- Predict whether your chosen variable will differ significantly between sides, and why.
Then run E1 and write your actual one- and two-tailed p-values and whether your predictions held.
E3 · Explain it, with YOUR numbers (3 pts)
Using your real output:
- Explain why the one-tailed p-value is (about) half the two-tailed one — in terms of where the rejection region sits on the t distribution.
- A one-tailed test is only legitimate if the direction was chosen before seeing the data. Explain, in plain language, what goes wrong if a researcher runs a two-tailed test, sees p = 0.08, and then switches to the one-tailed test that “works”.
- If your one-tailed result is significant but the two-tailed result is not, which would you report in a paper, and why?
Optional, no points: rerun E1 with
conf.level = 0.99and note how the CI changes — and why a one-tailedt.test()reports a one-sided CI (-InforInfat one end).
What your figures/ folder should contain
tree_project/
├── data/
│ └── 2026_09_03_data_sci_leaf_area.xlsx
├── figures/
│ ├── leaf_mass_mean_se.png <- from Activity 03 (GGPlot I)
│ └── leaf_mass_boxplot_ttest.png <- from this activity
└── scripts/
└── 10_t_tests_2.R <- your script (turn this in)
Getting unstuck
- Read the error message out loud. R usually names the line and the problem.
t.test()formula: the grouping variable goes on the right of~and must have exactly two levels. Check withunique(leaf_df$shade).- Cheat sheets — https://posit.co/resources/cheatsheets/
- Bring the exact error (copy-paste it) to class, Canvas, or office hours.
💡 Key idea: Nothing in the five-step sequence — hypotheses → normality → variance → test → report — was specific to leaf mass or to comparing exactly two sides. Swap in three species instead of two, and it’s the same sequence you’ll run for ANOVA.
End of the T-Tests II activity. Next: regression.