One equation for the whole thing. It adds nothing new — it names the quantity you have been computing since Lesson 3.
Each dot is an individual: trait z on the x-axis, fitness w (expected copies in the next generation) on the y-axis. Set how steeply fitness depends on the trait, and watch the mean trait move.
set.seed(42)z <- rnorm(600) # traitw <- pmax(0.01, 1 + 0.40*z) # fitness = line of w on zcov(w, z) / mean(w) # Δz̄ — the Price equation, one levelcoef(lm(w ~ z))[2] # the same covariance, as a slope (Lesson 3)
The same individuals, now sorted into groups. Each one pays for its own trait and receives according to its group's average. Two covariances appear at once, and they do not have to agree.
Zk <- tapply(z, grp, mean) # each group's mean traitWk <- tapply(w, grp, mean) # each group's mean fitness# between: the identity, with groups as the individualsbetween <- cov(Wk, Zk)# within: the identity inside each group, averagedwithin <- mean(tapply(seq_along(z), grp, function(i) cov(w[i], z[i])))(between + within) / mean(w)
Sweep how much the groups differ from each other, and watch the two terms trade places. Somewhere in that sweep the sum crosses zero.
Nothing new is introduced here. Stage C's two terms are computed at three places where a part and a whole are in competition. Only the biology changes, and only the dial changes with it.
Nothing is swapped in and nothing is added. The fitness rule has been the altruism one since Stage B — pay for your own trait, receive according to your group. Read the crossing off Stage C's sweep and put it beside the two dials.
w <- 1 - c*z + b*Zk[grp] # the fitness rule since Stage B# sweep how much the groups differ, find where (between + within) crosses 0r_star <- uniroot(function(r) dz(r, b, c), c(0.02, 0.95))$rootr_star * b # and compare it with c