Lesson 15 — The response to selection is a regression line in disguise

BIO 202, Spring 2026, draft v1. R = h²·S. The Galton slope, applied to the breeders.

What you'll do

Truncation-select a Gaussian trait. Couple to inheritance via h². Watch h² collapse. Apply to Grant finches.

A really counterintuitive thing: no matter how strong selection is on an additive trait, the population only moves by the additive variation in the population each generation. Selection sets direction. Additive variation sets the magnitude.— 202_lec19_01

A — Truncation selection on a Gaussian trait

Trait ~ Normal(μ, σ). Only individuals above threshold reproduce. Selection differential S = mean of breeders − mean of population.

Locked — confirm your name above to begin.

Scenario

Population of N = 2000 individuals with trait z ~ Normal(0, 1). Pick the top-fraction f as breeders. Compute the population mean z̄, the breeder mean z̄_b. S = z̄_b − z̄.

Trait distribution with selection threshold

N: 2000  |  fraction selected: 0.20  |  threshold:  |  S:

Prediction

  1. Q1. Selecting the top 20% on a Normal(0, 1) trait yields a selection differential S of approximately:
Try at least 4 fractions. 0/4 fractions

Controls

0.20
42

R code — truncation selection

set.seed(42)N <- 2000; z <- rnorm(N); f <- 0.2thr <- quantile(z, 1-f)S <- mean(z[z >= thr]) - mean(z)

B — R = h²·S — the next generation

Couple selection to inheritance with heritability h². The next generation's mean is shifted by R = h²·S.

Complete Stage A.

Scenario

Each parent contributes to offspring: offspring_z = h²·parent_z + Normal(0, σ_e). After truncation selection at fraction f, the breeders' mean is offset by S. The offspring mean is offset by h²·S.

Mean trait over generations

h²: 0.5  |  f selected: 0.20  |  S per gen:  |  total response (20 gen):

Prediction

  1. Q1. With h² = 0.5, S = 1.4 per generation, and 20 generations of selection, the expected total shift in trait mean is closest to:
Try at least 4 (h², f) combos. 0/4 combos

Controls

0.50
0.20
42

R code — breeder's equation

set.seed(42)N <- 2000; h2 <- 0.5; f <- 0.2; gens <- 20z <- rnorm(N); means <- mean(z)for (g in 1:gens) {  thr <- quantile(z, 1-f); br <- z[z >= thr]  z <- h2 * sample(br, N, replace=TRUE) + sqrt(1-h2) * rnorm(N)  means <- c(means, mean(z))}

C — Watch h² collapse

As selection runs, additive variance falls. Heritability falls. The response per generation shrinks. The trait asymptotes.

Complete Stage B.

Scenario

Long-run selection. Plot the mean trait AND additive variance over generations. h² is rebuilt by mutational input each generation; without it, h² collapses to 0 and selection stops working.

Mean trait and h² over generations

starting h²: 0.5  |  final h² (gen 100):  |  μ input: 0.02

Prediction

  1. Q1. With μ_input = 0 (no new mutations) and starting h² = 0.5, after 100 generations of truncation selection, h² will be:
Try at least 3 (μ, f) combos. 0/3 combos

Controls

0.50
0.20
0.020
42

R code — long-run h² collapse

# Track additive variance over time; new mutations refill it.# Realistic model needs a genetic architecture; here we approximate.

D — Grant finches, year by year

Beak depth in Geospiza fortis over 40 years. Year-by-year selection differential (drought vs wet El Niño). Compute observed response. Fit h² across years.

Complete Stage C.

Scenario

Grant finch beak depth from data/clean/grant_finches_40y.csv. Each year: mean beak depth, breeder mean, S. Next year: mean beak depth (= response R). h² is estimated as R/S for that pair.

Year-by-year R vs S (with 200-sample bootstrap of the slope)

years:  |  slope (= ĥ²):  |  95% bootstrap CI:  |  drought years (highlighted):

Prediction

  1. Q1. The slope of R on S across Grant finch years (heritability of beak depth) is approximately:
Refit at least 2 times. 0/2 refits

Controls

42

R code — Grant finch breeder's equation

finches <- read.csv("data/clean/grant_finches_40y.csv")# Per year: mean beak depth, mean breeder beak depth, next-year meanfit <- lm(R ~ 0 + S, data = year_pairs)coef(fit)   # slope = h²