I. Meta-data

# list of loaded packages and versions
si <- devtools::session_info()[[2]]
rownames(si) <- NULL
si %>% 
  select(package, loadedversion, date, source) %>% 
  
  #red bold the called packages
  mutate(package = cell_spec(package, 
                             color = ifelse(package %in% libraries, 
                                            "red", "black"),
                             bold = ifelse(package %in% libraries, 
                                           TRUE, FALSE))) %>% 
  knitr::kable(escape = F, caption = "All loaded packages. 
               Bolded in red are those loaded explicitly 
               with <code>library()</code>") %>% 
  kable_styling() %>% 
  scroll_box(height = "300px")
All loaded packages. Bolded in red are those loaded explicitly with library()
package loadedversion date source
assertthat 0.2.1 2019-03-21 CRAN (R 4.2.1)
backports 1.4.1 2021-12-13 CRAN (R 4.2.0)
base64enc 0.1-3 2015-07-28 CRAN (R 4.2.0)
bayestestR 0.13.0 2022-09-18 CRAN (R 4.2.1)
boot 1.3-28 2021-05-03 CRAN (R 4.2.2)
broom 1.0.1 2022-08-29 CRAN (R 4.2.1)
bslib 0.4.0 2022-07-16 CRAN (R 4.2.1)
cachem 1.0.6 2021-08-19 CRAN (R 4.2.1)
callr 3.7.3 2022-11-02 CRAN (R 4.2.2)
cellranger 1.1.0 2016-07-27 CRAN (R 4.2.1)
checkmate 2.1.0 2022-04-21 CRAN (R 4.2.1)
cli 3.4.1 2022-09-23 CRAN (R 4.2.1)
coda 0.19-4 2020-09-30 CRAN (R 4.2.1)
codetools 0.2-18 2020-11-04 CRAN (R 4.2.2)
colorspace 2.0-3 2022-02-21 CRAN (R 4.2.1)
crayon 1.5.2 2022-09-29 CRAN (R 4.2.1)
curl 4.3.3 2022-10-06 CRAN (R 4.2.1)
data.table 1.14.6 2022-11-16 CRAN (R 4.2.2)
datawizard 0.6.2 2022-10-04 CRAN (R 4.2.1)
DBI 1.1.3 2022-06-18 CRAN (R 4.2.1)
dbplyr 2.2.1 2022-06-27 CRAN (R 4.2.1)
devtools 2.4.5 2022-10-11 CRAN (R 4.2.1)
digest 0.6.29 2021-12-01 CRAN (R 4.2.1)
dplyr 1.0.10 2022-09-01 CRAN (R 4.2.1)
effectsize 0.8.1 2022-10-18 CRAN (R 4.2.1)
effsize 0.8.1 2020-10-05 CRAN (R 4.2.1)
ellipsis 0.3.2 2021-04-29 CRAN (R 4.2.1)
emmeans 1.8.1-1 2022-09-08 CRAN (R 4.2.1)
estimability 1.4.1 2022-08-05 CRAN (R 4.2.1)
evaluate 0.17 2022-10-07 CRAN (R 4.2.1)
fansi 1.0.3 2022-03-24 CRAN (R 4.2.1)
fastmap 1.1.0 2021-01-25 CRAN (R 4.2.1)
forcats 0.5.2 2022-08-19 CRAN (R 4.2.1)
foreign 0.8-83 2022-09-28 CRAN (R 4.2.2)
fs 1.5.2 2021-12-08 CRAN (R 4.2.1)
gargle 1.2.1 2022-09-08 CRAN (R 4.2.1)
generics 0.1.3 2022-07-05 CRAN (R 4.2.1)
ggeffects 1.1.3 2022-08-07 CRAN (R 4.2.1)
ggplot2 3.4.1 2023-02-10 CRAN (R 4.2.3)
glue 1.6.2 2022-02-24 CRAN (R 4.2.1)
googledrive 2.0.0 2021-07-08 CRAN (R 4.2.1)
googlesheets4 1.0.1 2022-08-13 CRAN (R 4.2.1)
gtable 0.3.1 2022-09-01 CRAN (R 4.2.1)
haven 2.5.1 2022-08-22 CRAN (R 4.2.1)
hms 1.1.2 2022-08-19 CRAN (R 4.2.1)
htmltools 0.5.3 2022-07-18 CRAN (R 4.2.1)
htmlwidgets 1.5.4 2021-09-08 CRAN (R 4.2.1)
httpuv 1.6.6 2022-09-08 CRAN (R 4.2.1)
httr 1.4.4 2022-08-17 CRAN (R 4.2.1)
insight 0.18.5 2022-10-12 CRAN (R 4.2.1)
jquerylib 0.1.4 2021-04-26 CRAN (R 4.2.1)
jsonlite 1.8.2 2022-10-02 CRAN (R 4.2.1)
kableExtra 1.3.4 2021-02-20 CRAN (R 4.2.1)
knitr 1.40 2022-08-24 CRAN (R 4.2.1)
later 1.3.0 2021-08-18 CRAN (R 4.2.1)
lattice 0.20-45 2021-09-22 CRAN (R 4.2.2)
lifecycle 1.0.3 2022-10-07 CRAN (R 4.2.1)
lme4 1.1-32 2023-03-14 CRAN (R 4.2.3)
lubridate 1.8.0 2021-10-07 CRAN (R 4.2.1)
magick 2.7.3 2021-08-18 CRAN (R 4.2.1)
magrittr 2.0.3 2022-03-30 CRAN (R 4.2.1)
MASS 7.3-58.1 2022-08-03 CRAN (R 4.2.2)
Matrix 1.5-1 2022-09-13 CRAN (R 4.2.2)
matrixStats 0.63.0 2022-11-18 CRAN (R 4.2.2)
memoise 2.0.1 2021-11-26 CRAN (R 4.2.1)
mime 0.12 2021-09-28 CRAN (R 4.2.0)
miniUI 0.1.1.1 2018-05-18 CRAN (R 4.2.1)
minqa 1.2.4 2014-10-09 CRAN (R 4.2.1)
modelr 0.1.9 2022-08-19 CRAN (R 4.2.1)
munsell 0.5.0 2018-06-12 CRAN (R 4.2.1)
mvtnorm 1.1-3 2021-10-08 CRAN (R 4.2.0)
nlme 3.1-160 2022-10-10 CRAN (R 4.2.2)
nloptr 2.0.3 2022-05-26 CRAN (R 4.2.1)
openxlsx 4.2.5 2021-12-14 CRAN (R 4.2.1)
pander 0.6.5 2022-03-18 CRAN (R 4.2.1)
parameters 0.19.0 2022-10-05 CRAN (R 4.2.1)
performance 0.10.0 2022-10-03 CRAN (R 4.2.1)
pillar 1.8.1 2022-08-19 CRAN (R 4.2.1)
pkgbuild 1.3.1 2021-12-20 CRAN (R 4.2.1)
pkgconfig 2.0.3 2019-09-22 CRAN (R 4.2.1)
pkgload 1.3.0 2022-06-27 CRAN (R 4.2.1)
plyr 1.8.7 2022-03-24 CRAN (R 4.2.1)
prettyunits 1.1.1 2020-01-24 CRAN (R 4.2.1)
processx 3.7.0 2022-07-07 CRAN (R 4.2.1)
profvis 0.3.7 2020-11-02 CRAN (R 4.2.1)
promises 1.2.0.1 2021-02-11 CRAN (R 4.2.1)
pryr 0.1.5 2021-07-26 CRAN (R 4.2.1)
ps 1.7.1 2022-06-18 CRAN (R 4.2.1)
purrr 1.0.1 2023-01-10 CRAN (R 4.2.3)
R6 2.5.1 2021-08-19 CRAN (R 4.2.1)
rapportools 1.1 2022-03-22 CRAN (R 4.2.1)
Rcpp 1.0.10 2023-01-22 CRAN (R 4.2.2)
readr 2.1.3 2022-10-01 CRAN (R 4.2.1)
readxl 1.4.1 2022-08-17 CRAN (R 4.2.1)
remotes 2.4.2 2021-11-30 CRAN (R 4.2.1)
reprex 2.0.2 2022-08-17 CRAN (R 4.2.1)
reshape2 1.4.4 2020-04-09 CRAN (R 4.2.1)
rio 0.5.29 2021-11-22 CRAN (R 4.2.1)
rlang 1.1.0 2023-03-14 CRAN (R 4.2.3)
rmarkdown 2.17 2022-10-07 CRAN (R 4.2.1)
rstudioapi 0.14 2022-08-22 CRAN (R 4.2.1)
rvest 1.0.3 2022-08-19 CRAN (R 4.2.1)
sass 0.4.2 2022-07-16 CRAN (R 4.2.1)
scales 1.2.1 2022-08-20 CRAN (R 4.2.1)
sessioninfo 1.2.2 2021-12-06 CRAN (R 4.2.1)
shiny 1.7.2 2022-07-19 CRAN (R 4.2.1)
sjlabelled 1.2.0 2022-04-10 CRAN (R 4.2.1)
sjmisc 2.8.9 2021-12-03 CRAN (R 4.2.1)
sjPlot 2.8.11 2022-08-07 CRAN (R 4.2.1)
sjstats 0.18.1 2021-01-09 CRAN (R 4.2.1)
stringi 1.7.8 2022-07-11 CRAN (R 4.2.1)
stringr 1.5.0 2022-12-02 CRAN (R 4.2.2)
summarytools 1.0.1 2022-05-20 CRAN (R 4.2.1)
svglite 2.1.0 2022-02-03 CRAN (R 4.2.1)
systemfonts 1.0.4 2022-02-11 CRAN (R 4.2.1)
tibble 3.1.8 2022-07-22 CRAN (R 4.2.1)
tidyr 1.3.0 2023-01-24 CRAN (R 4.2.3)
tidyselect 1.2.0 2022-10-10 CRAN (R 4.2.1)
tidyverse 1.3.2 2022-07-18 CRAN (R 4.2.1)
tzdb 0.3.0 2022-03-28 CRAN (R 4.2.1)
urlchecker 1.0.1 2021-11-30 CRAN (R 4.2.1)
usethis 2.1.6 2022-05-25 CRAN (R 4.2.1)
utf8 1.2.2 2021-07-24 CRAN (R 4.2.1)
vctrs 0.6.0 2023-03-16 CRAN (R 4.2.3)
viridisLite 0.4.1 2022-08-22 CRAN (R 4.2.1)
webshot 0.5.4 2022-09-26 CRAN (R 4.2.1)
withr 2.5.0 2022-03-03 CRAN (R 4.2.1)
xfun 0.33 2022-09-12 CRAN (R 4.2.1)
xml2 1.3.3 2021-11-30 CRAN (R 4.2.1)
xtable 1.8-4 2019-04-21 CRAN (R 4.2.1)
yaml 2.3.5 2022-02-21 CRAN (R 4.2.1)
zip 2.2.1 2022-09-08 CRAN (R 4.2.1)

II. Emerging Adulthood

A team of undergraduate research assistants (Amilla Aceiro, Garrett Mormile, Nicholas Hadacek) screened the most recent 6 issues of Emerging Adulthood, which constitutes the past 1 year of the journal.

# read in data
ea <- rio::import(file = "emerging-adulthood_data.xlsx")
ea[ea == "NA"] <- NA
ea <- ea %>% 
  mutate(N = as.numeric(N),
         Empirical = as.numeric(Empirical == "Yes"),
         Interaction = as.numeric(Interaction == "Yes"),
         Power = as.numeric(Power == "Yes"))

# summary
ea %>% select(N, Empirical, Interaction, Power) %>% 
  descr(stats = "common", order = "p")
## Descriptive Statistics  
## ea  
## N: 117  
## 
##                          N   Empirical   Interaction   Power
## --------------- ---------- ----------- ------------- -------
##            Mean    3312.01        0.58          0.57    0.40
##         Std.Dev   12000.97        0.50          0.50    0.50
##             Min      39.00        0.00          0.00    0.00
##          Median     501.00        1.00          1.00    0.00
##             Max   75070.00        1.00          1.00    1.00
##         N.Valid      68.00      117.00         68.00   40.00
##       Pct.Valid      58.12      100.00         58.12   34.19
# plots of binary variables
ggplot(ea, 
       aes(factor(Empirical,
                  levels = c(0, 1),
                  labels = c("Non-Empirical", "Empirical")))) + 
  geom_bar(fill = c("#f1c232", "#710c0c")) + 
  geom_text(stat='count', aes(label=..count..), vjust = -1) + 
  labs(
    title = "Count of quantitative and empirical papers",
    x = NULL
  ) +
  ylim(0, 100) +
  theme_classic()

ggplot(ea[which(!is.na(ea$Interaction)), ], 
       aes(factor(Interaction,
                  levels = c(0, 1),
                  labels = c("No Interaction Test", 
                             "At Least One Interaction Test")))) + 
  geom_bar(fill = c("#f1c232", "#710c0c")) + 
  geom_text(stat='count', aes(label=..count..), vjust = -1) + 
  labs(
    title = "Count of empirical papers with interaction tests",
    x = NULL
  ) +
  ylim(0, 60) +
  theme_classic()

ggplot(ea[which(!is.na(ea$Power)), ], 
       aes(factor(Power,
                  levels = c(0, 1),
                  labels = c("No Power Calculation", 
                             "Some Power Calculation")))) + 
  geom_bar(fill = c("#f1c232", "#710c0c")) + 
  geom_text(stat='count', aes(label=..count..), vjust = -1) + 
  labs(
    title = "Count of papers with interaction tests that performed some power calculation",
    x = NULL
  ) +
  ylim(0, 50) +
  theme_classic()

# plot of sample size
ggplot(data = ea[which(ea$Interaction == 1),], aes(N)) +
  geom_boxplot(fill = "#710c0c", color = "#f1c232") + 
  annotate("text", 
           label = paste0("Median = ", 
                          median(ea[which(ea$Interaction == 1), "N"]),
                          " participants"),
           x = 5000, y = 0.3) + 
  labs(
    title = "Distribution of sample sizes in papers with interaction tests",
    x = "Sample size (in participants)",
    y = NULL
  ) +
  xlim(-500, 23000) + 
  theme_classic()

# plot of sample size excluding outlier (N > 4000)
ggplot(data = ea[which(ea$Interaction == 1 & ea$N < 4000),], aes(N)) +
  geom_boxplot(fill = "#710c0c", color = "#f1c232") + 
  labs(
    title = "Distribution of sample sizes excluding 5 outliers (N > 4,000)",
    x = "Sample size (in participants)",
    y = NULL
  ) +
  theme_classic()

# bar plot
ea %>%
  filter(Interaction == 1) %>%
  mutate(name = fct_reorder(Title, N)) %>%
  ggplot(aes(x = name, y = N)) +
    geom_bar(stat = "identity", fill = "#710c0c") +
    labs(
      title = "Distribution of sample sizes in papers with interaction tests",
      x = "Empirical papers with at least one interaction test",
      y = "Sample size (in participants)"
    ) +
    theme_classic() +
    theme(axis.text.x = element_blank())

ea %>%
  filter(Interaction == 1 & N < 4000) %>%
  mutate(name = fct_reorder(Title, N)) %>%
  ggplot(aes(x = name, y = N)) +
    geom_bar(stat = "identity", fill = "#710c0c") +
    labs(
      title = "Distribution of sample sizes excluding 5 outliers (N > 4,000)",
      x = "Empirical papers with at least one interaction test",
      y = "Sample size (in participants)"
    ) +
    theme_classic() +
    theme(axis.text.x = element_blank())

III. Interaction types

In addition, we are highlighting here the minimum sample size required to achieve 80% power for three interaction shapes examples as presented by Sommet et al., 2022:

  1. Reversed interactions with simple slope Cohen’s \(d\): small/small (\(\pm0.20\)), medium/medium (\(\pm0.35\)), and large/large (\(\pm0.50\))
  2. Fully attenuated interactions with simple slope Cohen’s \(d\): small/null, medium/null, and large/null
  3. Partially attenuated interactions with simple slope Cohen’s \(d\): small/medium, small/large, medium/large

Reversed interactions

set.seed(202210)

mu <- 0         # grand mean

# first simple slope
d  <- 0.50      # Cohen's D
sd <- 1         # pooled SD
delta <- sd*d
m <- c(mu+delta/2,mu-delta/2)     # specify means for each group
n <- c(1000, 1000)                # sample size for each group

grp1 <- rnorm(n[1],mean=m[1],sd=sd)
grp3 <- rnorm(n[2],mean=m[2],sd=sd)

#cohen.d(grp1, grp2)

# second simple slope
d <- -0.50      # Cohen's D
delta <- sd*d
m <- c(mu+delta/2,mu-delta/2)     # specify means for each group

grp2 <- rnorm(n[1],mean=m[1],sd=sd)
grp4 <- rnorm(n[2],mean=m[2],sd=sd)

#cohen.d(grp3, grp4)

y   <- as.numeric(c(grp1, grp2, grp3, grp4))
x   <- c(rep("A", 2000), rep("B", 2000))
mod <- rep(c(rep("C", 1000), rep("D", 1000)), 2)
dat <- data.frame(y = y, x = as.factor(x), Moderator = as.factor(mod))

#summary(lm(y ~ x*Moderator, data = dat))

plot_model(lm(y ~ x*Moderator, data = dat), 
           type = "eff",
           terms = c("x", "Moderator"),
           axis.title = c("Predictor", "Outcome"),
           title = "Illustrative plot for large/large reversed interaction",
           jitter = NULL) + 
  geom_line(position = position_dodge(width = 0.1), size = 0.8) +
  scale_colour_manual(values = c(
    C = "#710c0c",
    D = "#f1c232")) +
  theme_classic()

# box plot
ggplot(data = ea[which(ea$Interaction == 1 & ea$N < 4000),], aes(N)) +
  geom_boxplot(fill = "#710c0c") + 
  geom_vline(xintercept = 787, color = "#f1c232", size = 1) +
  geom_vline(xintercept = 256, color = "#0180D4", size = 1) +
  geom_vline(xintercept = 125, color = "#0D803E", size = 1) +
  annotate("text", 
           label = paste0("N = 707 for small/small reversed effects"),
           x = 1500, y = 0.4, color = "#f1c232") + 
  annotate("text", 
           label = paste0("N = 256 for medium/medium reversed effects"),
           x = 1500, y = 0.3, color = "#0180D4") + 
  annotate("text", 
           label = paste0("N = 125 for large/large reversed effects"),
           x = 1500, y = 0.2, color = "#0D803E") + 
  labs(
    title = "Distribution of sample sizes excluding 5 outliers (N > 4,000)",
    x = "Sample size (in participants)",
    y = NULL
  ) +
  ylim(-0.5, 0.5) +
  xlim(0, 2000) +
  theme_classic()

# bar plot
ea %>%
  filter(Interaction == 1 & N < 4000) %>%
  mutate(name = fct_reorder(Title, N)) %>%
  ggplot(aes(x = name, y = N)) +
    geom_bar(stat = "identity", fill = "#710c0c") +
    geom_hline(yintercept = 787, color = "#f1c232", size = 1) +
    geom_hline(yintercept = 256, color = "#0180D4", size = 1) +
    geom_hline(yintercept = 125, color = "#0D803E", size = 1) +
    annotate("text", 
             label = paste0("N = 707 for small/small reversed effects"),
             x = 15, y = 1400, color = "#f1c232") + 
    annotate("text", 
             label = paste0("N = 256 for medium/medium reversed effects"),
             x = 15, y = 1250, color = "#0180D4") + 
    annotate("text", 
             label = paste0("N = 125 for large/large reversed effects"),
             x = 15, y = 1100, color = "#0D803E") + 
    labs(
      title = "Distribution of sample sizes excluding 5 outliers (N > 4,000)",
      x = "Empirical papers with at least one interaction test",
      y = "Sample size (in participants)"
    ) +
    theme_classic() +
    theme(axis.text.x = element_blank())

Fully attenuated interactions

set.seed(202210)

mu <- 0         # grand mean

# first simple slope
d  <- 0         # Cohen's D
sd <- 1         # pooled SD
delta <- sd*d
m <- c(mu+delta/2,mu-delta/2)     # specify means for each group
n <- c(1000, 1000)                # sample size for each group

grp1 <- rnorm(n[1],mean=m[1],sd=sd)
grp3 <- rnorm(n[2],mean=m[2],sd=sd)

#cohen.d(grp1, grp3)

# second simple slope
d <- -0.50       # Cohen's D
delta <- sd*d
m <- c(mean(grp1), mean(grp1)-delta)     # specify means for each group

grp2 <- rnorm(n[1],mean=m[1],sd=sd)
grp4 <- rnorm(n[2],mean=m[2],sd=sd)

#cohen.d(grp2, grp4)

y   <- as.numeric(c(grp1, grp2, grp3, grp4))
x   <- c(rep("A", 2000), rep("B", 2000))
mod <- rep(c(rep("C", 1000), rep("D", 1000)), 2)
dat <- data.frame(y = y, x = as.factor(x), Moderator = as.factor(mod))

#summary(lm(y ~ x*Moderator, data = dat))

plot_model(lm(y ~ x*Moderator, data = dat), 
           type = "eff",
           terms = c("x", "Moderator"),
           axis.title = c("Predictor", "Outcome"),
           title = "Illustrative plot for large/null full interaction",
           jitter = NULL) + 
  geom_line(position = position_dodge(width = 0.1), size = 0.8) +
  scale_colour_manual(values = c(
    C = "#710c0c",
    D = "#f1c232")) +
  ylim(-0.2, 0.7)+
  theme_classic()

# box plot
ggplot(data = ea[which(ea$Interaction == 1 & ea$N < 4000),], aes(N)) +
  geom_boxplot(fill = "#710c0c") + 
  geom_vline(xintercept = 3136, color = "#f1c232", size = 1) +
  geom_vline(xintercept = 1024, color = "#0180D4", size = 1) +
  geom_vline(xintercept = 502,  color = "#0D803E", size = 1) +
  annotate("text", 
           label = paste0("N = 3,136 for small/null attenuations"),
           x = 2000, y = 0.4, color = "#f1c232") + 
  annotate("text", 
           label = paste0("N = 1,024 for medium/null attenuations"),
           x = 2000, y = 0.3, color = "#0180D4") + 
  annotate("text", 
           label = paste0("N = 502 for large/null attentuations"),
           x = 2000, y = 0.2, color = "#0D803E") + 
  labs(
    title = "Distribution of sample sizes excluding 5 outliers (N > 4,000)",
    x = "Sample size (in participants)",
    y = NULL
  ) +
  ylim(-0.5, 0.5) +
  theme_classic()

# bar plot
ea %>%
  filter(Interaction == 1 & N < 4000) %>%
  mutate(name = fct_reorder(Title, N)) %>%
  ggplot(aes(x = name, y = N)) +
    geom_bar(stat = "identity", fill = "#710c0c") +
    geom_hline(yintercept = 3136, color = "#f1c232", size = 1) +
    geom_hline(yintercept = 1024, color = "#0180D4", size = 1) +
    geom_hline(yintercept = 502,  color = "#0D803E", size = 1) +
    annotate("text", 
             label = paste0("N = 3,136 for small/null attenuations"),
             x = 15, y = 2650, color = "#f1c232") + 
    annotate("text", 
             label = paste0("N = 1,024 for medium/null attenuations"),
             x = 15, y = 2300, color = "#0180D4") + 
    annotate("text", 
             label = paste0("N = 502 for large/null attentuations"),
             x = 15, y = 1950, color = "#0D803E") + 
    labs(
      title = "Distribution of sample sizes excluding 5 outliers (N > 4,000)",
      x = "Empirical papers with at least one interaction test",
      y = "Sample size (in participants)"
    ) +
    theme_classic() +
    theme(axis.text.x = element_blank())

Partially attenuated interactions

set.seed(202210)

mu <- 0          # grand mean

# first simple slope
d  <- -0.20      # Cohen's D
sd <- 1          # pooled SD
delta <- sd*d
m <- c(mu+delta/2,mu-delta/2)     # specify means for each group
n <- c(1000, 1000)                # sample size for each group

grp1 <- rnorm(n[1],mean=m[1],sd=sd)
grp3 <- rnorm(n[2],mean=m[2],sd=sd)

#cohen.d(grp1, grp2)

# second simple slope
d <- -0.50       # Cohen's D
delta <- sd*d
m <- c(mean(grp1),mean(grp1)-delta)     # specify means for each group

grp2 <- rnorm(n[1],mean=m[1],sd=sd)
grp4 <- rnorm(n[2],mean=m[2],sd=sd)

#cohen.d(grp3, grp4)

y   <- as.numeric(c(grp1, grp2, grp3, grp4))
x   <- c(rep("A", 2000), rep("B", 2000))
mod <- rep(c(rep("C", 1000), rep("D", 1000)), 2)
dat <- data.frame(y = y, x = as.factor(x), Moderator = as.factor(mod))

#summary(lm(y ~ x*Moderator, data = dat))

plot_model(lm(y ~ x*Moderator, data = dat), 
           type = "eff",
           terms = c("x", "Moderator"),
           axis.title = c("Predictor", "Outcome"),
           title = "Illustrative plot for small/large partial interaction",
           jitter = NULL) + 
  geom_line(position = position_dodge(width = 0.1), size = 0.8) +
  scale_colour_manual(values = c(
    C = "#710c0c",
    D = "#f1c232")) +
  ylim(-0.3, 0.6)+
  theme_classic()

# box plot
ggplot(data = ea[which(ea$Interaction == 1 & ea$N < 4000),], aes(N)) +
  geom_boxplot(fill = "#710c0c") + 
  geom_vline(xintercept = 5575, color = "#f1c232", size = 1) +
  geom_vline(xintercept = 1394, color = "#0180D4", size = 1) +
  annotate("text", 
           label = paste0("N = 5,575 for small/medium attenuations"),
           x = 3500, y = 0.4, color = "#f1c232") + 
  annotate("text", 
           label = paste0("N = 1,394 for small/large attenuations"),
           x = 3500, y = 0.3, color = "#0180D4") + 
  labs(
    title = "Distribution of sample sizes excluding 5 outliers (N > 4,000)",
    x = "Sample size (in participants)",
    y = NULL
  ) +
  ylim(-0.5, 0.5) +
  xlim(0, 7500) +
  theme_classic()

# bar plot
ea %>%
  filter(Interaction == 1 & N < 4000) %>%
  mutate(name = fct_reorder(Title, N)) %>%
  ggplot(aes(x = name, y = N)) +
    geom_bar(stat = "identity", fill = "#710c0c") +
    geom_hline(yintercept = 5575, color = "#f1c232", size = 1) +
    geom_hline(yintercept = 1394, color = "#0180D4", size = 1) +
    annotate("text", 
             label = paste0("N = 5,575 for small/medium attenuations"),
             x = 15, y = 4000, color = "#f1c232") + 
    annotate("text", 
             label = paste0("N = 1,394 for small/large attenuations"),
             x = 15, y = 3500, color = "#0180D4") + 
    labs(
      title = "Distribution of sample sizes excluding 5 outliers (N > 4,000)",
      x = "Empirical papers with at least one interaction test",
      y = "Sample size (in participants)"
    ) +
    theme_classic() +
    ylim(0, 6000) +
    theme(axis.text.x = element_blank())

# bar plot
ea %>%
  filter(Interaction == 1) %>%
  mutate(name = fct_reorder(Title, N)) %>%
  ggplot(aes(x = name, y = N)) +
    geom_bar(stat = "identity", fill = "#710c0c") +
    geom_hline(yintercept = 5575, color = "#f1c232", size = 1) +
    geom_hline(yintercept = 1394, color = "#0180D4", size = 1) +
    annotate("text", 
             label = paste0("N = 5,575 for small/medium attenuations"),
             x = 15, y = 7000, color = "#f1c232") + 
    annotate("text", 
             label = paste0("N = 1,394 for small/large attenuations"),
             x = 15, y = 3000, color = "#0180D4") + 
    labs(
      title = "Distribution of sample sizes including outliers",
      x = "Empirical papers with at least one interaction test",
      y = "Sample size (in participants)"
    ) +
    theme_classic() +
    ylim(0, 22000) +
    theme(axis.text.x = element_blank())