simsem/semTools

Interaction plots always intersect at origin by default leading to incorrect interpretations

Closed this issue · 3 comments

It seems that with the default options of probe2WayMC, the simple intercepts are not estimated and consequently the plotProbe will always plot the lines so that they all intesect at origin. This is a serious issue because intersecting lines have typically a different interpretation than lines that do not intersect. The default in indProduct is to do double mean centering. The documentation of probe2WayMC states that "Note that the double-mean centering may not be appropriate for probing interaction if researchers are interested in simple intercepts."

I propose two changes:

  1. Add a short explanation to the documentation explaining why double mean centering is not appropriate when simple intercepts are of interest
  2. Issue a warning when plotting results where intercepts were not estimated. For example, "Simple intercepts were not estimated by probe2WayMC. All lines intersect at origin by design. Relative positions of the lines on the y-axis should not be interpreted."

Here is an example of how the current defaults lead to very misleading plot. I do first regression with "true scores" and plot it to get the correct plot. Then I do a latent variable model which produces a very different plot. If I disable DMC, I get the correct plot from the latent variable model.

library(sjPlot)
library(semTools)

set.seed(1)
N <- 10000

X <- rnorm(N)
M <- rnorm(N)

Y <- X*M + 5*M + rnorm(N) 

plot_model(lm(Y ~ X*M), type = "pred", terms = c("X", "M"))


d <- matrix(c(X,X,X,M,M,M,Y,Y,Y) + rnorm(N*9), ncol = 9)
colnames(d) <- c("x1","x2","x3","m1","m2","m3","y1","y2","y3")

semMod <- "X =~ x1 + x2 + x3
M =~ m1 + m2 + m3
Y =~ y1 + y2 + y3

Y ~ X + M"

m1 <- sem(semMod, d)

dInt <- indProd(d, c("x1","x2","x3"), c("m1","m2","m3"))

intMod <- paste(semMod, "
                XM =~ x1.m1 + x2.m2 + x3.m3
                Y ~ XM")

m2 <- sem(intMod, dInt, 
          meanstructure = TRUE)

p <- probe2WayMC(m2,c("X","M","XM"), "Y", "M", valProbe = c(-1,0,1))
                 
plotProbe(p, xlim = c(1,5))

Thanks for the suggestion, I'll add both ideas.

Thanks. I think it would still be useful if the documentation of probe2WayMC (around line 18 in https://github.com/simsem/semTools/blob/master/semTools/R/probeInteraction.R) would explain a bit more beyond stating that "Note that the double-mean centering may not be appropriate for probing interaction if researchers are interested in simple intercepts.". It would be useful to have an explanation of why it might be inappropriate.

If I disable DMC, I get the correct plot from the latent variable model.

FYI, that is not what I get. I adapted your example to compare double, single, and no centering. (I also use the interactions package.)

library(semTools)
library(interactions)

set.seed(1)
N <- 10000

X <- rnorm(N)
M <- rnorm(N)
Y <- X*M + 5*M + rnorm(N) 

ols <- lm(Y ~ X*M)
interact_plot(ols, pred = "X", modx = "M")

d <- matrix(c(X,X,X,M,M,M,Y,Y,Y) + rnorm(N*9), ncol = 9)
colnames(d) <- c("x1","x2","x3","m1","m2","m3","y1","y2","y3")

semMod <- "X =~ x1 + x2 + x3
M =~ m1 + m2 + m3
Y =~ y1 + y2 + y3
XM =~ x1.m1 + x2.m2 + x3.m3

Y ~ 0*1 + X + M + XM
"

dat.noc <- indProd(d, c("x1","x2","x3"), c("m1","m2","m3"), doubleMC = FALSE, meanC = FALSE)
dat.mc <- indProd(d, c("x1","x2","x3"), c("m1","m2","m3"), doubleMC = FALSE)
dat.dmc <- indProd(d, c("x1","x2","x3"), c("m1","m2","m3"))

mod.noc <- sem(semMod, data = dat.noc)
mod.mc  <- sem(semMod, data = dat.mc )
mod.dmc <- sem(semMod, data = dat.dmc)

probe.noc <- probe2WayMC(mod.noc, c("X","M","XM"), "Y", "M", valProbe = c(-1,0,1))
probe.mc  <- probe2WayMC(mod.mc , c("X","M","XM"), "Y", "M", valProbe = c(-1,0,1))
probe.dmc <- probe2WayMC(mod.dmc, c("X","M","XM"), "Y", "M", valProbe = c(-1,0,1))

plotProbe(probe.noc, xlim = c(1,5))
plotProbe(probe.mc , xlim = c(1,5))
plotProbe(probe.dmc, xlim = c(1,5))

The issue is just that without an estimated y-intercept, the $SimpleIntcept element is NULL. Estimating the intercept (as in the probe2WayMC() help-page example) does resolve this.

semMod2 <- "X =~ x1 + x2 + x3
M =~ m1 + m2 + m3
Y =~ y1 + y2 + y3
XM =~ x1.m1 + x2.m2 + x3.m3

Y ~ 1 + X + M + XM
y1 ~ 0*1
"
mod2.dmc <- sem(semMod2, data = dat.dmc)
probe2.dmc <- probe2WayMC(mod2.dmc, c("X","M","XM"), "Y", "M", valProbe = c(-1,0,1))
plotProbe(probe2.dmc, xlim = c(-4,4))   # not xlim = c(1,5)

This is issue #127 that you opened.