11
$\begingroup$

Let's say I have data:

x1 <- rnorm(100,2,10)
x2 <- rnorm(100,2,10)
y <- x1+x2+x1*x2+rnorm(100,1,2)
dat <- data.frame(y=y,x1=x1,x2=x2)
res <- lm(y~x1*x2,data=dat)
summary(res)

I want to plot the continuous by continuous interaction such that x1 is on the X axis and x2 is represented by 3 lines, one which represents x2 at a Z-score of 0, one at Z-score of +1, and another at a Z-score of -1, with each line a separate color and labelled. How can I do this using ggplot2?

For example, it might look something like this (though of course with different colored lines rather than different line types): Example Image

$\endgroup$
1
  • $\begingroup$ Could you show an example image from an other package/software or give a more detailed description what you want to plot? $\endgroup$
    – daroczig
    Jan 26, 2011 at 1:38

2 Answers 2

9
$\begingroup$

Here's my version with your simulated data set:

x1 <- rnorm(100,2,10)
x2 <- rnorm(100,2,10)
y <- x1+x2+x1*x2+rnorm(100,1,2)
dat <- data.frame(y=y,x1=x1,x2=x2)
res <- lm(y~x1*x2,data=dat)
z1 <- z2 <- seq(-1,1)
newdf <- expand.grid(x1=z1,x2=z2)

library(ggplot2)
p <- ggplot(data=transform(newdf, yp=predict(res, newdf)), 
            aes(y=yp, x=x1, color=factor(x2))) + stat_smooth(method=lm)
p + scale_colour_discrete(name="x2") + 
  labs(x="x1", y="mean of resp") + 
  scale_x_continuous(breaks=seq(-1,1)) + theme_bw()

I let you manage the details about x/y-axis labels and legend positioning.

enter image description here

$\endgroup$
2
  • $\begingroup$ Looks good, except (of course) we would need to scale(x1) and scale(x2) first. $\endgroup$ Jan 27, 2011 at 13:54
  • 1
    $\begingroup$ @drknexus Yes, of course (in my initial tests, I used standardized N(0;1) variates, instead of yours). $\endgroup$
    – chl
    Jan 27, 2011 at 14:36
5
$\begingroup$

Computing the estimates for y with Z-score of 0 (y0 column), -1 (y1m column) and 1 (y1p column):

dat$y0 <- res$coefficients[[1]] + res$coefficients[[2]]*dat$x1 + res$coefficients[[3]]*0 + res$coefficients[[4]]*dat$x1*0
	dat$y1m <- res$coefficients[[1]] + res$coefficients[[2]]*dat$x1 + res$coefficients[[3]]*-1 + res$coefficients[[4]]*dat$x1*-1
dat$y1p <- res$coefficients[[1]] + res$coefficients[[2]]*dat$x1 + res$coefficients[[3]]*1 + res$coefficients[[4]]*dat$x1*1

Plotting the lines with base plot():

plot(dat$x1, dat$y0, type="l", xlab="x1", ylab="Estimates")
lines(dat$x1, dat$y1m, col="red")
lines(dat$x1, dat$y1p, col="blue")

enter image description here

To use ggplot, you may call geom_line:

ggplot(dat, aes(x1, y0)) + geom_line() +
    geom_line(aes(x1, y1m), color="red") +
    geom_line(aes(x1, y1p), color="blue") +
    theme_bw() + opts(title="") + xlab("x1") + ylab("Estimates")

enter image description here

$\endgroup$
3
  • 2
    $\begingroup$ you can get predictions using predict. dat[,"y0"]<-predict(res,newdata=data.frame(x1=dat[,"x1"],x2=0)) Saves a bit of typing. $\endgroup$
    – mpiktas
    Jan 26, 2011 at 7:38
  • $\begingroup$ @mpiktas: thank you, I did not know about predict, but seems useful. $\endgroup$
    – daroczig
    Jan 26, 2011 at 10:12
  • 1
    $\begingroup$ I'd alway recommend using predict instead of calculating the slopes yourself - it's much simpler especially when you have interactions or non-linear components. $\endgroup$
    – hadley
    Jan 27, 2011 at 14:55

Not the answer you're looking for? Browse other questions tagged or ask your own question.