Interaction Effects in Regression in R

When the effect of one predictor depends on another — add an interaction term with *, interpret it, and test whether the synergy is real against the additive model

Biostatistics

Model interaction effects in linear regression in R. Add an interaction term with the * operator, interpret the interaction coefficient (how one predictor’s effect changes with another), and test whether the interaction model beats the additive model with anova() and adjusted R². The hierarchical principle, worked on the marketing data.

Published

June 23, 2026

Modified

July 7, 2026

TipKey takeaways
  • An interaction effect means the effect of one predictor on the outcome depends on the value of another — they’re not independent (in marketing, a synergy).
  • Add an interaction in R with the * operator: lm(y ~ x1 * x2) fits the main effects and the x1:x2 interaction term.
  • The interaction coefficient is how much one predictor’s slope changes per one-unit increase in the other.
  • The hierarchical principle: if you keep an interaction, keep its main effects too — even if their own p-values aren’t significant.
  • Test whether the interaction is worth it by comparing the interaction model to the additive one with anova() and adjusted R².

Introduction

A standard multiple regression is additive: it assumes each predictor’s effect is the same regardless of the others. Often that’s wrong. Spending on facebook advertising may make youtube advertising more effective — an interaction (or synergy) effect.

The scenario: does the payoff of youtube advertising on sales depend on how much is also spent on facebook? An interaction term answers that — and tells you whether modelling the synergy actually improves the fit.

The data

We use the marketing dataset from datarium — advertising budgets and resulting sales for 200 campaigns:

data("marketing", package = "datarium")
head(marketing, 4)
  youtube facebook newspaper sales
1  276.12    45.36     83.04 26.52
2   53.40    47.16     54.12 12.48
3   20.64    55.08     83.16 11.16
4  181.80    49.56     70.20 22.20

The additive model (no interaction)

First the standard additive model — youtube and facebook, each with a fixed effect:

data("marketing", package = "datarium")

model_add <- lm(sales ~ youtube + facebook, data = marketing)
summary(model_add)

Call:
lm(formula = sales ~ youtube + facebook, data = marketing)

Residuals:
     Min       1Q   Median       3Q      Max 
-10.5572  -1.0502   0.2906   1.4049   3.3994 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  3.50532    0.35339   9.919   <2e-16 ***
youtube      0.04575    0.00139  32.909   <2e-16 ***
facebook     0.18799    0.00804  23.382   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 2.018 on 197 degrees of freedom
Multiple R-squared:  0.8972,    Adjusted R-squared:  0.8962 
F-statistic: 859.6 on 2 and 197 DF,  p-value: < 2.2e-16

This assumes the effect of youtube is the same at every facebook budget. Adjusted R² ≈ 0.896.

Add the interaction

Use the * operator — youtube * facebook expands to youtube + facebook + youtube:facebook (both main effects plus the interaction). (Write youtube:facebook if you ever want only the interaction term.)

data("marketing", package = "datarium")

model_int <- lm(sales ~ youtube * facebook, data = marketing)
summary(model_int)

Call:
lm(formula = sales ~ youtube * facebook, data = marketing)

Residuals:
    Min      1Q  Median      3Q     Max 
-7.6039 -0.4833  0.2197  0.7137  1.8295 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)      8.100e+00  2.974e-01  27.233   <2e-16 ***
youtube          1.910e-02  1.504e-03  12.699   <2e-16 ***
facebook         2.886e-02  8.905e-03   3.241   0.0014 ** 
youtube:facebook 9.054e-04  4.368e-05  20.727   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 1.132 on 196 degrees of freedom
Multiple R-squared:  0.9678,    Adjusted R-squared:  0.9673 
F-statistic:  1963 on 3 and 196 DF,  p-value: < 2.2e-16

Interpret the interaction

Every coefficient — including youtube:facebook — is significant, so there’s a real interaction. The fitted equation is:

sales = 8.10 + 0.0191·youtube + 0.0289·facebook + 0.00091·(youtube × facebook)

Read it by factoring out a predictor:

  • The effect of youtube is (0.0191 + 0.00091 × facebook) per unit. So youtube’s payoff grows with the facebook budget — at facebook = 0 a 1 k$ youtube bump adds ~19 sales units per 1000$; at facebook = 30 it adds ~19 + 0.9 × 30 ≈ 46.
  • Symmetrically, facebook’s effect is (0.0289 + 0.00091 × youtube) per unit.

That’s the synergy: the two channels amplify each other.

Warning

The hierarchical principle. If you keep an interaction term, keep its main effects in the model too — even if a main effect’s own p-value isn’t significant. An interaction without its main effects is almost always mis-specified and hard to interpret.

Is the interaction worth it?

Compare the interaction model to the additive one. The interaction model should have a higher adjusted R², and an anova() F-test tells you whether the improvement is significant:

data("marketing", package = "datarium")
model_add <- lm(sales ~ youtube + facebook, data = marketing)
model_int <- lm(sales ~ youtube * facebook, data = marketing)

c(additive = summary(model_add)$adj.r.squared,
  interaction = summary(model_int)$adj.r.squared)
   additive interaction 
  0.8961505   0.9672975 
anova(model_add, model_int)
Analysis of Variance Table

Model 1: sales ~ youtube + facebook
Model 2: sales ~ youtube * facebook
  Res.Df    RSS Df Sum of Sq      F    Pr(>F)    
1    197 801.96                                  
2    196 251.26  1     550.7 429.59 < 2.2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Adjusted R² jumps from 0.90 to 0.97, and the anova() F-test is highly significant (p < 2e-16) — adding the interaction significantly improves the model. For this data, the interaction model wins.

Visualize the synergy

Plot youtube against sales, coloured by a facebook split — the lines have different slopes, which is the interaction:

library(ggpubr)

data("marketing", package = "datarium")
marketing$fb_level <- ifelse(marketing$facebook > median(marketing$facebook),
                             "High facebook", "Low facebook")

ggscatter(marketing, x = "youtube", y = "sales",
          color = "fb_level", palette = "jco",
          add = "reg.line", legend = "right",
          xlab = "YouTube budget (k$)", ylab = "Sales") +
  ggpubr::stat_cor(aes(color = fb_level))

Scatter plot of sales versus youtube budget with separate regression lines for low and high facebook budget; the high-facebook line is steeper, showing the interaction.

The High facebook line is steeper — youtube returns more when facebook spending is high. Non-parallel lines are the visual signature of an interaction.

Report

A multiple linear regression tested the interaction between youtube and facebook advertising on sales. The interaction was significant (b = 0.0009, p < 0.001), and the interaction model explained substantially more variance than the additive model (adjusted R² = 0.97 vs 0.90; F(1, 196) = 430, p < 0.001). The effect of youtube on sales increased with the facebook budget — a synergy between the two channels.

With an interaction, \(y = \beta_0 + \beta_1 x_1 + \beta_2 x_2 + \beta_3 (x_1 x_2)\). Factor out \(x_1\): \(y = \beta_0 + (\beta_1 + \beta_3 x_2)\,x_1 + \beta_2 x_2\) — so the slope of \(x_1\) is no longer constant but \((\beta_1 + \beta_3 x_2)\), a line in \(x_2\). \(\beta_3\) is the rate at which \(x_1\)’s slope changes per unit of \(x_2\) (and, symmetrically, \(x_2\)’s slope per unit of \(x_1\)). \(\beta_3 = 0\) collapses back to the additive model.

Try it live

Does newspaper interact with youtube the way facebook does? Fit sales ~ youtube * newspaper and check the interaction term. The sandbox boots on first Run.

🟢 With an AI agent

Ask Prova “add an interaction term to my regression and tell me whether it significantly improves the model” — it answers with code you can run on your own data and interprets the interaction. The runtime is the judge. Ask Prova →

Common issues

You dropped a non-significant main effect but kept the interaction. That violates the hierarchical principle — keep both main effects whenever the interaction is in the model, or the coefficients become uninterpretable.

You interpreted the main-effect coefficient as the predictor’s overall effect. With an interaction, youtube’s coefficient is its effect only when facebook = 0 — not its average effect. The real effect is (b_youtube + b_interaction × facebook), which varies.

You added every possible interaction. Interactions multiply fast and overfit. Add them where you have a reason to expect one (or a clear plot signal), then confirm with anova() — don’t fish.

Frequently asked questions

Use the * operator in the formula: lm(y ~ x1 * x2) fits both main effects and the x1:x2 interaction. Use the colon (x1:x2) for the interaction term alone, but you’ll almost always want * so the main effects come along (the hierarchical principle).

It’s the amount by which one predictor’s slope changes per one-unit increase in the other. For youtube:facebook = 0.0009, each extra unit of facebook raises youtube’s per-unit effect by 0.0009 (and vice versa). The full effect of youtube is b_youtube + b_interaction × facebook.

If a model includes an interaction term, it should also include the main effects of the variables in that interaction — even when those main effects are not individually significant. Removing them makes the interaction mis-specified and the model hard to interpret.

Compare the interaction model to the additive model with anova(model_add, model_int) (a significant F-test means the interaction improves the fit) and check that adjusted R² rises. If the interaction term is non-significant and adjusted R² doesn’t improve, prefer the simpler additive model.

Test your understanding

  1. Run it. In the live cell, fit sales ~ youtube * newspaper. Is the youtube–newspaper interaction significant the way the youtube–facebook one is?
  2. Conceptual. In the interaction model, youtube’s coefficient is 0.019, smaller than its 0.046 in the additive model. Does that mean youtube became less important? Why or why not?

Fill the blank with newspaper, then compare its interaction p-value with the facebook one. For question 2, remember what the main-effect coefficient means when an interaction is present (facebook = 0).

The youtube–newspaper interaction is far weaker/non-significant compared with youtube–facebook — newspaper doesn’t amplify youtube the way facebook does. For question 2: no, youtube did not become less important. With the interaction in the model, youtube’s coefficient (0.019) is its effect only when facebook = 0; the actual effect is 0.019 + 0.0009 × facebook, which at a typical facebook budget exceeds the additive 0.046. The number changed meaning, not importance.

TipWhich model when?
  • Predictors act independentlymultiple linear regression.
  • One predictor’s effect depends on anotherinteraction effects (this lesson).
  • A factor’s effect depends on another factor → factor * factor interaction (same * syntax); see also two-way ANOVA.

Conclusion

You can now model interaction effects in regression in R: add a term with *, interpret the interaction coefficient as a slope-that-changes, respect the hierarchical principle, and test whether the synergy is real by comparing the interaction model to the additive one with anova() and adjusted R². When predictors amplify each other, an interaction captures what an additive model misses.

Reuse

Citation

BibTeX citation:
@online{2026,
  author = {},
  title = {Interaction {Effects} in {Regression} in {R}},
  date = {2026-06-23},
  url = {https://www.datanovia.com/learn/biostatistics/regression/interaction-effects-in-regression-in-r},
  langid = {en}
}
For attribution, please cite this work as:
“Interaction Effects in Regression in R.” 2026. June 23. https://www.datanovia.com/learn/biostatistics/regression/interaction-effects-in-regression-in-r.