library(tidyverse) #Data prep/explorationlibrary(dplyr) # data manipulationlibrary(lme4) # glmer multilevel modelslibrary(performance) # icc() — easiest VPC for glmer binomiallibrary(broom.mixed) # tidy() for model summaries## Read data relative to this documentPain <-readRDS("pain_workshop.rds")str(Pain)
##Model 0: Two-level variance-components binomial modelM0 <-glmer(dental_pain ~1+ (1|school_id), data = Pain, family =binomial(link="logit"))# Model 1: Two-level Random Intercept binomial model with exposure onlyM1 <-update(M0, . ~ . + high_sugar)# Model 2: Two-level Random Intercept binomial model adjusted ##by level 1 confoundersM2 <-update(M1, . ~ . + age_c + sex + family_income)# Model 3: Two-level Random Intercept binomial model adjusted by ##all confoundersM3 <-update(M2, . ~ . + school_type)## Results of M0summary(M0)
Generalized linear mixed model fit by maximum likelihood (Laplace
Approximation) [glmerMod]
Family: binomial ( logit )
Formula: dental_pain ~ 1 + (1 | school_id)
Data: Pain
AIC BIC logLik -2*log(L) df.resid
6301.1 6314.2 -3148.6 6297.1 4998
Scaled residuals:
Min 1Q Median 3Q Max
-1.8974 -0.7440 -0.5083 0.9823 2.5854
Random effects:
Groups Name Variance Std.Dev.
school_id (Intercept) 0.6977 0.8353
Number of obs: 5000, groups: school_id, 300
Fixed effects:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -0.59988 0.05836 -10.28 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## probability of having pain plogis(fixef(M0))
(Intercept)
0.3543713
#Observed prevalencemean(Pain$dental_pain)
[1] 0.374
Variance Partition Coefficient (VPC)
# manual VPC in a tidy wayvar_u <-VarCorr(M0)$school_id[1,1]vpc <- var_u / (var_u + pi^2/3)var_u
# MOR: for use with the multilevel logistic regression model# var_u denote the estimate variance of the random effects.var_u=VarCorr(M3)$school_id[1,1]MOR <-exp(((2*var_u)^0.5)*qnorm(0.75))MOR
[1] 2.048593
Single Level Model
M_SL <-glm(dental_pain ~ high_sugar + age_c + sex + family_income + school_type, data = Pain, family =binomial(link="logit"))tidy(M_SL, conf.int =TRUE, exponentiate =TRUE) %>% dplyr::select(term, estimate, std.error) %>%mutate(across(where(is.numeric), ~round(., 3)))