Example of Polynomial Interaction
- DV: Quit smoking, IVs: Fear (X) + Self-Efficacy (Z)
- Simulation: \(Y = -.18X - .15X^2 + Z +
.16XZ + .07X^2Z +20 +\epsilon\)
- Set Fear of your health to be uniform distribution between 1 to 9
(centered)
- Set Self-Efficacy to be normal, \(M\)=0 and \(S\)=15
- Set \(\epsilon\) = 10 (normal
distribution of noise)
set.seed(42)
n <- 250
#Fear of Health
X <- scale(runif(n, 1, 9), scale=F)
#Centered Self-Efficacy
Z <- scale(runif(n, 0, 15), scale=F)
# Our equation to create Y
Y <- -.05*X - .20*X^2 + .15*X*Z + .22*(X^2)*Z+ 35 + rnorm(n, sd=10)
#Built our data frame
Smoke.Data<-data.frame(Smoking=Y,Health=X,SelfEfficacy=Z)
#run our regression
Smoke.Model.1<-lm(Smoking~poly(Health,2)+SelfEfficacy,Smoke.Data)
Smoke.Model.2<-lm(Smoking~poly(Health,2)*SelfEfficacy,Smoke.Data)
Smoke.Model.1.R<-lm(Smoking~poly(Health,2, raw=T)+SelfEfficacy,Smoke.Data)
Smoke.Model.2.R<-lm(Smoking~poly(Health,2, raw=T)*SelfEfficacy,Smoke.Data)
|
|
Dependent variable:
|
|
|
|
Smoking
|
|
Main Effects
|
Interaction
|
|
(1)
|
(2)
|
|
Constant
|
33.263*** (0.680)
|
33.493*** (0.621)
|
poly(Health, 2)1
|
1.010 (10.786)
|
3.083 (9.813)
|
poly(Health, 2)2
|
-9.037 (10.766)
|
-6.505 (9.795)
|
SelfEfficacy
|
1.188*** (0.155)
|
1.189*** (0.141)
|
poly(Health, 2)1:SelfEfficacy
|
|
3.042 (2.218)
|
poly(Health, 2)2:SelfEfficacy
|
|
16.361*** (2.288)
|
|
Observations
|
250
|
250
|
R2
|
0.197
|
0.341
|
Adjusted R2
|
0.187
|
0.328
|
Residual Std. Error
|
10.759 (df = 246)
|
9.781 (df = 244)
|
F Statistic
|
20.058*** (df = 3; 246)
|
25.297*** (df = 5; 244)
|
|
Note:
|
p<0.1; p<0.05;
p<0.01
|
|
|
Dependent variable:
|
|
|
|
Smoking
|
|
Main Effects Non-Ortho
|
Interaction Non-Ortho
|
|
(1)
|
(2)
|
|
Constant
|
33.909*** (1.027)
|
33.958*** (0.934)
|
poly(Health, 2, raw = T)1
|
0.009 (0.294)
|
0.070 (0.268)
|
poly(Health, 2, raw = T)2
|
-0.119 (0.142)
|
-0.086 (0.129)
|
SelfEfficacy
|
1.188*** (0.155)
|
0.020 (0.217)
|
poly(Health, 2, raw = T)1:SelfEfficacy
|
|
0.116* (0.060)
|
poly(Health, 2, raw = T)2:SelfEfficacy
|
|
0.216*** (0.030)
|
|
Observations
|
250
|
250
|
R2
|
0.197
|
0.341
|
Adjusted R2
|
0.187
|
0.328
|
Residual Std. Error
|
10.759 (df = 246)
|
9.781 (df = 244)
|
F Statistic
|
20.058*** (df = 3; 246)
|
25.297*** (df = 5; 244)
|
|
Note:
|
p<0.1; p<0.05;
p<0.01
|
- Note how different the results might look when you examine that as
power polynomials
Plotting the Simple Slopes when there are Curves
- These can be done with the
effects
package as I showed
you above and last week
- We will work with the orthogonal polynomial models
- or we can simply use the plotCurves function from the ‘rockchalk’
package
SmokeInterPlot <- plotCurves(Smoke.Model.2,
modx = "SelfEfficacy", plotx = "Health",
n=3,modxVals="std.dev")
- Lets plot just the main effect (and think about what it means
relative the power)
plotCurves(Smoke.Model.1, plotx = "Health")
- Does not look very quadratic, does it? In other words, you cannot
see the higher order effects as they can be hidden by the moderating
variable
- How to find these hidden things?
- You have to test for interactions and changes in \(R^2\)
- You have to try to add higher order terms, but they should be
motivated by some theory
- What if you did not know the second order term was in the model
above.
Smoke.Model.1.L<-lm(Smoking~Health+SelfEfficacy,Smoke.Data)
Smoke.Model.2.L<-lm(Smoking~Health*SelfEfficacy,Smoke.Data)
|
|
Dependent variable:
|
|
|
|
Smoking
|
|
Main Effects
|
Interaction
|
|
(1)
|
(2)
|
|
Constant
|
33.263*** (0.680)
|
33.334*** (0.680)
|
Health
|
0.028 (0.293)
|
0.042 (0.292)
|
SelfEfficacy
|
1.193*** (0.155)
|
1.207*** (0.155)
|
Health:SelfEfficacy
|
|
0.097 (0.066)
|
|
Observations
|
250
|
250
|
R2
|
0.194
|
0.201
|
Adjusted R2
|
0.188
|
0.192
|
Residual Std. Error
|
10.752 (df = 247)
|
10.727 (df = 246)
|
F Statistic
|
29.770*** (df = 2; 247)
|
20.666*** (df = 3; 246)
|
|
Note:
|
p<0.1; p<0.05;
p<0.01
|
ChangeInR.Smoke<-anova(Smoke.Model.1.L,Smoke.Model.2.L)
knitr::kable(ChangeInR.Smoke, digits=4)
247 |
28557.09 |
NA |
NA |
NA |
NA |
246 |
28306.63 |
1 |
250.4599 |
2.1766 |
0.1414 |
- There is no significant interaction, but let’s plot it anyway.
- Replotting as linear interaction
SmokeInterPlot.Linear <- plotSlopes(Smoke.Model.2.L, modx = "SelfEfficacy", plotx = "Health", n=3, modxVals="std.dev")
- Let’s check the change in \(R^2\)
from Linear interaction model to poly interaction model now
stargazer(Smoke.Model.2.L,Smoke.Model.2,type="html",
column.labels = c("Linear", "Poly"),
intercept.bottom = FALSE,
single.row=TRUE,
notes.append = FALSE,
header=FALSE)
|
|
Dependent variable:
|
|
|
|
Smoking
|
|
Linear
|
Poly
|
|
(1)
|
(2)
|
|
Constant
|
33.334*** (0.680)
|
33.493*** (0.621)
|
Health
|
0.042 (0.292)
|
|
poly(Health, 2)1
|
|
3.083 (9.813)
|
poly(Health, 2)2
|
|
-6.505 (9.795)
|
SelfEfficacy
|
1.207*** (0.155)
|
1.189*** (0.141)
|
Health:SelfEfficacy
|
0.097 (0.066)
|
|
poly(Health, 2)1:SelfEfficacy
|
|
3.042 (2.218)
|
poly(Health, 2)2:SelfEfficacy
|
|
16.361*** (2.288)
|
|
Observations
|
250
|
250
|
R2
|
0.201
|
0.341
|
Adjusted R2
|
0.192
|
0.328
|
Residual Std. Error
|
10.727 (df = 246)
|
9.781 (df = 244)
|
F Statistic
|
20.666*** (df = 3; 246)
|
25.297*** (df = 5; 244)
|
|
Note:
|
p<0.1; p<0.05;
p<0.01
|
ChangeInR.Smoke.2<-anova(Smoke.Model.2,Smoke.Model.2.L)
knitr::kable(ChangeInR.Smoke.2, digits=4)
244 |
23341.19 |
NA |
NA |
NA |
NA |
246 |
28306.63 |
-2 |
-4965.442 |
25.9534 |
0 |
Notes
- So, model with poly is a significantly better fit
- Would it change the story by much? In this case YES, but not always!
- Sometimes the improvement in fit is minor and does not change the
story
- Often ignoring the higher order term can make it easier to test
simple slopes and tell a story
- However, ignoring the higher order terms can violate your
assumptions when the results, let’s compare our linear vs poly models
residuals
- Linear Model
autoplot(Smoke.Model.2, which = 1:2, label.size = 1) + theme_bw()
autoplot(Smoke.Model.2.L, which = 1:2, label.size = 1) + theme_bw()