BIO 202, Spring 2026 — draft v1. Build the bell from coin flips. Discover that the mean is the best constant prediction when you have no other information. Meet the formula y ~ Normal(μ, σ) at the end and see that it is just what you have been doing the whole time.
When you do not know the answer, what is your best single guess, and how wrong will you typically be? Build the answer four ways: coins, simulated heights, a head-to-head between two predictors, and finally a real dataset.
Why coins and heights, not finches? The machine you build here — predict, measure the miss, name the spread — is the exact machine you will later point at finch beaks (Lesson 15), drifting alleles (Lesson 10), and species on a tree (Lesson 19). Unit 1 installs the machine on data you already have intuition for, so that the biology is the only new thing in the room when it arrives. The math is the same; only the data changes.
Pick a number. Flip 20 coins. See how close you got. Do it three times.
Pick how many heads you expect, on the right. Then click Flip Coin until you have flipped 20. Three rounds; the running tally below tracks how close you were each time.
A guess of 10 counts as ✓ only when 10 heads actually come up. That happens about 1 round in 6. Watch what's happening to your guesses themselves across the three rounds even when individual rounds come up ✗.
How many heads do you expect to see in 20 single coin flips?
set.seed(42)flips <- rbinom(20, size = 1, prob = 0.5)sum(flips) # count of heads
How far off each round's prediction was from the actual heads count.
| Round | You predicted | Heads observed | Off by |
|---|
Average error across 3 rounds: —
That last column — how far off each prediction was — is your error. Here the miss is sampling scatter: a finite batch of 20 flips lands off the long-run 50/50 by chance. Flip more coins per round and this scatter shrinks — it is a property of the sample size, not of you.
A good predictor doesn't hit zero on every single try (the sampling scatter still bites). What it does is land with an average error near zero — too high about as often as too low. Stage B turns this into a running tracker — but watch for a second, different kind of miss there, one that does not shrink no matter how much data you collect.
Real human heights. Get the average error low across 30 or more draws to move on.
Pick a single guess (in centimeters) for the height of a random adult. Click Draw to pull one. Repeat. If your average error across 30 draws ends up low — close enough to zero — you move on. If not, the page resets.
# 30 random adult heights from real data.nh <- read.csv("data/clean/nhanes_adults.csv")set.seed(7)truths <- sample(nh$Height, 30)guess <- ___ # type a value; aim for an average error near zeromean(guess - truths)
Two numbers behind everything you have done so far.
Click Draw one adult. Each click pulls one real NHANES height and adds its distance from the population mean to the second plot.
In Stage B you found the height that made your average error fall toward zero. Pick the description of that number that fits what it just did for you:
Top: the whole adult population. The solid red line is μ — the same number your Stage B average error settled around. The shaded band is ± σ — a typical distance any single adult sits from μ.
Bottom: the miss for each draw (truth − μ) — the individual spread, or residual once a model is in play. After enough draws its distribution settles to width σ, centered at zero. Unlike Stage A's sampling scatter, this spread does not shrink as you draw more people — it is how different adults are from one another, a fixed property of the population. Keep the two misses apart: sampling scatter shrinks with n (this is what drift will be, in Lesson 10) and individual spread stays at σ (this is the residual the rest of the course subtracts, starting in Lesson 3).
yi ~ Normal(μ, σ)
nh <- read.csv("data/clean/nhanes_adults.csv")y <- nh$Heightmean(y); sd(y) # μ and σ from real datahist(y, breaks = 40, freq = FALSE, col = "gray85", border = "white")abline(v = mean(y), col = "#b23a48", lwd = 2)abline(v = mean(y) + c(-1, 1) * sd(y), col = "#b23a48", lty = 3)
Open the downloaded .R and change nh$Height to nh$Weight. Compute μ and σ on weights. Compute the median as well. Which one — mean or median — is closer to "typical weight"? Plot both as vertical lines on the histogram.
NHANES adults are roughly half men and half women. Run the same μ-as-best-constant machine within each group. You get two μs and two σs instead of one.
Notice: the between-group difference (men's μ − women's μ) is a few times smaller than the within-group spread (σ inside either group).
Most of the variation in adult height is within men or within women — not between the two groups. The same machine, told to operate inside two groups, gives you a number for each kind of variation.
Lesson 6 returns to this — every two-group test is asking whether the between-group difference is bigger than the within-group spread would predict by chance.