Unit 09.04: A separate slope per group
An interaction says the effect of one variable depends on another. It is powerful, easy to abuse, and should be pre-specified.
a * b fits a separate slope per group
An additive model forces one slope on every group. An interaction lets the slope differ, which is what you want when the same action pays off differently in different segments.
revenue ~ spend * channel expands to spend + channel + their interaction. The interaction coefficient is the *difference* in slopes, so the second group's slope is the base slope plus that coefficient.
The danger is that interactions are the most tempting thing to add after the main effect disappoints. Every additional interaction is another comparison, and finding one that reaches significance is easy. Pre-specify them.
This block fits both models to data where two channels genuinely differ.
suppressPackageStartupMessages(library(broom))
set.seed(605)
n <- 300
d <- data.frame(spend = runif(n, 0, 100),
channel = factor(rep(c("email", "social"), each = 150)))
# Email returns 3 per unit spent; social returns only 1.
slope <- ifelse(d$channel == "email", 3, 1)
d$revenue <- 20 + slope * d$spend + rnorm(n, 0, 25)
additive <- lm(revenue ~ spend + channel, data = d)
inter <- lm(revenue ~ spend * channel, data = d)
cat("Additive model (one slope for both channels):\n")
print(tidy(additive)[, c("term", "estimate", "p.value")])
cat("\nInteraction model (a slope per channel):\n")
print(tidy(inter)[, c("term", "estimate", "p.value")])
co <- coef(inter)
cat("\nEmail slope :", round(co["spend"], 3), "\n")
cat("Social slope:", round(co["spend"] + co["spend:channelsocial"], 3), "\n\n")
cat("Residual SD:", round(summary(additive)$sigma, 2), "->",
round(summary(inter)$sigma, 2), "\n")
cat("`a * b` means a + b + their interaction. Use it when you expect the\n")
cat("effect of one variable to DEPEND on the other -- and say so in advance.\n")
The additive model reports one slope of 2.02 for both channels. The interaction model gives email 2.976 and social 1.015 — very close to the 3 and 1 built into the data, and utterly invisible in the additive fit. The residual SD falls from 41.09 to 27.94, because the additive model was forcing a compromise slope on two different populations.
The mistake this prevents
The mistake is adding interactions after the main effect fails and reporting the one that works. That is subgroup fishing wearing a regression's clothes.
Takeaway
Pre-specify interactions when you have a substantive reason to expect one. Report the group-specific slopes rather than the raw interaction coefficient, and treat a post-hoc interaction as a hypothesis for the next study.
