BIO 202, Spring 2026, draft v1. R = h²·S. The Galton slope, applied to the breeders.
Truncation-select a Gaussian trait. Couple to inheritance via h². Watch h² collapse. Apply to Grant finches.
Trait ~ Normal(μ, σ). Only individuals above threshold reproduce. Selection differential S = mean of breeders − mean of population.
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̄.
set.seed(42)N <- 2000; z <- rnorm(N); f <- 0.2thr <- quantile(z, 1-f)S <- mean(z[z >= thr]) - mean(z)
Couple selection to inheritance with heritability h². The next generation's mean is shifted by R = h²·S.
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.
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))}
As selection runs, additive variance falls. Heritability falls. The response per generation shrinks. The trait asymptotes.
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.
# Track additive variance over time; new mutations refill it.# Realistic model needs a genetic architecture; here we approximate.
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.
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.
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²