Fitting a shared parameter joint model for longitudinal and time-to-event data with brms

I have been trying to figure out the equivalent syntax for rstanarm::stan_jm in brms as I’m more confident in my ability to modify brms programs than I am with rstanarm . I’ve been able to get syntax that works, but returns very different results, suggesting that the brms implementation is doing something different (or incorrectly).

The stan_jm model is:

f1 <- stan_jm(formulaLong = logBili ~ year + (1 | id), 
              dataLong = pbcLong,
              formulaEvent = Surv(futimeYears, death) ~ sex + trt, 
              dataEvent = pbcSurv,
              time_var = "year",
              # this next line is only to keep the example small in size!
              chains = 1, cores = 1, seed = 12345, iter = 1000, basehaz = "weibull")

My attempt at a brms implementation (based on an embarrassing amount of asking chatGPT):

#combine the pbcLong and pbcSurve data into a single dataframe for brms
tst <- merge(pbcLong, pbcSurv)

brms_joint <- brm(
  formula = bf(logBili ~ year + (1 | id)) +    # Longitudinal model for log(bili)
    bf(futimeYears | cens(1 - status) ~ sex +trt, family = weibull()),  # Survival model using Weibull distribution
  data = tst,
  chains = 2, cores = 2, iter = 3000, seed = 12345,
  prior = prior,
  control = list(adapt_delta = 0.95)
)

I can’t tell whether the syntax in the brms model is using a different association structure (or how I would change that). Or perhaps it is not possible to fit such a model in brms (maybe @Solomon has already tried this)? The results of the two models are not just numerically different, but would lead to substantially different conclusions.

Thanks for any suggestions ou can give.

  • Operating System: MacOS Sonoma 14.7.2
  • brms Version:2.22.0
sessionInfo(package = NULL)
R version 4.4.0 (2024-04-24)
Platform: x86_64-apple-darwin20
Running under: macOS Sonoma 14.7.2

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib 
LAPACK: /Library/Frameworks/R.framework/Versions/4.4-x86_64/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: America/Boise
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] rstanarm_2.32.1 survival_3.5-8  brms_2.22.0     Rcpp_1.0.13    

loaded via a namespace (and not attached):
 [1] tidyselect_1.2.1     dplyr_1.1.4          loo_2.8.0            fastmap_1.2.0       
 [5] tensorA_0.36.2.1     shinystan_2.6.0      promises_1.3.0       shinyjs_2.1.0       
 [9] digest_0.6.37        mime_0.12            lifecycle_1.0.4      StanHeaders_2.32.10 
[13] processx_3.8.4       magrittr_2.0.3       posterior_1.6.0      compiler_4.4.0      
[17] rlang_1.1.5          tools_4.4.0          igraph_2.1.1         utf8_1.2.4          
[21] data.table_1.15.4    bridgesampling_1.1-2 htmlwidgets_1.6.4    pkgbuild_1.4.4      
[25] curl_5.2.3           plyr_1.8.9           dygraphs_1.1.1.6     pkgload_1.3.4       
[29] abind_1.4-8          miniUI_0.1.1.1       grid_4.4.0           stats4_4.4.0        
[33] fansi_1.0.6          xts_0.14.0           xtable_1.8-4         colorspace_2.1-1    
[37] inline_0.3.19        ggplot2_3.5.1        MASS_7.3-60.2        scales_1.3.0        
[41] gtools_3.9.5         cli_3.6.4            mvtnorm_1.2-5        generics_0.1.3      
[45] RcppParallel_5.1.9   rstudioapi_0.16.0    reshape2_1.4.4       minqa_1.2.8         
[49] rstan_2.32.7         stringr_1.5.1        shinythemes_1.2.0    splines_4.4.0       
[53] bayesplot_1.11.1     parallel_4.4.0       matrixStats_1.4.1    base64enc_0.1-3     
[57] vctrs_0.6.5          boot_1.3-30          V8_4.4.2             Matrix_1.7-0        
[61] jsonlite_1.8.9       callr_3.7.6          crosstalk_1.2.1      glue_1.8.0          
[65] nloptr_2.1.1         codetools_0.2-20     ps_1.8.0             DT_0.33             
[69] distributional_0.5.0 stringi_1.8.4        gtable_0.3.6         later_1.3.2         
[73] QuickJSR_1.3.1       lme4_1.1-35.5        munsell_0.5.1        tibble_3.2.1        
[77] colourpicker_1.3.0   pillar_1.9.0         htmltools_0.5.8.1    Brobdingnag_1.2-9   
[81] R6_2.5.1             shiny_1.9.1          lattice_0.22-6       markdown_1.13       
[85] backports_1.5.0      threejs_0.3.3        httpuv_1.6.15        rstantools_2.4.0    
[89] coda_0.19-4.1        gridExtra_2.3        nlme_3.1-164         checkmate_2.3.2     
[93] zoo_1.8-12           pkgconfig_2.0.3 

Sorry, I’m of no help here. I’ve never used rstanarm::stan_jm(), and I’m not familiar with joint models for longitudinal and time-to-event data. Sounds cool, though.

Thanks @Solomon, maybe @paul.buerkner or @sambrilleman has some advice here?

Maybe inspect the resulting stan code for either implementation? That might clarify if the model structures are actually different.
I’m also wondering if default priors differ between brm and stan_jm, leading you to different results.