When you used one number to predict human size, you were wrong by some amount. Every model is going to be wrong. Any feature you measure, outside of extremely controlled physics experiments, is influenced by a very large number of other factors. The goal is to find the subset of factors that explains a large enough fraction of the data to produce predictions useful for your purpose — and purposes differ, so what counts as useful differs too.
When we included biological sex we had two numbers, and that did better than one. By the end of Lesson 2 we had two numbers again but in a different way: a starting point and a rate, across two axes — a predictor and a response. A common trap is to treat a model you know is wrong and incomplete as though it were nevertheless perfect.
Here you predict body mass from height: taller people are on average heavier, shorter people lighter. The number in the corner is R², which is roughly how reliably height predicts weight — how useful the relationship is. You are going to find ten different lines whose R² are all about the same. For your sixty adults, anything from — to — counts, and with only 60 people the difference between those two is nothing — it is sampling error. So every one of those ten lines is functionally the same answer.
nh <- read.csv("data/clean/nhanes_adults.csv")set.seed(404)d <- nh[sample(nrow(nh), 60), ]steps <- (d$Height - 170) / 5base <- 70.0extra <- 0.0guess <- base + extra * steps1 - sum((d$Weight - guess)^2) / sum((d$Weight - mean(d$Weight))^2)# every pair on this grid that gets within 0.05 of the bestg <- expand.grid(base = seq(55, 115, 0.5), extra = seq(0, 12, 0.1))nrow(g) # out of this many
In the last part you had 60 adults and found ten lines that were all functionally equivalent. Here you will see how the spread of functionally equivalent lines varies with sample size.
Take samples of adults at different sizes and watch the spread of the lines that come back. How many different rates and starting points can produce the same functional answer? The range of consistent lines is not a property of the method. It is a property of how much you measured.
nh <- read.csv("data/clean/nhanes_adults.csv")n <- 40paces <- replicate(200, { d <- nh[sample(nrow(nh), n), ] coef(lm(Weight ~ I((Height - 170)/5), data = d))[2]})diff(quantile(paces, c(.025, .975)))sd(paces) # halves when n goes up four-fold
You have already analysed the Lord of the Rings data. Getting that data means actually matching the quotes to the film: sitting down with the book and the film, looking for a particular quote, and noting the minute it is spoken.
So assume you watch all three films through once, catching one quote from each book, and write down where it lands. Then you watch them again and catch a second one. Then a third. Each viewing gives you one more point per film — and every time, we can ask whether the pace of one film is yet distinguishable from the pace of another, given how uncertain each line still is.
q <- read.csv("data/clean/lotr_quotes.csv")k <- 3 # quotes noted per film so farnoted <- do.call(rbind, lapply(split(q, q$film), function(d) head(d[sample(nrow(d)), ], k)))# every pace still consistent with what you have notedcloud <- sapply(split(noted, noted$film), function(d) replicate(2000, coef(lm(page ~ minute, data = d[sample(nrow(d), nrow(d), replace = TRUE), ]))[2]))apply(cloud, 2, quantile, c(.025, .975))