MRP Tutorial Answer Key

1. Partial Pooling Effect

In the tutorial example, which subclass shows the most partial pooling effect? Identify this subclass with R code and provide a justification for your answer.

Answer

First, we run the previous code from the tutorial: (if you need code explanations, see the tutorial R script.). I didn’t include that part for clarity.

We aim to identify which subclass shows the most partial pooling effect. Partial pooling occurs in hierarchical models when group-level estimates are shrunk towards the overall mean due to the influence of both group-level and individual-level data. The degree of shrinkage (partial pooling) is related to the difference between adjusted estimate for a subclass and unadjusted estimate. You can calculate for all estimates or for one specific variable. Below, we’re gonna calculate that for state variable - to find out in which state we have the most shrunk estimate:

# Calculate the difference between adjusted and unadjusted estimates for each state
states_df <- states_df %>%
  mutate(shrinkage_effect = sample_cces_estimate - mrp_estimate)

# Calculate the absolute difference to see the magnitude of shrinkage
states_df <- states_df %>%
  mutate(abs_shrinkage_effect = abs(shrinkage_effect))

# Identify the states with the most shrinkage effect (largest absolute difference)
states_df %>%
  arrange(desc(abs_shrinkage_effect)) %>%
  select(state, mrp_estimate, sample_cces_estimate, shrinkage_effect, abs_shrinkage_effect) %>%
  head(3)
#;-)   state mrp_estimate sample_cces_estimate shrinkage_effect abs_shrinkage_effect
#;-) 1    VT    0.4140674            0.7272727        0.3132054            0.3132054
#;-) 2    RI    0.3707830            0.1428571       -0.2279259            0.2279259
#;-) 3    MS    0.5428256            0.6923077        0.1494821            0.1494821

Looks like the answer is Vermont.

2. Random Effect vs Fixed Effect

We used the state variable as a random effect. What would it imply if we had used it as a fixed effect instead?

Answer

Random Effect: Random effects models incorporate partial pooling - where estimates for states with less data are “shrunk” towards the overall mean, borrowing strength from the entire dataset. This results in more stable estimates - especially for states with small sample sizes. Just like in the case of Vermont.

Fixed Effect: Fixed effects models do not allow for pooling across states. Each state’s effect is estimated independently, which can lead to unreliable estimates for states with small sample sizes due to high variance.

So we could have changed the model accordingly:

fit <- stan_glmer(
  abortion ~ state + (1 | eth) + (1 | educ) + male +
    (1 | male:eth) + (1 | educ:age) + (1 | educ:eth) +
    repvote + factor(region),
  family = binomial(link = "logit"),
  data = cces_df
)

3. Interpretation

Interpret the coefficient of the previous Republican vote variable from the Bayesian model output. Based on this coefficient value, how does it influence the outcome?

Answer

s <- summary(fit)[1:3, c(1:8)]
kableExtra::kable(s, format = "markdown")
mean mcse sd 10% 50% 90% n_eff Rhat
(Intercept) -1.0123274 0.0078918 0.3647464 -1.4706816 -1.0171482 -0.5401627 2136 1.0003073
male 0.3662283 0.0033355 0.1368470 0.2036286 0.3752859 0.5130264 1683 0.9998432
repvote 1.2217615 0.0099133 0.5275221 0.5528034 1.2197457 1.8924256 2832 1.0012010

So the estimate for republican vote’s effect is 1.221 and standard deviation is 0.53. The estimate’s + and - 2 sd (1.221 +-2 x 0.53) doesn’t include 0; so we can say that it’s statistically significant.

Since we used logistic regression, the result is not directly interpretable. It’s log odds, we can convert it to odds ratio at the very least:

exp(1.221)
#;-) [1] 3.390577

This implies that for each one-unit increase in repvote, the odds of supporting abortion increase by a factor of 3.39. In practical terms, states with higher previous Republican vote shares are significantly more likely to support abortion than those with lower shares.

You can also calculate the marginal effect to have a more straightforward interpretation in “probability” terms.

Alternatively, an even better interpretation comes from Lopez-Martin et al’s tutorial Introduction to Mister P - Case Studies:

“As the scale of repvote was between 0 and 1, this coefficient corresponds to the difference in probability of supporting the statement between someone that was in a state in which no one voted Republican to someone whose state voted all Republican. This is not reasonable, and therefore we start by dividing the median coefficient by 10. Doing this, we consider a difference of a 10% increase in Republican vote share. This means that we expect that someone from a state with a 55% Republican vote share has approximately (1.2 / 10) / 4 = 3% higher probability of supporting the statement relative to another individual with similar characteristics from a state in which Republicans received 45% of the vote.

Session info

sessionInfo()
#;-) R version 4.4.1 (2024-06-14)
#;-) Platform: aarch64-apple-darwin20
#;-) Running under: macOS Sonoma 14.1.1
#;-) 
#;-) Matrix products: default
#;-) BLAS:   /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib 
#;-) LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.0
#;-) 
#;-) locale:
#;-) [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#;-) 
#;-) time zone: Europe/Berlin
#;-) tzcode source: internal
#;-) 
#;-) attached base packages:
#;-) [1] stats     graphics  grDevices utils     datasets  methods   base     
#;-) 
#;-) other attached packages:
#;-)  [1] formatR_1.14        kableExtra_1.4.0    scales_1.3.0       
#;-)  [4] readr_2.1.5         stringr_1.5.1       reshape2_1.4.4     
#;-)  [7] tidyr_1.3.1         forcats_1.0.0       dplyr_1.1.4        
#;-) [10] data.table_1.16.0   rstanarm_2.32.1     rstan_2.32.6       
#;-) [13] StanHeaders_2.32.10 brms_2.21.0         Rcpp_1.0.13        
#;-) 
#;-) loaded via a namespace (and not attached):
#;-)   [1] gridExtra_2.3        inline_0.3.19        rlang_1.1.4         
#;-)   [4] magrittr_2.0.3       matrixStats_1.4.1    compiler_4.4.1      
#;-)   [7] loo_2.8.0            systemfonts_1.1.0    vctrs_0.6.5         
#;-)  [10] crayon_1.5.3         pkgconfig_2.0.3      fastmap_1.2.0       
#;-)  [13] backports_1.5.0      utf8_1.2.4           threejs_0.3.3       
#;-)  [16] promises_1.3.0       rmarkdown_2.28       markdown_1.13       
#;-)  [19] tzdb_0.4.0           nloptr_2.1.1         bit_4.5.0           
#;-)  [22] purrr_1.0.2          xfun_0.47            reprex_2.1.1        
#;-)  [25] jsonlite_1.8.9       later_1.3.2          styler_1.10.3       
#;-)  [28] parallel_4.4.1       R6_2.5.1             dygraphs_1.1.1.6    
#;-)  [31] stringi_1.8.4        boot_1.3-30          knitr_1.48          
#;-)  [34] zoo_1.8-12           base64enc_0.1-3      R.utils_2.12.3      
#;-)  [37] bayesplot_1.11.1     httpuv_1.6.15        Matrix_1.7-0        
#;-)  [40] splines_4.4.1        R.cache_0.16.0       igraph_2.0.3        
#;-)  [43] tidyselect_1.2.1     rstudioapi_0.16.0    abind_1.4-8         
#;-)  [46] yaml_2.3.10          codetools_0.2-20     miniUI_0.1.1.1      
#;-)  [49] curl_5.2.2           pkgbuild_1.4.4       lattice_0.22-6      
#;-)  [52] tibble_3.2.1         plyr_1.8.9           shiny_1.9.1         
#;-)  [55] withr_3.0.1          bridgesampling_1.1-2 posterior_1.6.0     
#;-)  [58] coda_0.19-4.1        evaluate_0.24.0      survival_3.6-4      
#;-)  [61] RcppParallel_5.1.9   xml2_1.3.6           xts_0.14.0          
#;-)  [64] pillar_1.9.0         tensorA_0.36.2.1     checkmate_2.3.2     
#;-)  [67] DT_0.33              stats4_4.4.1         shinyjs_2.1.0       
#;-)  [70] distributional_0.4.0 generics_0.1.3       vroom_1.6.5         
#;-)  [73] hms_1.1.3            ggplot2_3.5.1        rstantools_2.4.0    
#;-)  [76] munsell_0.5.1        minqa_1.2.8          gtools_3.9.5        
#;-)  [79] xtable_1.8-4         glue_1.7.0           tools_4.4.1         
#;-)  [82] shinystan_2.6.0      lme4_1.1-35.5        colourpicker_1.3.0  
#;-)  [85] fs_1.6.4             mvtnorm_1.3-1        grid_4.4.1          
#;-)  [88] QuickJSR_1.3.1       crosstalk_1.2.1      colorspace_2.1-1    
#;-)  [91] nlme_3.1-164         cli_3.6.3            fansi_1.0.6         
#;-)  [94] viridisLite_0.4.2    svglite_2.1.3        Brobdingnag_1.2-9   
#;-)  [97] V8_5.0.0             gtable_0.3.5         R.methodsS3_1.8.2   
#;-) [100] digest_0.6.37        htmlwidgets_1.6.4    htmltools_0.5.8.1   
#;-) [103] R.oo_1.26.0          lifecycle_1.0.4      mime_0.12           
#;-) [106] bit64_4.5.2          shinythemes_1.2.0    MASS_7.3-61