Skip to course content
Free R statistics course

Statistical Data Analytics with R

Unit 09.05: Look for pattern, not for size

R-squared cannot tell you the model is the wrong shape. The residuals can, and a badly wrong model often has the higher R-squared.

Look for pattern, not for size

Residuals from a correctly specified model should scatter around zero with no systematic relationship to the fitted values. A pattern in them is the model telling you something is missing.

A straight line fitted to a curved relationship produces the classic signature: too high at the extremes and too low in the middle, or the reverse. The mean residual within thirds of the fitted range makes this visible as a sign change.

plot(model) draws the four standard diagnostics — residuals against fitted for shape, Q-Q for tail behaviour, scale-location for constant spread, and leverage for influential points.

This block fits a line to correctly linear data and to genuinely curved data.

set.seed(606)
x <- runif(150, 1, 20)

# Model 1: correctly specified. Model 2: the truth is curved.
y_ok    <- 5 + 2 * x + rnorm(150, 0, 4)
y_curve <- 5 + 2 * x + 0.35 * x^2 + rnorm(150, 0, 4)

# Split the fitted values into thirds and look at the MEAN residual in each.
# A correct model scatters around zero everywhere. A line fitted to a curve
# is too high in the middle and too low at both ends -- a - + - pattern.
for (nm in c("y_ok", "y_curve")) {
  m <- lm(get(nm) ~ x)
  r <- residuals(m); f <- fitted(m)
  third <- cut(f, quantile(f, c(0, 1/3, 2/3, 1)), include.lowest = TRUE)
  means <- tapply(r, third, mean)
  cat(sprintf("%-8s R2 %.3f   mean residual by fitted third: %+6.2f %+6.2f %+6.2f\n",
              nm, summary(m)$r.squared, means[1], means[2], means[3]))
}

cat("\nBoth models report a high R-squared -- the curved one is HIGHER.\n")
cat("Only the residuals show that it is the wrong shape: its mean residual\n")
cat("swings from positive to negative and back, while the correct model's\n")
cat("stays near zero across the whole fitted range.\n\n")
cat("plot(model) draws the four standard diagnostics: residuals vs fitted\n")
cat("(shape), Q-Q (tails), scale-location (constant spread), and leverage.\n")

The correct model has R-squared 0.875 and mean residuals of +0.36, −0.15, −0.21 across the fitted thirds — noise. The curved model has the *higher* R-squared at 0.967, and its mean residuals run +4.60, −9.83, +5.23: a systematic swing of nearly fifteen units. A reader comparing R-squared alone would pick the wrong model.

The mistake this prevents

The mistake is selecting a model on R-squared and never plotting the residuals. R-squared measures how much variance is explained, not whether the functional form is right.

Takeaway

Plot residuals against fitted values for every model you take seriously. Treat any systematic pattern as evidence of a missing term or a wrong shape, and never compare models on R-squared alone.