#get example data with predictors X1 and X2 and a dependent variable Y
ds <- as.data.frame(
read.table(
"https://raw.github.com/johannjacoby/interaction_and_slopes/master/no_interaction_differing_slopes.dat",
header=T, sep="\t"))
#center both predictors
ds$centered.X1 <- scale(ds$X1, center=T, scale=F)
ds$centered.X2 <- scale(ds$X2, center=T, scale=F)
#shift X2 to obtain the simple slope of X1 @ 1SD below the mean of X2
ds$centered.X2.lo <- ds$centered.X2 + sd(ds$X2)
#shift X2 to obtain the simple slope of X1 @ 1SD above the mean of X2
ds$centered.X2.hi <- ds$centered.X2 - sd(ds$X2)
#### yes, it is correct, to get ds$centered.X2.hi you have to subtract 1 SD,
#### and in order to get ds$centered.X2.lo you have to add 1 SD.
# now estimate the basic regression model to see whether X1 and X2 interact:
model0 <- lm(Y~centered.X1*centered.X2, ds)
# and the two regression models in order to obtain the simple slopes of X1 at X2=1SD below the mean and at X2=1SD above the mean:
model.lo <- lm(Y~centered.X1*centered.X2.lo, ds)
model.hi <- lm(Y~centered.X1*centered.X2.hi, ds)
#show the models estimates
summary(model0); summary(model.lo); summary(model.hi)
# print the interaction and the simple slopes of X1 @ X2=-1SD and X2=+1SD
results0 <- summary(model0)[[4]]
results.lo <- summary(model.lo)[[4]]
results.hi <- summary(model.hi)[[4]]
cat("\n",
"Interaction X1 * X2: b=",results0[4],", t=",results0[12],", p=",
sprintf("%5.4f",results0[16]),ifelse(results0[16] < .05," *",""),"\n",
"Slope of X1 @ X2 = -1SD: b=",results.lo[2],", t=",results.lo[10],", p=",
sprintf("%5.4f",results.lo[14]),ifelse(results.lo[14] < .05," *",""),"\n",
"Slope of X1 @ X2 = +1SD: b=",results.hi[2],", t=",results.hi[10],", p=",
sprintf("%5.4f",results.hi[14]),ifelse(results.hi[14] < .05," *",""),"\n",
"absolute diff(p) = |",results.hi[14]," - ",results.lo[14],"| = ", abs(results.hi[14] - results.lo[14]), "\n",
"diff(b) = ",results.hi[2]," - ",results.lo[2]," = ",results.hi[2] - results.lo[2], "\n",
sep="")
# simple slope of X1 @ X2 = mean
cat("Slope of X1 @ X2 = mean of X2: b=",results0[2],", t=",results0[10],", p=",sprintf("%5.4f",results0[14]),ifelse(results0[14] < .05," *",""),"\n")
# simple slopes of X1 @ X2 = -2.5 SD and @ X1 = -0.5SD
ds$centered.X2.minus2SD <- ds$centered.X2 + 2 *sd(ds$X2)
model.lo.other <- lm(Y~centered.X1*centered.X2.minus2SD, ds)
summary(model.lo.other)
results.lo.other <- summary(model.lo.other)[[4]]; results.hi.other = summary(model.hi.other)[[4]]
cat(
"Slope of X1 @ X2 = -2SD: b=",results.lo.other[2],", t=",results.lo.other[10],", p=",
sprintf("%5.4f",results.lo.other[14]),ifelse(results.lo.other[14] < .05," *",""),"\n",
"Slope of X1 @ X2 = mean of X2: b=",results0[2],", t=",results0[10],", p=",
sprintf("%5.4f",results0[14]),ifelse(results0[14] < .05," *",""),"\n",
"abs.diff(p) = |",results.hi.other[14]," - ",results.lo.other[14],"| = ",abs(results.hi.other[14] - results.lo.other[14]), "\n",
"diff(b) = ",results.hi.other[2]," - ",results.lo.other[2]," = ",results.hi.other[2] - results.lo.other[2], "\n",
sep="")
exampledata.group.means <- as.data.frame(
read.table(
"https://raw.github.com/johannjacoby/interaction_and_slopes/master/group.mean.comparison.dat", header=T, sep="\t", quote="", stringsAsFactors=F))
#comparing group means individually against 0
test1 <- t.test(exampledata.group.means[which(exampledata.group.means$group==1),]$dv)
test2 <- t.test(exampledata.group.means[which(exampledata.group.means$group==2),]$dv)
cat(
"Group 1: t = ",test1$statistic,", p = ", sprintf("%10.9f",test1$p.value),"\n",
"Group 2: t = ",test2$statistic,", p = ", sprintf("%10.9f",test2$p.value),"\n",
sep="")
library(gplots)
dg <- barplot2(
tapply(exampledata.group.means$dv, exampledata.group.means$group, mean),
width=c(1,1), names.arg = c("Group 1", "Group 2"),
xlim=c(0,3), ylim = c(min(c(test1$conf.int[1], test2$conf.int[1]))-1,max(c(test1$conf.int[2], test2$conf.int[2]))+1),
plot.ci=TRUE, ci.l=c(test1$conf.int[1], test2$conf.int[1]), ci.u=c(test1$conf.int[2], test2$conf.int[2]),
ci.width=.1
)
title(sub=expression(paste("Error bars denote 95% confidence intervals | * = significant at ", alpha, " < .05", sep="")), cex.sub=.7, adj=0)
text(dg[1],test1$conf.int[2]+.5,paste("M = ",sprintf("%3.2f", test1$estimate), " ", ifelse(test1$p.value < .05,"*","n.s."), sep=""))
text(dg[2],test2$conf.int[2]+.5,paste("M = ",sprintf("%3.2f", test2$estimate), " ", ifelse(test2$p.value < .05,"*","n.s."), sep=""))
#comparing the difference between means against 0
test.both <- t.test(exampledata.group.means$dv, exampledata.group.means$group)
cat(
"Group comparison [M(Group 1) - M(Group2) against zero]: t = ",test.both$statistic,", p = ", sprintf("%5.4f",test.both$p.value),"\n",
sep="")
# data example: interaction significant but the simple slopes are not
example2 <- as.data.frame(
read.table(
"https://raw.github.com/johannjacoby/interaction_and_slopes/master/interaction_insignificant_slopes.dat",
header=T, sep="\t"))
example2$centered.X1 <- scale(example2$X1, center=T, scale=F)
example2$centered.X2 <- scale(example2$X2, center=T, scale=F)
example2$centered.X2.lo <- example2$centered.X2 + sd(example2$X2)
example2$centered.X2.hi <- example2$centered.X2 - sd(example2$X2)
model0.2 <- lm(Y~centered.X1*centered.X2, example2)
model.lo.2 <- lm(Y~centered.X1*centered.X2.lo, example2)
model.hi.2 <- lm(Y~centered.X1*centered.X2.hi, example2)
results0.2 <- summary(model0.2)[[4]]; results.lo.2 <- summary(model.lo.2)[[4]]; results.hi.2 <- summary(model.hi.2)[[4]]
cat("\n",
"Interaction X1 * X2: b=",results0.2[4],", t=",results0.2[12],", p=",
sprintf("%5.4f",results0[16]),ifelse(results0.2[16] < .05," *",""),"\n",
"Slope of X1 @ X2 = -1SD: b=",results.lo.2[2],", t=",results.lo.2[10],", p=",
sprintf("%5.4f",results.lo.2[14]),ifelse(results.lo.2[14] < .05," *",""),"\n",
"Slope of X1 @ X2 = +1SD: b=",results.hi.2[2],", t=",results.hi.2[10],", p=",
sprintf("%5.4f",results.hi.2[14]),ifelse(results.hi.2[14] < .05," *",""),"\n",
"absolute diff(p) = |",results.hi.2[14]," - ",results.lo.2[14],"| = ", abs(results.hi.2[14] - results.lo.2[14]), "\n",
"diff(b) = ",results.hi.2[2]," - ",results.lo.2[2]," = ",results.hi.2[2] - results.lo.2[2], "\n",
sep="")