Moderation

Moderated regression with lm; multigroup SEM moderation; latent interaction (advanced)

Author
Affiliation

George Michaelides

Norwich Business School, University of East Anglia

Published

July 7, 2026

Learning objectives

By the end of this tutorial you will be able to:

  • describe what moderation is and how it differs from mediation
  • fit a moderated regression model with lm() and interpret an interaction term
  • centre predictors at their mean and compute simple slopes
  • plot an interaction with ggplot2
  • test moderation by a categorical variable with multigroup SEM, assuming measurement invariance (Tutorial 17)
  • recognise the syntax for latent variable interaction (advanced, beyond MSc scope)

Setup

Setup code (you have seen this before)
library(haven)
library(lavaan)
library(ggplot2)

What is moderation?

Moderation addresses the question “when or for whom does \(X\) affect \(Y\)?” A moderator \(W\) changes the size or direction of the \(X \rightarrow Y\) relationship. Unlike a mediator, the moderator is not in the causal chain from \(X\) to \(Y\) — it modifies the relationship itself.

Examples

  • The effect of job control on well-being may be stronger for employees with high self-efficacy than for those with low self-efficacy. Self-efficacy moderates the job control → well-being relationship.
  • The effect of training on performance may depend on gender: the training may be more effective for one gender than the other. Gender moderates the training → performance relationship.

Moderation versus mediation

Mediation Moderation
Question How does \(X\) affect \(Y\)? When does \(X\) affect \(Y\)?
Third variable In the causal chain (\(X \rightarrow M \rightarrow Y\)) Not in the causal chain; modifies the \(X \rightarrow Y\) path
Statistical model Indirect effect \(ab\) Interaction \(X \times W\)
Tutorial 11, 12 16

Moderated regression with lm()

The simplest moderation analysis is a moderated regression: you predict \(Y\) from \(X\), \(W\), and their interaction \(X \times W\). In R, the interaction is specified with the * operator, which expands to both main effects plus the product:

fit_mod <- lm(creat ~ con * gender, data = ps)
summary(fit_mod)
## 
## Call:
## lm(formula = creat ~ con * gender, data = ps)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.07002 -0.73321 -0.06803  0.59963  2.00284 
## 
## Coefficients:
##                  Estimate Std. Error t value Pr(>|t|)    
## (Intercept)       3.45216    0.36066   9.572   <2e-16 ***
## con              -0.09414    0.09416  -1.000    0.318    
## genderFemale     -0.39408    0.52905  -0.745    0.457    
## con:genderFemale  0.09712    0.13858   0.701    0.484    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.8585 on 328 degrees of freedom
##   (11 observations deleted due to missingness)
## Multiple R-squared:  0.003309,   Adjusted R-squared:  -0.005807 
## F-statistic: 0.363 on 3 and 328 DF,  p-value: 0.7798

The con * gender term expands to con + gender + con:gender, where con:gender is the interaction. The model has three coefficients beyond the intercept:

  • con — the effect of job control on creativity for the reference group of gender (Male, since it is the first level of the factor)
  • genderFemale — the difference in creativity between females and males when job control is zero (which is not meaningful if job control is on a 1–5 scale — see centring below)
  • con:genderFemale — the moderation effect: how much the slope of job control on creativity differs for females relative to males

If the interaction term is significant, gender moderates the relationship — the slope differs between males and females.

Centring predictors

The con coefficient and the genderFemale coefficient are interpreted at con = 0, which is not meaningful for a 1–5 Likert scale. To make the main effects interpretable, centre the continuous predictor at its mean:

ps$con_c <- scale(ps$con, scale = FALSE)   # mean-centre (subtract the mean)
attr(ps$con_c, "scaled:center")            # show the mean that was subtracted
## [1] 3.760447
fit_mod_c <- lm(creat ~ con_c * gender, data = ps)
summary(fit_mod_c)
## 
## Call:
## lm(formula = creat ~ con_c * gender, data = ps)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.07002 -0.73321 -0.06803  0.59963  2.00284 
## 
## Coefficients:
##                    Estimate Std. Error t value Pr(>|t|)    
## (Intercept)         3.09816    0.06435  48.146   <2e-16 ***
## con_c              -0.09414    0.09416  -1.000    0.318    
## genderFemale       -0.02885    0.09449  -0.305    0.760    
## con_c:genderFemale  0.09712    0.13858   0.701    0.484    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.8585 on 328 degrees of freedom
##   (11 observations deleted due to missingness)
## Multiple R-squared:  0.003309,   Adjusted R-squared:  -0.005807 
## F-statistic: 0.363 on 3 and 328 DF,  p-value: 0.7798

After centring:

  • con_c — the effect of job control on creativity for males, at the mean of job control (i.e. at con_c = 0)
  • genderFemale — the difference in creativity between females and males at the mean of job control
  • con_c:genderFemale — the moderation effect (unchanged by centring — only the main effects change interpretation)
NoteWhy centring matters

Centring does not change the interaction term or the model’s overall fit. It changes only the interpretation of the main effects. Without centring, the main effects are evaluated at con = 0 (meaningless). With centring, they are evaluated at the sample mean of con (meaningful). Always centre continuous predictors before interpreting main effects in a moderation model.

Simple slopes

A significant interaction means the slope of con on creat differs by gender. To understand how it differs, compute the simple slopes — the slope of con on creat separately for each gender group.

For a two-level moderator, the simplest approach is to fit separate regressions for each group:

# Slope of con on creat for males
fit_male <- lm(creat ~ con_c, data = subset(ps, gender == "Male"))
summary(fit_male)$coefficients
##                Estimate Std. Error   t value      Pr(>|t|)
## (Intercept)  3.09815770 0.06331666 48.931158 2.093875e-104
## con_c       -0.09413823 0.09265061 -1.016056  3.109973e-01
# Slope of con on creat for females
fit_female <- lm(creat ~ con_c, data = subset(ps, gender == "Female"))
summary(fit_female)$coefficients
##                Estimate Std. Error     t value     Pr(>|t|)
## (Intercept) 3.069308185 0.07045775 43.56239069 9.093927e-88
## con_c       0.002985641 0.10353237  0.02883775 9.770318e-01

Compare the con_c coefficients: if they differ substantially (and the interaction was significant), the moderation is practically meaningful. The con_c coefficient for males is the slope at the reference level; for females it is the slope at the other level.

Plotting the interaction

ggplot(ps, aes(x = con_c, y = creat, colour = gender)) +
  geom_point(alpha = 0.3) +
  geom_smooth(method = "lm", se = TRUE) +
  labs(x = "Job control (centred at mean)",
       y = "Creativity (mean of 3 items)",
       colour = "Gender",
       title = "Job control and creativity by gender") +
  theme_minimal()

Interaction plot: the relationship between job control (centred) and creativity, separately for males and females. Each line is the simple slope for one gender group.

The plot shows two fitted lines — one for each gender group. If the lines are parallel, there is no moderation (the slopes are the same). If the lines diverge or cross, moderation is present (the slopes differ).

TipTry it

Fit a moderated regression of creat on pa (centred) and gender. Is the interaction significant? Plot the interaction with ggplot2. Do males and females differ in how strongly positive affect predicts creativity?

ps$pa_c <- scale(ps$pa, scale = FALSE)
fit_pa_mod <- lm(creat ~ pa_c * gender, data = ps)
summary(fit_pa_mod)
## 
## Call:
## lm(formula = creat ~ pa_c * gender, data = ps)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.02495 -0.62345 -0.01414  0.56888  2.02102 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)    
## (Intercept)        3.07009    0.06345  48.386  < 2e-16 ***
## pa_c               0.18596    0.06179   3.009  0.00282 ** 
## genderFemale       0.02836    0.09320   0.304  0.76111    
## pa_c:genderFemale -0.01388    0.08584  -0.162  0.87161    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.8378 on 328 degrees of freedom
##   (11 observations deleted due to missingness)
## Multiple R-squared:  0.05062,    Adjusted R-squared:  0.04194 
## F-statistic:  5.83 on 3 and 328 DF,  p-value: 0.0006853
ggplot(ps, aes(x = pa_c, y = creat, colour = gender)) +
  geom_point(alpha = 0.3) +
  geom_smooth(method = "lm", se = TRUE) +
  labs(x = "Positive affect (centred at mean)",
       y = "Creativity",
       colour = "Gender") +
  theme_minimal()

Check the pa_c:genderFemale coefficient in the summary. If it is significant, gender moderates the PA → creativity relationship. The plot shows whether the two gender groups’ slopes diverge.

Multigroup SEM in lavaan

When the moderator is a categorical variable (like gender) and you have latent variables in your model, you can test moderation with multigroup SEM: you fit the model separately for each group and test whether the structural paths are equal across groups.

A prerequisite is measurement invariance — establishing that the measurement model (the factor loadings and item intercepts) is equivalent across groups. Without it, any path differences you find could be artefacts of the items measuring the factors differently in the two groups rather than true structural differences. Measurement invariance testing is involved enough to warrant its own tutorial; we cover it in full in Tutorial 17. The rest of this section assumes (partial) metric invariance has been established, which is the level required to compare structural paths.

Testing moderation of structural paths

Once (partial) metric invariance is established, you can test whether the structural paths differ across groups. In the context of our mediation model (Tutorial 12), you could test whether the indirect effect of con on creat through pa differs between males and females:

model_med <- '
  con   =~ p1 + p2 + p3
  pa    =~ pa1 + pa2 + pa3
  creat =~ creat1 + creat2 + creat3

  creat ~ b * pa + c * con
  pa    ~ a * con

  indirect := a * b
  direct   := c
  total    := c + (a * b)
'

# Fit with equal measurement model across groups
# but free structural paths
fit_med_group <- sem(model_med, data = ps, group = "gender",
                     group.equal = "loadings", estimator = "MLR")

# Now constrain structural paths to be equal
fit_med_group_eq <- sem(model_med, data = ps, group = "gender",
                        group.equal = c("loadings", "regressions"),
                        estimator = "MLR")

lavTestLRT(fit_med_group, fit_med_group_eq)

A significant result means the structural paths differ across groups — gender moderates the mediation. A non-significant result means the paths are equivalent — no moderation.

WarningMultigroup SEM requires sufficient sample size per group

Each group should have enough participants to estimate the model reliably. A rough rule of thumb is 100+ per group. The PS dataset has 178 males and 154 females — adequate but not generous. With smaller groups, the model may not converge or may produce unstable estimates.

Latent variable interaction (advanced)

When both the predictor and the moderator are latent variables (factors measured by multiple indicators), testing moderation requires modelling the interaction between two latent variables. This is more complex than a product term between observed variables.

lavaan supports latent interactions via the ~*~ operator (the product-indicator approach), but this is a PhD-level technique and beyond the scope of an MSc dissertation. We mention it here so you are aware it exists:

model_int <- '
  pa   =~ pa1 + pa2 + pa3
  con  =~ p1 + p2 + p3
  pa ~*~ con   # latent interaction between pa and con

  creat ~ pa + con + pa.con    # pa.con is the latent interaction term
'
ImportantLatent interaction is beyond MSc scope

Modelling interactions between latent variables requires the product-indicator approach (Klein & Moosbrugger, 2000) or the latent moderated structural equations (LMS) method. These are computationally demanding and theoretically advanced. For MSc work, we recommend:

  1. If both predictor and moderator are latent: compute factor scores from a CFA, then use the product of the factor scores as an observed interaction term in lm() — a simpler but approximate approach.
  2. If one variable is categorical: use multigroup SEM (as demonstrated above).
  3. If both are observed: use lm() with a product term (as demonstrated above).

Latent interaction is a topic for PhD-level work.

Common errors

WarningInterpreting main effects in the presence of an interaction

When an interaction term is in the model, the main effects are conditional effects — they apply only at the reference level of the moderator (for a categorical moderator) or at zero (for a continuous moderator). Do not interpret main effects as “overall” effects when an interaction is present. Centre continuous moderators to make the main effects interpretable at the mean.

Standardising the moderator before centring

scale(x, scale = TRUE) both centres and standardises (divides by the SD). This changes the scale of the coefficient — it is now in SD units, not original units. Use scale = FALSE for centring only; use scale = TRUE only if you want standardised coefficients.

Exercises

  1. Fit a moderated regression of creat on con (centred) and gender. Is the interaction significant? Compute the simple slopes for each gender group. Plot the interaction with ggplot2.

  2. Assuming (partial) metric invariance holds for the two-factor PA/neg model across gender — see Tutorial 17 — fit a multigroup SEM with the mediation model (Tutorial 12) and test whether the structural paths are equal across groups. Is the mediation moderated by gender?

  3. A researcher wants to test whether age moderates the effect of job control on creativity. Age is categorical (5 levels) in the PS dataset. Describe two ways they could test this: (a) with lm() and (b) with multigroup lavaan. What are the trade-offs?

Exercise 1

fit_ex1 <- lm(creat ~ con_c * gender, data = ps)
summary(fit_ex1)
## 
## Call:
## lm(formula = creat ~ con_c * gender, data = ps)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.07002 -0.73321 -0.06803  0.59963  2.00284 
## 
## Coefficients:
##                    Estimate Std. Error t value Pr(>|t|)    
## (Intercept)         3.09816    0.06435  48.146   <2e-16 ***
## con_c              -0.09414    0.09416  -1.000    0.318    
## genderFemale       -0.02885    0.09449  -0.305    0.760    
## con_c:genderFemale  0.09712    0.13858   0.701    0.484    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.8585 on 328 degrees of freedom
##   (11 observations deleted due to missingness)
## Multiple R-squared:  0.003309,   Adjusted R-squared:  -0.005807 
## F-statistic: 0.363 on 3 and 328 DF,  p-value: 0.7798
coef_male   <- coef(lm(creat ~ con_c, data = subset(ps, gender == "Male")))["con_c"]
coef_female <- coef(lm(creat ~ con_c, data = subset(ps, gender == "Female")))["con_c"]
coef_male
##       con_c 
## -0.09413823
coef_female
##       con_c 
## 0.002985641
ggplot(ps, aes(x = con_c, y = creat, colour = gender)) +
  geom_point(alpha = 0.3) +
  geom_smooth(method = "lm", se = TRUE) +
  labs(x = "Job control (centred)", y = "Creativity", colour = "Gender") +
  theme_minimal()

The interaction is significant if the con_c:genderFemale p-value is below .05. The simple slopes (coef_male, coef_female) show how the effect of job control differs by gender.

Exercise 2

ps$p1 <- (ps$con9 + ps$con10) / 2
ps$p2 <- (ps$con1 + ps$con8)  / 2
ps$p3 <- (ps$con3 + ps$con6)  / 2

model_med <- '
  con   =~ p1 + p2 + p3
  pa    =~ pa1 + pa2 + pa3
  creat =~ creat1 + creat2 + creat3
  creat ~ b * pa + c * con
  pa    ~ a * con
  indirect := a * b
  direct   := c
  total    := c + (a * b)
'

fit_free <- sem(model_med, data = ps, group = "gender",
                group.equal = "loadings", estimator = "MLR")
fit_eq   <- sem(model_med, data = ps, group = "gender",
                group.equal = c("loadings", "regressions"), estimator = "MLR")
lavTestLRT(fit_free, fit_eq)

A significant result means the structural paths differ by gender — the mediation is moderated. A non-significant result means the paths are equivalent — no moderation.

Exercise 3

(a) With lm(): Recode age as a factor and fit lm(creat ~ con * age, data = ps). The interaction terms con:age2, con:age3, etc. test whether the slope of con differs for each age band relative to the reference band. This is simple but does not separate measurement error from structural effects.

(b) With multigroup lavaan: Fit the latent SEM mediation model with group = "age". This tests whether the structural paths among the latent factors differ across age groups. This is more appropriate if you want to remove measurement error, but it requires sufficient sample size per age band (the PS dataset has only 21 participants in age band 1, which is too few for a stable multigroup SEM).

Trade-offs: lm() is simpler, faster, and works with small per-group samples, but uses manifest scores (with measurement error). Multigroup lavaan removes measurement error but requires larger per-group samples and is more complex to specify and interpret.

Summary

You have now completed the full tutorial series. You can:

  • Fit CFA, path analysis, SEM, and mediation models in lavaan (Tutorials 05–12)
  • Report results in APA format with texreg tables and tidySEM diagrams (Tutorial 13)
  • Extend to multilevel and growth curve models (Tutorials 14–15)
  • Test moderation with lm() and multigroup SEM (Tutorial 16)
  • Establish measurement invariance across groups (Tutorial 17)

These are the core tools you need for a quantitative dissertation in organisational psychology. The cheat sheet, glossary, and notation key are there for quick reference. When you encounter a technique we have not covered — latent profile analysis, EFA, categorical outcome SEM — the lavaan documentation and the further reading lists in each tutorial are your next stop.

Good luck with your dissertation.

Further reading

  • Hayes (2018) — the standard reference for moderation, mediation, and conditional process analysis.
  • Hoyle (2012) — the Handbook of Structural Equation Modeling includes chapters on multigroup SEM and latent interactions.
  • Kelloway (2015) — the textbook basis for the original teaching materials; covers moderation in an SEM framework.

References

Hayes, A. F. (2018). Introduction to mediation, moderation, and conditional process analysis: A regression-based approach.
Hoyle, R. H. (2012). Handbook of structural equation modeling.
Kelloway, E. K. (2015). Using mplus for structural equation modeling (2nd ed.). SAGE Publications.