<- function(n_subjects = 100, n_items = 50,
simulate b_0 = 0.847, b_e = 1.350, b_a = -1.253, b_c = 2.603,
b_ea = 0.790, b_ec = -1.393,
sd_u0s = 0.5, sd_u0i = 0.5, ...){
require(dplyr)
require(faux)
# simulate design
<- add_random(subject = n_subjects, item = n_items) %>%
dat add_between("subject", expert = c(1, 0), .prob = c(0.25, 0.75)) %>%
mutate(advice_present = rbinom(n(), 1, prob = 2/3)) %>%
mutate(advice_correct = if_else(advice_present == 1L,
rbinom(n(), 1L, prob = 0.8), 0L)) %>%
# add random effects
add_ranef("subject", u0s = sd_u0s) %>%
add_ranef("item", u0i = sd_u0i) %>%
# compute dependent variable
mutate(linpred = b_0 + u0i + u0s +
* expert + b_a * advice_present + b_c * advice_correct +
b_e * expert * advice_present + b_ec * expert * advice_correct) %>%
b_ea mutate(y_prob = plogis(linpred)) %>%
mutate(y_bin = rbinom(n = n(), size = 1, prob = y_prob))
dat }
Note
This Notebook was used to run the full simulation for the case study discussed in the manuscript. The simulation takes more than 1 hour to run on a Mac Book Pro (13-inch, M1, 2020) with 16 GB memory.
Simulation functions
In [1]:
In [2]:
<- function(
sim_and_analyse formula_chr = "y_bin ~ 1 + expert + advice_present + advice_correct +
expert:advice_present + expert:advice_correct + (1|subject) + (1|item)",
contrasts = c("b8 = b2", "b2 = b6", "b7 = b1", "b1 = b5"), ...){
require(lme4)
require(marginaleffects)
require(tidyr)
# simulate data
<- simulate(...)
dat # fit model
<- glmer(as.formula(formula_chr), data = dat, family = "binomial")
model # compute contrasts
<- expand_grid(advice_present = 0:1, advice_correct = 0:1,
contr_df expert = 0:1)
predictions(model, newdata = contr_df, type = "response", re.form = NA) %>%
hypotheses(hypothesis = contrasts, equivalence = c(0, 0)) %>%
data.frame()
}
Run simulation
In [3]:
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.4 ✔ readr 2.1.5
✔ forcats 1.0.0 ✔ stringr 1.5.1
✔ ggplot2 3.5.1 ✔ tibble 3.2.1
✔ lubridate 1.9.3 ✔ tidyr 1.3.1
✔ purrr 1.0.2
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(future)
library(furrr)
plan("multisession", workers = 6)
set.seed(2)
<- crossing(
sim_result rep = 1:500,
n_subjects = c(100, 150, 200, 250),
n_items = c(10, 30, 50, 70)
%>%
) mutate(res = future_pmap(., sim_and_analyse,
.options = furrr_options(seed = TRUE))) %>%
unnest(col = res)
Loading required package: lme4
Loading required package: Matrix
Attaching package: ‘Matrix’
The following objects are masked from ‘package:tidyr’:
expand, pack, unpack
Loading required package: marginaleffects
Loading required package: faux
************
Welcome to faux. For support and examples visit:
https://debruine.github.io/faux/
- Get and set global package options with: faux_options()
************
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
Loading required package: lme4
Loading required package: Matrix
Attaching package: ‘Matrix’
The following objects are masked from ‘package:tidyr’:
expand, pack, unpack
Loading required package: marginaleffects
Loading required package: faux
************
Welcome to faux. For support and examples visit:
https://debruine.github.io/faux/
- Get and set global package options with: faux_options()
************
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
Loading required package: lme4
Loading required package: Matrix
Attaching package: ‘Matrix’
The following objects are masked from ‘package:tidyr’:
expand, pack, unpack
Loading required package: marginaleffects
Loading required package: faux
************
Welcome to faux. For support and examples visit:
https://debruine.github.io/faux/
- Get and set global package options with: faux_options()
************
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
Loading required package: lme4
Loading required package: Matrix
Attaching package: ‘Matrix’
The following objects are masked from ‘package:tidyr’:
expand, pack, unpack
Loading required package: marginaleffects
Loading required package: faux
************
Welcome to faux. For support and examples visit:
https://debruine.github.io/faux/
- Get and set global package options with: faux_options()
************
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
Loading required package: lme4
Loading required package: Matrix
Attaching package: ‘Matrix’
The following objects are masked from ‘package:tidyr’:
expand, pack, unpack
Loading required package: marginaleffects
Loading required package: faux
************
Welcome to faux. For support and examples visit:
https://debruine.github.io/faux/
- Get and set global package options with: faux_options()
************
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
Loading required package: lme4
Loading required package: Matrix
Attaching package: ‘Matrix’
The following objects are masked from ‘package:tidyr’:
expand, pack, unpack
Loading required package: marginaleffects
Loading required package: faux
************
Welcome to faux. For support and examples visit:
https://debruine.github.io/faux/
- Get and set global package options with: faux_options()
************
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
Warning: There were 226 warnings in `mutate()`.
The first warning was:
ℹ In argument: `res = future_pmap(., sim_and_analyse, .options =
furrr_options(seed = TRUE))`.
Caused by warning in `checkConv()`:
! Model failed to converge with max|grad| = 0.0158128 (tol = 0.002, component 1)
ℹ Run `dplyr::last_dplyr_warnings()` to see the 225 remaining warnings.
Save results file to be used in the manuscript
In [4]:
saveRDS(sim_result, file = "results.rds")