\(~\)
Update: This function has migrated to the
rempsyc
package (https://github.com/rempsyc/rempsyc).
Let’s first load the demo data. This data set comes with base
R
(meaning you have it too and can directly type this
command into your R
console).
head(mtcars)
## mpg cyl disp hp drat wt qsec vs am gear carb
## Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
## Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
## Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
## Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
## Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
Load the rempsyc
package:
library(rempsyc)
Note: If you haven’t installed this package yet, you will need to install it via the following command:
devtools::install_github("rempsyc/rempsyc")
. Packagedevtools
is necessary for this command. If you haven’t installeddevtools
yet, install it viainstall.packages("devtools")
.
\(~\)
Simple moderation
nice_mod(data = mtcars,
response = "mpg",
predictor = "gear",
moderator = "wt") -> moderations
moderations
## Dependent Variable Predictor df b t p sr2
## 1 mpg gear 28 5.615951 1.9437108 0.06204275 0.028488305
## 2 mpg wt 28 1.403861 0.4301493 0.67037970 0.001395217
## 3 mpg gear:wt 28 -1.966931 -2.1551077 0.03989970 0.035022025
If we want it to look nice
<- nice_table(moderations, highlight = TRUE)) (my_table
Dependent Variable | Predictor | df | b | t | p | sr2 |
mpg | gear | 28 | 5.62 | 1.94 | .062 | .03 |
mpg | wt | 28 | 1.40 | 0.43 | .670 | .00 |
mpg | gear:wt | 28 | -1.97 | -2.16 | .040 | .04 |
Save table to Word
Let’s save it to word for use in a publication (optional).
save_as_docx(my_table, path = "D:/R treasures/moderations.docx")
Note: The sr2 (semi-partial correlation squared, also known as delta square) allows us to quantify the unique contribution (proportion of variance explained) of an independent variable on the dependent variable, over and above the other variables in the model. sr2 is often considered a better indicator of the practical relevance of a variable.
Simple slopes
Let’s extract the simple slopes now, including the sr2.
nice_slopes(data = mtcars,
response = "mpg",
predictor = "gear",
moderator = "wt") -> slopes
slopes
## Dependent Variable Predictor (+/-1 SD) df b t p
## 1 mpg gear (LOW-wt) 28 7.540509 2.010656 0.05408136
## 2 mpg gear (MEAN-wt) 28 5.615951 1.943711 0.06204275
## 3 mpg gear (HIGH-wt) 28 3.691393 1.795568 0.08336403
## sr2
## 1 0.03048448
## 2 0.02848830
## 3 0.02431123
nice_table(slopes, highlight = TRUE)
Dependent Variable | Predictor (+/-1 SD) | df | b | t | p | sr2 |
mpg | gear (LOW-wt) | 28 | 7.54 | 2.01 | .054 | .03 |
mpg | gear (MEAN-wt) | 28 | 5.62 | 1.94 | .062 | .03 |
mpg | gear (HIGH-wt) | 28 | 3.69 | 1.80 | .083 | .02 |
In this specific case, the interaction is significant but none of the simple slopes. This means that although the two slopes are significantly different from each other, taken individually, the slopes aren’t significantly different from a straight line.
The neat thing is that you can add as many dependent variables at once as you want.
# Moderations
nice_mod(data = mtcars,
response = c("mpg", "disp", "hp"),
predictor = "gear",
moderator = "wt") -> moderations
moderations
## Model Number Dependent Variable Predictor df b t p
## 1 1 mpg gear 28 5.615951 1.9437108 0.06204275
## 2 1 mpg wt 28 1.403861 0.4301493 0.67037970
## 3 1 mpg gear:wt 28 -1.966931 -2.1551077 0.03989970
## 4 2 disp gear 28 35.797623 0.6121820 0.54535707
## 5 2 disp wt 28 160.930043 2.4364098 0.02144867
## 6 2 disp gear:wt 28 -15.037022 -0.8140664 0.42247646
## 7 3 hp gear 28 -7.461189 -0.1554963 0.87754563
## 8 3 hp wt 28 11.253239 0.2076235 0.83702568
## 9 3 hp gear:wt 28 14.539586 0.9592587 0.34563902
## sr2
## 1 0.0284883047
## 2 0.0013952173
## 3 0.0350220247
## 4 0.0027372180
## 5 0.0433559718
## 6 0.0048402513
## 7 0.0003885555
## 8 0.0006927326
## 9 0.0147871391
nice_table(moderations, highlight = TRUE)
Model Number | Dependent Variable | Predictor | df | b | t | p | sr2 |
1 | mpg | gear | 28 | 5.62 | 1.94 | .062 | .03 |
1 | mpg | wt | 28 | 1.40 | 0.43 | .670 | .00 |
1 | mpg | gear:wt | 28 | -1.97 | -2.16 | .040 | .04 |
2 | disp | gear | 28 | 35.80 | 0.61 | .545 | .00 |
2 | disp | wt | 28 | 160.93 | 2.44 | .021 | .04 |
2 | disp | gear:wt | 28 | -15.04 | -0.81 | .422 | .00 |
3 | hp | gear | 28 | -7.46 | -0.16 | .878 | .00 |
3 | hp | wt | 28 | 11.25 | 0.21 | .837 | .00 |
3 | hp | gear:wt | 28 | 14.54 | 0.96 | .346 | .01 |
# Simple slopes
nice_slopes(data = mtcars,
response = c("mpg", "disp", "hp"),
predictor = "gear",
moderator = "wt") -> slopes
slopes
## Model Number Dependent Variable Predictor (+/-1 SD) df b t
## 1 1 mpg gear (LOW-wt) 28 7.540509 2.0106560
## 2 1 mpg gear (MEAN-wt) 28 5.615951 1.9437108
## 3 1 mpg gear (HIGH-wt) 28 3.691393 1.7955678
## 4 2 disp gear (LOW-wt) 28 50.510710 0.6654856
## 5 2 disp gear (MEAN-wt) 28 35.797623 0.6121820
## 6 2 disp gear (HIGH-wt) 28 21.084536 0.5067498
## 7 3 hp gear (LOW-wt) 28 -21.687555 -0.3482182
## 8 3 hp gear (MEAN-wt) 28 -7.461189 -0.1554963
## 9 3 hp gear (HIGH-wt) 28 6.765177 0.1981502
## p sr2
## 1 0.05408136 0.0304844847
## 2 0.06204275 0.0284883047
## 3 0.08336403 0.0243112307
## 4 0.51118526 0.0032346367
## 5 0.54535707 0.0027372180
## 6 0.61629796 0.0018755795
## 7 0.73028083 0.0019485684
## 8 0.87754563 0.0003885555
## 9 0.84435922 0.0006309595
nice_table(slopes, highlight = TRUE)
Model Number | Dependent Variable | Predictor (+/-1 SD) | df | b | t | p | sr2 |
1 | mpg | gear (LOW-wt) | 28 | 7.54 | 2.01 | .054 | .03 |
1 | mpg | gear (MEAN-wt) | 28 | 5.62 | 1.94 | .062 | .03 |
1 | mpg | gear (HIGH-wt) | 28 | 3.69 | 1.80 | .083 | .02 |
2 | disp | gear (LOW-wt) | 28 | 50.51 | 0.67 | .511 | .00 |
2 | disp | gear (MEAN-wt) | 28 | 35.80 | 0.61 | .545 | .00 |
2 | disp | gear (HIGH-wt) | 28 | 21.08 | 0.51 | .616 | .00 |
3 | hp | gear (LOW-wt) | 28 | -21.69 | -0.35 | .730 | .00 |
3 | hp | gear (MEAN-wt) | 28 | -7.46 | -0.16 | .878 | .00 |
3 | hp | gear (HIGH-wt) | 28 | 6.77 | 0.20 | .844 | .00 |
Pro tip: Both the
nice_mod()
andnice_slopes()
functions take the same argument, so you can just copy-paste the first and change the function call to save time!
Covariates
You can also have more complicated models, like with added covariates.
# Moderations
nice_mod(data = mtcars,
response = "mpg",
predictor = "gear",
moderator = "wt",
covariates = c("am", "vs")) -> moderations
moderations
## Dependent Variable Predictor df b t p sr2
## 1 mpg gear 26 5.840594 2.0773482 0.047786602 0.024922116
## 2 mpg wt 26 3.433057 1.1692031 0.252929701 0.007894893
## 3 mpg am 26 1.578465 0.8569286 0.399314133 0.004240876
## 4 mpg vs 26 3.817509 3.2441426 0.003228614 0.060780767
## 5 mpg gear:wt 26 -2.096457 -2.5615471 0.016567730 0.037894048
nice_table(moderations, highlight = TRUE)
Dependent Variable | Predictor | df | b | t | p | sr2 |
mpg | gear | 26 | 5.84 | 2.08 | .048 | .02 |
mpg | wt | 26 | 3.43 | 1.17 | .253 | .01 |
mpg | am | 26 | 1.58 | 0.86 | .399 | .00 |
mpg | vs | 26 | 3.82 | 3.24 | .003 | .06 |
mpg | gear:wt | 26 | -2.10 | -2.56 | .017 | .04 |
# Simple slopes
nice_slopes(data = mtcars,
response = "mpg",
predictor = "gear",
moderator = "wt",
covariates = c("am", "vs")) -> slopes
nice_table(slopes, highlight = TRUE)
Dependent Variable | Predictor (+/-1 SD) | df | b | t | p | sr2 |
mpg | gear (LOW-wt) | 26 | 7.89 | 2.21 | .036 | .03 |
mpg | gear (MEAN-wt) | 26 | 5.84 | 2.08 | .048 | .02 |
mpg | gear (HIGH-wt) | 26 | 3.79 | 1.82 | .081 | .02 |
In this case, the fist and middle rows are significant, which means
that those who are low on the wt
variable (below one
standard deviation) or those who are average on wt
have
significantly higher mpg
the higher their gear. We can plot
this in the more traditional way:
# First need to define model for plot function
<- lm(mpg ~ gear * wt + am + vs, data = mtcars)
mod
# Plot the model
library(interactions)
interact_plot(mod, pred = "gear", modx = "wt", interval = TRUE)
Note: If you haven’t installed this package yet, you will need to install it via the following command:
install.packages(interactions)
. Furthermore, know that this plot can be heavily customized with available arguments for publication purposes, but I won’t be going into these details here.
Three-way interaction
Let’s make a three-way interaction for example. Note that for the simple slopes, for now, the second moderator needs to be a dichotomic variable (and the first moderator a continuous variable).
# Moderations
nice_mod(response = "mpg",
predictor = "gear",
moderator = "wt",
moderator2 = "am",
data = mtcars) -> moderations
moderations
## Dependent Variable Predictor df b t p sr2
## 1 mpg gear 24 52.97009 1.831564 0.07945785 0.01660219
## 2 mpg wt 24 42.12157 1.603869 0.12182331 0.01273090
## 3 mpg am 24 202.38995 2.216085 0.03641826 0.02430490
## 4 mpg gear:wt 24 -15.09281 -1.729114 0.09663310 0.01479682
## 5 mpg gear:am 24 -58.83248 -1.992346 0.05782588 0.01964494
## 6 mpg wt:am 24 -58.67147 -2.053052 0.05112221 0.02086032
## 7 mpg gear:wt:am 24 16.79352 1.854357 0.07601677 0.01701798
nice_table(moderations, highlight = TRUE)
Dependent Variable | Predictor | df | b | t | p | sr2 |
mpg | gear | 24 | 52.97 | 1.83 | .079 | .02 |
mpg | wt | 24 | 42.12 | 1.60 | .122 | .01 |
mpg | am | 24 | 202.39 | 2.22 | .036 | .02 |
mpg | gear:wt | 24 | -15.09 | -1.73 | .097 | .01 |
mpg | gear:am | 24 | -58.83 | -1.99 | .058 | .02 |
mpg | wt:am | 24 | -58.67 | -2.05 | .051 | .02 |
mpg | gear:wt:am | 24 | 16.79 | 1.85 | .076 | .02 |
# Simple slopes
nice_slopes(data = mtcars,
response = "mpg",
predictor = "gear",
moderator = "wt",
moderator2 = "am") -> slopes
slopes
## Dependent Variable am Predictor (+/-1 SD) df b t p
## 1 mpg 0 gear (LOW-wt) 24 67.737763 1.8085806 0.08306317
## 2 mpg 0 gear (MEAN-wt) 24 52.970093 1.8315641 0.07945785
## 3 mpg 0 gear (HIGH-wt) 24 38.202424 1.8731910 0.07327171
## 4 mpg 1 gear (LOW-wt) 24 -7.526458 -0.9092225 0.37227347
## 5 mpg 1 gear (MEAN-wt) 24 -5.862384 -0.9829465 0.33543976
## 6 mpg 1 gear (HIGH-wt) 24 -4.198309 -1.1312335 0.26913442
## sr2
## 1 0.016188137
## 2 0.016602191
## 3 0.017365419
## 4 0.004091302
## 5 0.004781684
## 6 0.006333236
nice_table(slopes, highlight = TRUE)
Dependent Variable | am | Predictor (+/-1 SD) | df | b | t | p | sr2 |
mpg | 0.00 | gear (LOW-wt) | 24 | 67.74 | 1.81 | .083 | .02 |
mpg | 0.00 | gear (MEAN-wt) | 24 | 52.97 | 1.83 | .079 | .02 |
mpg | 0.00 | gear (HIGH-wt) | 24 | 38.20 | 1.87 | .073 | .02 |
mpg | 1.00 | gear (LOW-wt) | 24 | -7.53 | -0.91 | .372 | .00 |
mpg | 1.00 | gear (MEAN-wt) | 24 | -5.86 | -0.98 | .335 | .00 |
mpg | 1.00 | gear (HIGH-wt) | 24 | -4.20 | -1.13 | .269 | .01 |
Complex models
For more complicated models not supported by nice_mod
,
one can define the model in the traditional way and feed it to
nice_lm
instead. It supports multiple lm
models as well.
<- lm(mpg ~ cyl + wt * hp, mtcars)
model1 <- lm(qsec ~ disp + drat * carb, mtcars)
model2 <- list(model1, model2)
my.models <- nice_lm(my.models)) (nicelm.table
## Model Number Dependent Variable Predictor df b t
## 1 1 mpg cyl 27 -0.365239089 -0.7180977
## 2 1 mpg wt 27 -7.627489287 -5.0146028
## 3 1 mpg hp 27 -0.108394273 -3.6404181
## 4 1 mpg wt:hp 27 0.025836594 3.2329593
## 5 2 qsec disp 27 -0.006222635 -1.9746464
## 6 2 qsec drat 27 0.227692395 0.1968842
## 7 2 qsec carb 27 1.154106215 0.7179431
## 8 2 qsec drat:carb 27 -0.477539959 -1.0825727
## p sr2
## 1 0.47886516037 0.0021596150
## 2 0.00002928375 0.1053130854
## 3 0.00113640283 0.0555024045
## 4 0.00322175341 0.0437733438
## 5 0.05861684483 0.0702566891
## 6 0.84539274511 0.0006984424
## 7 0.47895897531 0.0092872897
## 8 0.28857203297 0.0211165564
nice_table(nicelm.table, highlight = TRUE)
Model Number | Dependent Variable | Predictor | df | b | t | p | sr2 |
1 | mpg | cyl | 27 | -0.37 | -0.72 | .479 | .00 |
1 | mpg | wt | 27 | -7.63 | -5.01 | < .001 | .11 |
1 | mpg | hp | 27 | -0.11 | -3.64 | .001 | .06 |
1 | mpg | wt:hp | 27 | 0.03 | 3.23 | .003 | .04 |
2 | qsec | disp | 27 | -0.01 | -1.97 | .059 | .07 |
2 | qsec | drat | 27 | 0.23 | 0.20 | .845 | .00 |
2 | qsec | carb | 27 | 1.15 | 0.72 | .479 | .01 |
2 | qsec | drat:carb | 27 | -0.48 | -1.08 | .289 | .02 |
The same applies to simple slopes, this time we use the
nice_lm_slopes
function. It supports multiple
lm
models as well, but the predictor and moderator need to
be the same for these models (the dependent variable can change).
<- lm(mpg ~ gear * wt, mtcars)
model1 <- lm(disp ~ gear * wt, mtcars)
model2 <- list(model1, model2)
my.models <- nice_lm_slopes(my.models, predictor = "gear", moderator = "wt")) (lmslopes.table
## Model Number Dependent Variable Predictor (+/-1 SD) df b t
## 1 1 mpg gear (LOW-wt) 28 7.540509 2.0106560
## 2 1 mpg gear (MEAN-wt) 28 5.615951 1.9437108
## 3 1 mpg gear (HIGH-wt) 28 3.691393 1.7955678
## 4 2 disp gear (LOW-wt) 28 50.510710 0.6654856
## 5 2 disp gear (MEAN-wt) 28 35.797623 0.6121820
## 6 2 disp gear (HIGH-wt) 28 21.084536 0.5067498
## p sr2
## 1 0.05408136 0.030484485
## 2 0.06204275 0.028488305
## 3 0.08336403 0.024311231
## 4 0.51118526 0.003234637
## 5 0.54535707 0.002737218
## 6 0.61629796 0.001875579
nice_table(lmslopes.table, highlight = TRUE)
Model Number | Dependent Variable | Predictor (+/-1 SD) | df | b | t | p | sr2 |
1 | mpg | gear (LOW-wt) | 28 | 7.54 | 2.01 | .054 | .03 |
1 | mpg | gear (MEAN-wt) | 28 | 5.62 | 1.94 | .062 | .03 |
1 | mpg | gear (HIGH-wt) | 28 | 3.69 | 1.80 | .083 | .02 |
2 | disp | gear (LOW-wt) | 28 | 50.51 | 0.67 | .511 | .00 |
2 | disp | gear (MEAN-wt) | 28 | 35.80 | 0.61 | .545 | .00 |
2 | disp | gear (HIGH-wt) | 28 | 21.08 | 0.51 | .616 | .00 |
\(~\)
\(~\)
Thanks for checking in
Make sure to check out this page again if you use the code after a time or if you encounter errors, as I periodically update or improve the code. Feel free to contact me for comments, questions, or requests to improve this function at https://github.com/rempsyc/rempsyc/issues.
\(~\)
\(~\)
\(~\)
\(~\)
\(~\)
Updated 2022-04-20 (added demos of nice_lm
and
nice_lm_slopes
functions)
\(~\)
\(~\)
\(~\)
\(~\)
\(~\)
\(~\)