Skip to content
Statistical RethinkingStatistical Rethinking

7.4 Interactions in design formulas

R formula syntax provides a compact way to specify interactions. This section reviews the standard design formula notation and shows how to translate it into a model definition.

7.4.1 R formula notation

R provides several ways to specify interactions in model formulas:

  • y ~ x + z: Main effects only (no interaction)
  • y ~ x * z: Main effects plus interaction (equivalent to x + z + x:z)
  • y ~ x:z: Interaction only (no main effects)
  • y ~ (x + z)^2: All pairwise interactions (same as x * z for two variables)
  • y ~ (x + z + w)^3: All interactions up to 3-way

y∼x∗z≡y∼x+z+x:zy \sim x * z \equiv y \sim x + z + x:z

# R formula notation for interactions
set.seed(42)
n <- 100
x <- runif(n, 0, 10)
z <- runif(n, 0, 10)
y <- 1 + 2 * x + 3 * z + 0.5 * x * z + rnorm(n, sd = 2)

# Different formula notations

m1 <- lm(y ~ x + z) # main effects only
m2 <- lm(y ~ x * z) # main effects + interaction
m3 <- lm(y ~ x + z + x:z) # explicit: same as m2
m4 <- lm(y ~ (x + z)^2) # same as m2

cat("Main effects only (x + z):\n")
cat(" Coefficients:", length(coef(m1)), "\n")

cat("\nWith interaction (x * z):\n")
cat(" Coefficients:", length(coef(m2)), "\n")
cat(" Names:", paste(names(coef(m2)), collapse = ", "), "\n")

cat("\nExplicit (x + z + x:z):\n")
cat(" Same as x * z?", identical(coef(m2), coef(m3)), "\n")

cat("\nFormula notation (x + z)^2:\n")
cat(" Same as x * z?", identical(coef(m2), coef(m4)), "\n")
Click Run to execute this code in your browser with WebR

7.4.2 Higher-order interactions

For three or more predictors, R's formula notation scales:

  • y ~ x * z * w: All main effects, all 2-way interactions, and the 3-way interaction
  • y ~ (x + z + w)^2: Main effects and all 2-way interactions (no 3-way)
  • y ~ x * z + x * w: Selected interactions only
# Higher order interactions
set.seed(42)
n <- 100
x <- runif(n, 0, 10)
z <- runif(n, 0, 10)
w <- runif(n, 0, 10)
y <- 1 + 2*x + 3*z + 1*w + 0.5*x*z + rnorm(n, sd = 2)

# All interactions (3-way)

m*full <- lm(y ~ x * z _ w)
cat("Full (x _ z _ w):", length(coef(m_full)), "coefficients\n")
cat(" ", paste(names(coef(m_full)), collapse = ", "), "\n")

# Up to 2-way interactions

m_2way <- lm(y ~ (x + z + w)^2)
cat("\n2-way only ((x+z+w)^2):", length(coef(m_2way)), "coefficients\n")
cat(" ", paste(names(coef(m_2way)), collapse = ", "), "\n")

# Selected interactions

m_sel <- lm(y ~ x * z + w)
cat("\nSelected (x*z + w):", length(coef(m_sel)), "coefficients\n")
cat(" ", paste(names(coef(m_sel)), collapse = ", "), "\n")
Click Run to execute this code in your browser with WebR

7.4.3 Translating to model notation

The R formula y ~ x * z translates to the model notation:

yi∼Normal(μi,σ)y_i \sim \text{Normal}(\mu_i, \sigma) μi=α+βxxi+βzzi+βxzxizi\mu_i = \alpha + \beta_x x_i + \beta_z z_i + \beta_{xz} x_i z_i

In the rethinking package, this would be:

y ~ dnorm(mu, sigma)
mu <- a + bx * x + bz * z + bxz * x * z
Rethinking

The formula is the interface, not the model. R's formula notation is a convenient interface for specifying models, but it is not the model itself. The model is the set of probability statements and deterministic equations. The formula is just a shorthand. When in doubt, write out the full model notation to make sure you understand what the formula implies. This is especially important for interactions — the * operator silently adds main effects, which can be surprising if you only wanted the interaction term (:).

Summary of Section 7.4

  • y ~ x * z includes main effects and interaction (equivalent to x + z + x:z).
  • y ~ x:z includes only the interaction (no main effects).
  • y ~ (x + z + w)^2 includes all 2-way interactions but no 3-way.
  • R formulas are a convenient interface, but the model notation is the specification.
  • When in doubt, write out the full model to verify what the formula implies.