BCVA data comparison between Bayesian and frequentist MMRMs
27/03/2024
Source:vignettes/bcva.Rmd
bcva.Rmd
About
This vignette uses the bcva_data
dataset from the
mmrm
package to compare a Bayesian MMRM fit, obtained by
brms.mmrm::brm_model()
, and a frequentist MMRM fit,
obtained by mmrm::mmrm()
. An overview of parameter
estimates and differences by type of MMRM is given in the summary (Tables 4 and 5) at the end.
Prerequisites
This comparison workflow requires the following packages.
> packages <- c(
+ "dplyr",
+ "tidyr",
+ "ggplot2",
+ "gt",
+ "gtsummary",
+ "purrr",
+ "parallel",
+ "brms.mmrm",
+ "mmrm",
+ "emmeans",
+ "posterior"
+ )
> invisible(lapply(packages, library, character.only = TRUE))
We set a seed for the random number generator to ensure statistical reproducibility.
Data
Pre-processing
This analysis exercise uses the bcva_data
dataset
contained in the mmrm
package:
According to https://openpharma.github.io/mmrm/latest-tag/articles/mmrm_review_methods.html:
The BCVA dataset contains data from a randomized longitudinal ophthalmology trial evaluating the change in baseline corrected visual acuity (BCVA) over the course of 10 visits. BCVA corresponds to the number of letters read from a visual acuity chart.
The dataset is a tibble
with 800 rows and 7 variables.
The primary endpoint for the analysis is BCVA_CHG
.
-
USUBJID
(subject ID) -
AVISITN
(visit number, numeric) -
AVISIT
(visit number, factor) -
ARMCD
(treatment,TRT
orCTL
) -
RACE
(3-category race) -
BCVA_BL
(BCVA at baseline) -
BCVA_CHG
(BCVA change from baseline)
The rest of the pre-processing steps create factors for the study arm
and visit and apply the usual checking and standardization steps of
brms.mmrm::brm_data()
.
> bcva_data <- brm_data(
+ data = bcva_data,
+ outcome = "BCVA_CHG",
+ role = "change",
+ group = "ARMCD",
+ time = "AVISIT",
+ patient = "USUBJID",
+ baseline = "BCVA_BL",
+ reference_group = "CTL",
+ covariates = "RACE"
+ ) |>
+ mutate(ARMCD = factor(ARMCD), AVISIT = factor(AVISIT))
The following table shows the first rows of the dataset.
> head(bcva_data) |>
+ gt() |>
+ tab_caption(caption = md("Table 1. First rows of the pre-processed `bcva_data` dataset."))
BCVA_CHG | BCVA_BL | ARMCD | AVISIT | USUBJID | RACE |
---|---|---|---|---|---|
5.058546 | 71.70881 | CTL | VIS01 | 3 | Asian |
4.018582 | 71.70881 | CTL | VIS02 | 3 | Asian |
3.572535 | 71.70881 | CTL | VIS03 | 3 | Asian |
4.822669 | 71.70881 | CTL | VIS04 | 3 | Asian |
7.348768 | 71.70881 | CTL | VIS05 | 3 | Asian |
6.076615 | 71.70881 | CTL | VIS06 | 3 | Asian |
Descriptive statistics
Table of baseline characteristics:
> bcva_data |>
+ select(ARMCD, USUBJID, RACE, BCVA_BL) |>
+ distinct() |>
+ select(-USUBJID) |>
+ tbl_summary(
+ by = c(ARMCD),
+ statistic = list(
+ all_continuous() ~ "{mean} ({sd})",
+ all_categorical() ~ "{n} / {N} ({p}%)"
+ )
+ ) |>
+ modify_caption("Table 2. Baseline characteristics.")
Characteristic | CTL, N = 4941 | TRT, N = 5061 |
---|---|---|
RACE | ||
Asian | 151 / 494 (31%) | 146 / 506 (29%) |
Black | 149 / 494 (30%) | 168 / 506 (33%) |
White | 194 / 494 (39%) | 192 / 506 (38%) |
BCVA_BL | 75 (10) | 75 (10) |
1 n / N (%); Mean (SD) |
Table of change from baseline in BCVA over 52 weeks:
> bcva_data |>
+ pull(AVISIT) |>
+ unique() |>
+ sort() |>
+ purrr::map(
+ .f = ~ bcva_data |>
+ filter(AVISIT %in% .x) |>
+ tbl_summary(
+ by = ARMCD,
+ include = BCVA_CHG,
+ type = BCVA_CHG ~ "continuous2",
+ statistic = BCVA_CHG ~ c(
+ "{mean} ({sd})",
+ "{median} ({p25}, {p75})",
+ "{min}, {max}"
+ ),
+ label = list(BCVA_CHG = paste("Visit ", .x))
+ )
+ ) |>
+ tbl_stack(quiet = TRUE) |>
+ modify_caption("Table 3. Change from baseline.")
Characteristic | CTL, N = 494 | TRT, N = 506 |
---|---|---|
Visit VIS01 | ||
Mean (SD) | 5.32 (1.23) | 5.86 (1.33) |
Median (IQR) | 5.34 (4.51, 6.17) | 5.86 (4.98, 6.81) |
Range | 1.83, 9.02 | 2.28, 10.30 |
Unknown | 12 | 5 |
Visit VIS02 | ||
Mean (SD) | 5.59 (1.49) | 6.33 (1.45) |
Median (IQR) | 5.53 (4.64, 6.47) | 6.36 (5.34, 7.31) |
Range | 0.29, 10.15 | 2.35, 10.75 |
Unknown | 13 | 7 |
Visit VIS03 | ||
Mean (SD) | 5.79 (1.61) | 6.79 (1.71) |
Median (IQR) | 5.73 (4.64, 6.89) | 6.82 (5.66, 7.93) |
Range | 1.53, 11.46 | 1.13, 11.49 |
Unknown | 23 | 17 |
Visit VIS04 | ||
Mean (SD) | 6.18 (1.73) | 7.29 (1.82) |
Median (IQR) | 6.14 (5.05, 7.40) | 7.24 (6.06, 8.54) |
Range | 0.45, 11.49 | 2.07, 11.47 |
Unknown | 36 | 18 |
Visit VIS05 | ||
Mean (SD) | 6.28 (1.97) | 7.68 (1.94) |
Median (IQR) | 6.18 (4.96, 7.71) | 7.75 (6.48, 8.93) |
Range | 0.87, 11.53 | 2.24, 14.10 |
Unknown | 40 | 35 |
Visit VIS06 | ||
Mean (SD) | 6.69 (1.97) | 8.31 (1.98) |
Median (IQR) | 6.64 (5.26, 8.14) | 8.29 (6.92, 9.73) |
Range | 1.35, 12.95 | 1.93, 14.38 |
Unknown | 84 | 48 |
Visit VIS07 | ||
Mean (SD) | 6.78 (2.09) | 8.78 (2.11) |
Median (IQR) | 6.91 (5.46, 8.29) | 8.67 (7.44, 10.25) |
Range | -1.54, 11.99 | 3.21, 14.36 |
Unknown | 106 | 78 |
Visit VIS08 | ||
Mean (SD) | 7.08 (2.25) | 9.40 (2.26) |
Median (IQR) | 7.08 (5.57, 8.67) | 9.35 (7.96, 10.86) |
Range | 0.97, 13.71 | 2.28, 15.95 |
Unknown | 123 | 86 |
Visit VIS09 | ||
Mean (SD) | 7.39 (2.33) | 10.01 (2.50) |
Median (IQR) | 7.47 (5.77, 9.05) | 10.01 (8.19, 11.73) |
Range | 0.04, 14.61 | 4.22, 18.09 |
Unknown | 167 | 114 |
Visit VIS10 | ||
Mean (SD) | 7.49 (2.58) | 10.59 (2.36) |
Median (IQR) | 7.40 (5.73, 9.01) | 10.71 (9.03, 12.24) |
Range | -0.08, 15.75 | 3.24, 16.40 |
Unknown | 213 | 170 |
The following figure shows the primary endpoint over the four study visits in the data.
> bcva_data |>
+ group_by(ARMCD) |>
+ ggplot(aes(x = AVISIT, y = BCVA_CHG, fill = factor(ARMCD))) +
+ geom_hline(yintercept = 0, col = "grey", linewidth = 1.2) +
+ geom_boxplot(na.rm = TRUE) +
+ labs(
+ x = "Visit",
+ y = "Change from baseline in BCVA",
+ fill = "Treatment"
+ ) +
+ scale_fill_manual(values = c("darkgoldenrod2", "coral2")) +
+ theme_bw()
Fitting MMRMs
Bayesian model
The formula for the Bayesian model includes additive effects for baseline, study visit, race, and study-arm-by-visit interaction.
> b_mmrm_formula <- brm_formula(
+ data = bcva_data,
+ intercept = TRUE,
+ baseline = TRUE,
+ group = FALSE,
+ time = TRUE,
+ baseline_time = FALSE,
+ group_time = TRUE,
+ correlation = "unstructured"
+ )
> print(b_mmrm_formula)
#> BCVA_CHG ~ BCVA_BL + ARMCD:AVISIT + AVISIT + RACE + unstr(time = AVISIT, gr = USUBJID)
#> sigma ~ 0 + AVISIT
We fit the model using brms.mmrm::brm_model()
. The
computation takes several minutes because of the size of the dataset. To
ensure a good basis of comparison with the frequentist model, we put an
extremely diffuse prior on the intercept. The parameters already have
diffuse flexible priors by default.
> b_mmrm_fit <- brm_model(
+ data = filter(bcva_data, !is.na(BCVA_CHG)),
+ formula = b_mmrm_formula,
+ prior = brms::prior(class = "Intercept", prior = "student_t(3, 0, 1000)"),
+ iter = 10000,
+ warmup = 2000,
+ chains = 4,
+ cores = 4,
+ refresh = 0
+ )
Here is a posterior summary of model parameters, including fixed effects and pairwise correlation among visits within patients.
> summary(b_mmrm_fit)
#> Family: gaussian
#> Links: mu = identity; sigma = log
#> Formula: BCVA_CHG ~ BCVA_BL + ARMCD:AVISIT + AVISIT + RACE + unstr(time = AVISIT, gr = USUBJID)
#> sigma ~ 0 + AVISIT
#> Data: data[!is.na(data[[attr(data, "brm_outcome")]]), ] (Number of observations: 8605)
#> Draws: 4 chains, each with iter = 10000; warmup = 2000; thin = 1;
#> total post-warmup draws = 32000
#>
#> Correlation Structures:
#> Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
#> cortime(VIS01,VIS02) 0.05 0.03 -0.01 0.11 1.00 64232 23380
#> cortime(VIS01,VIS03) 0.31 0.03 0.25 0.37 1.00 63974 26624
#> cortime(VIS02,VIS03) 0.05 0.03 -0.02 0.11 1.00 70110 24587
#> cortime(VIS01,VIS04) 0.21 0.03 0.15 0.27 1.00 42555 26079
#> cortime(VIS02,VIS04) 0.13 0.03 0.07 0.20 1.00 50575 25891
#> cortime(VIS03,VIS04) -0.01 0.03 -0.07 0.05 1.00 50372 25192
#> cortime(VIS01,VIS05) 0.17 0.03 0.11 0.23 1.00 44730 27906
#> cortime(VIS02,VIS05) 0.12 0.03 0.05 0.18 1.00 50419 27572
#> cortime(VIS03,VIS05) -0.01 0.03 -0.07 0.06 1.00 53185 27533
#> cortime(VIS04,VIS05) 0.38 0.03 0.32 0.43 1.00 50371 27017
#> cortime(VIS01,VIS06) 0.26 0.03 0.20 0.32 1.00 41105 27790
#> cortime(VIS02,VIS06) 0.20 0.03 0.14 0.27 1.00 46110 26785
#> cortime(VIS03,VIS06) 0.04 0.03 -0.02 0.11 1.00 50559 27215
#> cortime(VIS04,VIS06) 0.40 0.03 0.35 0.46 1.00 51210 27168
#> cortime(VIS05,VIS06) 0.39 0.03 0.33 0.45 1.00 54492 24829
#> cortime(VIS01,VIS07) 0.07 0.04 -0.00 0.13 1.00 64797 24890
#> cortime(VIS02,VIS07) 0.09 0.03 0.02 0.15 1.00 66962 24910
#> cortime(VIS03,VIS07) -0.00 0.04 -0.07 0.07 1.00 61101 24110
#> cortime(VIS04,VIS07) 0.15 0.03 0.08 0.21 1.00 62311 22787
#> cortime(VIS05,VIS07) 0.19 0.03 0.13 0.26 1.00 62582 24390
#> cortime(VIS06,VIS07) 0.21 0.04 0.14 0.28 1.00 68580 24400
#> cortime(VIS01,VIS08) 0.05 0.04 -0.02 0.12 1.00 66066 23819
#> cortime(VIS02,VIS08) 0.10 0.04 0.03 0.17 1.00 69331 24606
#> cortime(VIS03,VIS08) -0.03 0.04 -0.10 0.04 1.00 65051 23999
#> cortime(VIS04,VIS08) 0.17 0.03 0.10 0.24 1.00 70470 24091
#> cortime(VIS05,VIS08) 0.17 0.04 0.10 0.24 1.00 72172 24032
#> cortime(VIS06,VIS08) 0.16 0.04 0.09 0.23 1.00 68767 24574
#> cortime(VIS07,VIS08) 0.05 0.04 -0.02 0.13 1.00 68724 22432
#> cortime(VIS01,VIS09) 0.03 0.04 -0.04 0.10 1.00 70365 23435
#> cortime(VIS02,VIS09) -0.01 0.04 -0.08 0.07 1.00 67029 24108
#> cortime(VIS03,VIS09) -0.04 0.04 -0.12 0.03 1.00 65481 22947
#> cortime(VIS04,VIS09) 0.12 0.04 0.04 0.19 1.00 70778 24290
#> cortime(VIS05,VIS09) 0.09 0.04 0.01 0.16 1.00 67795 23738
#> cortime(VIS06,VIS09) 0.17 0.04 0.09 0.24 1.00 68382 23236
#> cortime(VIS07,VIS09) 0.02 0.04 -0.06 0.09 1.00 60320 23116
#> cortime(VIS08,VIS09) 0.06 0.04 -0.02 0.14 1.00 66326 24022
#> cortime(VIS01,VIS10) 0.02 0.04 -0.06 0.10 1.00 56720 25693
#> cortime(VIS02,VIS10) 0.13 0.04 0.05 0.20 1.00 57584 25219
#> cortime(VIS03,VIS10) 0.02 0.04 -0.06 0.10 1.00 60710 25228
#> cortime(VIS04,VIS10) 0.31 0.04 0.24 0.38 1.00 56727 25218
#> cortime(VIS05,VIS10) 0.24 0.04 0.16 0.31 1.00 63407 25064
#> cortime(VIS06,VIS10) 0.30 0.04 0.22 0.37 1.00 59518 24562
#> cortime(VIS07,VIS10) 0.06 0.04 -0.03 0.15 1.00 68160 23806
#> cortime(VIS08,VIS10) 0.09 0.04 0.01 0.18 1.00 71536 24639
#> cortime(VIS09,VIS10) 0.08 0.05 -0.01 0.17 1.00 72879 23828
#>
#> Population-Level Effects:
#> Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
#> Intercept 4.29 0.17 3.95 4.62 1.00 52968 23424
#> BCVA_BL -0.00 0.00 -0.01 0.00 1.00 55733 22421
#> AVISITVIS02 0.28 0.07 0.14 0.42 1.00 29523 26038
#> AVISITVIS03 0.46 0.07 0.33 0.59 1.00 43908 25273
#> AVISITVIS04 0.86 0.08 0.71 1.01 1.00 27128 26680
#> AVISITVIS05 0.97 0.09 0.80 1.14 1.00 27041 26249
#> AVISITVIS06 1.34 0.09 1.17 1.51 1.00 28423 26075
#> AVISITVIS07 1.42 0.11 1.21 1.63 1.00 33236 26105
#> AVISITVIS08 1.71 0.12 1.49 1.94 1.00 33031 26727
#> AVISITVIS09 2.00 0.13 1.75 2.25 1.00 37527 27192
#> AVISITVIS10 2.10 0.14 1.82 2.38 1.00 31905 25606
#> RACEBlack 1.04 0.06 0.93 1.15 1.00 50375 27044
#> RACEWhite 2.01 0.05 1.90 2.11 1.00 48898 25367
#> AVISITVIS01:ARMCDTRT 0.54 0.06 0.42 0.66 1.00 33402 25937
#> AVISITVIS02:ARMCDTRT 0.73 0.08 0.57 0.88 1.00 45687 26156
#> AVISITVIS03:ARMCDTRT 1.01 0.09 0.83 1.19 1.00 44466 25516
#> AVISITVIS04:ARMCDTRT 1.10 0.10 0.91 1.30 1.00 35139 25412
#> AVISITVIS05:ARMCDTRT 1.38 0.11 1.16 1.61 1.00 34453 27482
#> AVISITVIS06:ARMCDTRT 1.63 0.12 1.39 1.86 1.00 34605 26525
#> AVISITVIS07:ARMCDTRT 2.02 0.14 1.74 2.29 1.00 42883 25319
#> AVISITVIS08:ARMCDTRT 2.35 0.15 2.05 2.64 1.00 42545 25257
#> AVISITVIS09:ARMCDTRT 2.66 0.17 2.33 2.98 1.00 42305 25539
#> AVISITVIS10:ARMCDTRT 3.07 0.18 2.72 3.43 1.00 39524 25368
#> sigma_AVISITVIS01 -0.01 0.02 -0.05 0.03 1.00 62714 25549
#> sigma_AVISITVIS02 0.23 0.02 0.18 0.27 1.00 70306 23424
#> sigma_AVISITVIS03 0.36 0.02 0.31 0.40 1.00 65928 25658
#> sigma_AVISITVIS04 0.44 0.02 0.40 0.49 1.00 54413 26689
#> sigma_AVISITVIS05 0.57 0.02 0.52 0.61 1.00 62557 26764
#> sigma_AVISITVIS06 0.58 0.02 0.53 0.63 1.00 53370 26108
#> sigma_AVISITVIS07 0.69 0.03 0.64 0.74 1.00 71710 24191
#> sigma_AVISITVIS08 0.74 0.03 0.69 0.79 1.00 74050 24224
#> sigma_AVISITVIS09 0.80 0.03 0.75 0.85 1.00 75622 23406
#> sigma_AVISITVIS10 0.84 0.03 0.79 0.90 1.00 63708 25100
#>
#> Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
#> and Tail_ESS are effective sample size measures, and Rhat is the potential
#> scale reduction factor on split chains (at convergence, Rhat = 1).
Frequentist model
The formula for the frequentist model is the same, except for the different syntax for specifying the covariance structure of the MMRM. We fit the model below.
> f_mmrm_fit <- mmrm::mmrm(
+ formula = BCVA_CHG ~ BCVA_BL + ARMCD:AVISIT + AVISIT + RACE +
+ us(AVISIT | USUBJID),
+ data = bcva_data
+ )
The parameter summaries of the frequentist model are below.
> summary(f_mmrm_fit)
#> mmrm fit
#>
#> Formula: BCVA_CHG ~ BCVA_BL + ARMCD:AVISIT + AVISIT + RACE + us(AVISIT |
#> USUBJID)
#> Data: bcva_data (used 8605 observations from 1000 subjects with maximum 10
#> timepoints)
#> Covariance: unstructured (55 variance parameters)
#> Method: Satterthwaite
#> Vcov Method: Asymptotic
#> Inference: REML
#>
#> Model selection criteria:
#> AIC BIC logLik deviance
#> 32181.0 32451.0 -16035.5 32071.0
#>
#> Coefficients:
#> Estimate Std. Error df t value Pr(>|t|)
#> (Intercept) 4.288e+00 1.709e-01 1.065e+03 25.085 < 2e-16 ***
#> BCVA_BL -9.934e-04 2.156e-03 9.905e+02 -0.461 0.645
#> AVISITVIS02 2.810e-01 7.067e-02 9.995e+02 3.976 7.51e-05 ***
#> AVISITVIS03 4.573e-01 6.716e-02 9.747e+02 6.809 1.71e-11 ***
#> AVISITVIS04 8.570e-01 7.636e-02 9.796e+02 11.222 < 2e-16 ***
#> AVISITVIS05 9.638e-01 8.634e-02 9.630e+02 11.163 < 2e-16 ***
#> AVISITVIS06 1.334e+00 8.650e-02 9.450e+02 15.421 < 2e-16 ***
#> AVISITVIS07 1.417e+00 1.071e-01 8.698e+02 13.233 < 2e-16 ***
#> AVISITVIS08 1.711e+00 1.145e-01 8.467e+02 14.944 < 2e-16 ***
#> AVISITVIS09 1.996e+00 1.283e-01 7.784e+02 15.549 < 2e-16 ***
#> AVISITVIS10 2.101e+00 1.400e-01 7.025e+02 15.003 < 2e-16 ***
#> RACEBlack 1.038e+00 5.496e-02 1.011e+03 18.891 < 2e-16 ***
#> RACEWhite 2.005e+00 5.198e-02 9.768e+02 38.573 < 2e-16 ***
#> AVISITVIS01:ARMCDTRT 5.391e-01 6.282e-02 9.859e+02 8.582 < 2e-16 ***
#> AVISITVIS02:ARMCDTRT 7.248e-01 7.984e-02 9.804e+02 9.078 < 2e-16 ***
#> AVISITVIS03:ARMCDTRT 1.012e+00 9.163e-02 9.638e+02 11.039 < 2e-16 ***
#> AVISITVIS04:ARMCDTRT 1.104e+00 1.004e-01 9.653e+02 11.003 < 2e-16 ***
#> AVISITVIS05:ARMCDTRT 1.383e+00 1.147e-01 9.505e+02 12.065 < 2e-16 ***
#> AVISITVIS06:ARMCDTRT 1.630e+00 1.189e-01 9.157e+02 13.714 < 2e-16 ***
#> AVISITVIS07:ARMCDTRT 2.016e+00 1.382e-01 8.262e+02 14.592 < 2e-16 ***
#> AVISITVIS08:ARMCDTRT 2.347e+00 1.474e-01 8.041e+02 15.924 < 2e-16 ***
#> AVISITVIS09:ARMCDTRT 2.658e+00 1.644e-01 7.277e+02 16.172 < 2e-16 ***
#> AVISITVIS10:ARMCDTRT 3.072e+00 1.815e-01 6.620e+02 16.929 < 2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Covariance estimate:
#> VIS01 VIS02 VIS03 VIS04 VIS05 VIS06 VIS07 VIS08 VIS09 VIS10
#> VIS01 0.9713 0.0630 0.4371 0.3315 0.3056 0.4688 0.1325 0.1020 0.0611 0.0587
#> VIS02 0.0630 1.5618 0.0871 0.2685 0.2635 0.4637 0.2181 0.2777 -0.0153 0.3761
#> VIS03 0.4371 0.0871 2.0221 -0.0216 -0.0190 0.1102 -0.0048 -0.0993 -0.1322 0.0719
#> VIS04 0.3315 0.2685 -0.0216 2.4114 1.0476 1.1410 0.4626 0.5660 0.4085 1.1479
#> VIS05 0.3056 0.2635 -0.0190 1.0476 3.0916 1.2594 0.6910 0.6308 0.3594 0.9999
#> VIS06 0.4688 0.4637 0.1102 1.1410 1.2594 3.1853 0.7541 0.6094 0.6823 1.2559
#> VIS07 0.1325 0.2181 -0.0048 0.4626 0.6910 0.7541 3.9273 0.2306 0.0723 0.3020
#> VIS08 0.1020 0.2777 -0.0993 0.5660 0.6308 0.6094 0.2306 4.3272 0.2683 0.4660
#> VIS09 0.0611 -0.0153 -0.1322 0.4085 0.3594 0.6823 0.0723 0.2683 4.8635 0.4140
#> VIS10 0.0587 0.3761 0.0719 1.1479 0.9999 1.2559 0.3020 0.4660 0.4140 5.3520
Comparison
This section compares the Bayesian posterior parameter estimates from
brms.mmrm
to the frequentist parameter estimates of the
mmrm
package.
Extract estimates from Bayesian model
We extract and standardize the Bayesian estimates.
> b_mmrm_draws <- b_mmrm_fit |>
+ as_draws_df()
> visit_levels <- sort(unique(as.character(bcva_data$AVISIT)))
> for (level in visit_levels) {
+ name <- paste0("b_sigma_AVISIT", level)
+ b_mmrm_draws[[name]] <- exp(b_mmrm_draws[[name]])
+ }
> b_mmrm_summary <- b_mmrm_draws |>
+ summarize_draws() |>
+ select(variable, mean, sd) |>
+ filter(!(variable %in% c("lprior", "lp__"))) |>
+ rename(bayes_estimate = mean, bayes_se = sd) |>
+ mutate(
+ variable = variable |>
+ tolower() |>
+ gsub(pattern = "b_", replacement = "") |>
+ gsub(pattern = "b_sigma_AVISIT", replacement = "sigma_") |>
+ gsub(pattern = "cortime", replacement = "correlation") |>
+ gsub(pattern = "__", replacement = "_")
+ )
Extract estimates from frequentist model
We extract and standardize the frequentist estimates.
> f_mmrm_fixed <- summary(f_mmrm_fit)$coefficients |>
+ as_tibble(rownames = "variable") |>
+ mutate(variable = tolower(variable)) |>
+ mutate(variable = gsub("(", "", variable, fixed = TRUE)) |>
+ mutate(variable = gsub(")", "", variable, fixed = TRUE)) |>
+ rename(freq_estimate = Estimate, freq_se = `Std. Error`) |>
+ select(variable, freq_estimate, freq_se)
> f_mmrm_variance <- tibble(
+ variable = paste0("sigma_AVISIT", visit_levels) |> tolower(),
+ freq_estimate = sqrt(diag(f_mmrm_fit$cov))
+ )
> f_diagonal_factor <- diag(1 / sqrt(diag(f_mmrm_fit$cov)))
> f_corr_matrix <- f_diagonal_factor %*% f_mmrm_fit$cov %*% f_diagonal_factor
> colnames(f_corr_matrix) <- visit_levels
> f_mmrm_correlation <- f_corr_matrix |>
+ as.data.frame() |>
+ as_tibble() |>
+ mutate(x1 = visit_levels) |>
+ pivot_longer(
+ cols = -any_of("x1"),
+ names_to = "x2",
+ values_to = "freq_estimate"
+ ) |>
+ filter(
+ as.numeric(gsub("[^0-9]", "", x1)) < as.numeric(gsub("[^0-9]", "", x2))
+ ) |>
+ mutate(variable = sprintf("correlation_%s_%s", x1, x2)) |>
+ select(variable, freq_estimate)
Summary
The first table below summarizes the parameter estimates from each model and the differences between estimates (Bayesian minus frequentist). The second table shows the standard errors of these estimates and differences between standard errors. In each table, the “Relative” column shows the relative difference (the difference divided by the frequentist quantity).
Because of the different statistical paradigms and estimation
procedures, especially regarding the covariance parameters, it would not
be realistic to expect the Bayesian and frequentist approaches to yield
virtually identical results. Nevertheless, the absolute and relative
differences in the table below show strong agreement between
brms.mmrm
and mmrm
.
> b_f_comparison <- full_join(
+ x = b_mmrm_summary,
+ y = f_mmrm_summary,
+ by = "variable"
+ ) |>
+ mutate(
+ diff_estimate = bayes_estimate - freq_estimate,
+ diff_relative_estimate = diff_estimate / freq_estimate,
+ diff_se = bayes_se - freq_se,
+ diff_relative_se = diff_se / freq_se
+ ) |>
+ select(variable, ends_with("estimate"), ends_with("se"))
> table_estimates <- b_f_comparison |>
+ select(variable, ends_with("estimate"))
> gt(table_estimates) |>
+ fmt_number(decimals = 4) |>
+ tab_caption(
+ caption = md(
+ paste(
+ "Table 4. Comparison of parameter estimates between",
+ "Bayesian and frequentist MMRMs."
+ )
+ )
+ ) |>
+ cols_label(
+ variable = "Variable",
+ bayes_estimate = "Bayesian",
+ freq_estimate = "Frequentist",
+ diff_estimate = "Difference",
+ diff_relative_estimate = "Relative"
+ )
Variable | Bayesian | Frequentist | Difference | Relative |
---|---|---|---|---|
intercept | 4.2871 | 4.2881 | −0.0009 | −0.0002 |
bcva_bl | −0.0010 | −0.0010 | 0.0000 | −0.0005 |
avisitvis02 | 0.2814 | 0.2810 | 0.0004 | 0.0015 |
avisitvis03 | 0.4579 | 0.4573 | 0.0006 | 0.0013 |
avisitvis04 | 0.8578 | 0.8570 | 0.0008 | 0.0010 |
avisitvis05 | 0.9656 | 0.9638 | 0.0018 | 0.0019 |
avisitvis06 | 1.3353 | 1.3339 | 0.0014 | 0.0010 |
avisitvis07 | 1.4179 | 1.4167 | 0.0012 | 0.0008 |
avisitvis08 | 1.7125 | 1.7107 | 0.0017 | 0.0010 |
avisitvis09 | 1.9965 | 1.9956 | 0.0009 | 0.0005 |
avisitvis10 | 2.1011 | 2.1005 | 0.0006 | 0.0003 |
raceblack | 1.0386 | 1.0382 | 0.0003 | 0.0003 |
racewhite | 2.0056 | 2.0051 | 0.0005 | 0.0003 |
avisitvis01:armcdtrt | 0.5403 | 0.5391 | 0.0012 | 0.0023 |
avisitvis02:armcdtrt | 0.7254 | 0.7248 | 0.0006 | 0.0009 |
avisitvis03:armcdtrt | 1.0122 | 1.0115 | 0.0007 | 0.0007 |
avisitvis04:armcdtrt | 1.1041 | 1.1042 | 0.0000 | 0.0000 |
avisitvis05:armcdtrt | 1.3828 | 1.3834 | −0.0006 | −0.0004 |
avisitvis06:armcdtrt | 1.6290 | 1.6301 | −0.0011 | −0.0007 |
avisitvis07:armcdtrt | 2.0165 | 2.0160 | 0.0006 | 0.0003 |
avisitvis08:armcdtrt | 2.3460 | 2.3469 | −0.0010 | −0.0004 |
avisitvis09:armcdtrt | 2.6583 | 2.6585 | −0.0002 | −0.0001 |
avisitvis10:armcdtrt | 3.0728 | 3.0723 | 0.0005 | 0.0002 |
sigma_avisitvis01 | 0.9895 | 0.9855 | 0.0039 | 0.0040 |
sigma_avisitvis02 | 1.2557 | 1.2497 | 0.0060 | 0.0048 |
sigma_avisitvis03 | 1.4289 | 1.4220 | 0.0068 | 0.0048 |
sigma_avisitvis04 | 1.5569 | 1.5529 | 0.0040 | 0.0026 |
sigma_avisitvis05 | 1.7632 | 1.7583 | 0.0049 | 0.0028 |
sigma_avisitvis06 | 1.7883 | 1.7847 | 0.0036 | 0.0020 |
sigma_avisitvis07 | 1.9930 | 1.9817 | 0.0112 | 0.0057 |
sigma_avisitvis08 | 2.0924 | 2.0802 | 0.0122 | 0.0058 |
sigma_avisitvis09 | 2.2203 | 2.2053 | 0.0150 | 0.0068 |
sigma_avisitvis10 | 2.3283 | 2.3134 | 0.0149 | 0.0064 |
correlation_vis01_vis02 | 0.0493 | 0.0512 | −0.0019 | −0.0367 |
correlation_vis01_vis03 | 0.3086 | 0.3119 | −0.0033 | −0.0107 |
correlation_vis02_vis03 | 0.0482 | 0.0490 | −0.0008 | −0.0169 |
correlation_vis01_vis04 | 0.2129 | 0.2166 | −0.0037 | −0.0172 |
correlation_vis02_vis04 | 0.1348 | 0.1383 | −0.0035 | −0.0256 |
correlation_vis03_vis04 | −0.0107 | −0.0098 | −0.0009 | 0.0901 |
correlation_vis01_vis05 | 0.1724 | 0.1764 | −0.0040 | −0.0226 |
correlation_vis02_vis05 | 0.1165 | 0.1199 | −0.0035 | −0.0288 |
correlation_vis03_vis05 | −0.0084 | −0.0076 | −0.0008 | 0.1023 |
correlation_vis04_vis05 | 0.3767 | 0.3837 | −0.0069 | −0.0180 |
correlation_vis01_vis06 | 0.2621 | 0.2665 | −0.0044 | −0.0166 |
correlation_vis02_vis06 | 0.2037 | 0.2079 | −0.0042 | −0.0200 |
correlation_vis03_vis06 | 0.0423 | 0.0434 | −0.0011 | −0.0262 |
correlation_vis04_vis06 | 0.4043 | 0.4117 | −0.0074 | −0.0180 |
correlation_vis05_vis06 | 0.3939 | 0.4013 | −0.0074 | −0.0186 |
correlation_vis01_vis07 | 0.0655 | 0.0679 | −0.0024 | −0.0348 |
correlation_vis02_vis07 | 0.0856 | 0.0881 | −0.0025 | −0.0283 |
correlation_vis03_vis07 | −0.0021 | −0.0017 | −0.0004 | 0.2066 |
correlation_vis04_vis07 | 0.1461 | 0.1503 | −0.0042 | −0.0278 |
correlation_vis05_vis07 | 0.1934 | 0.1983 | −0.0049 | −0.0246 |
correlation_vis06_vis07 | 0.2080 | 0.2132 | −0.0052 | −0.0244 |
correlation_vis01_vis08 | 0.0481 | 0.0497 | −0.0017 | −0.0336 |
correlation_vis02_vis08 | 0.1042 | 0.1068 | −0.0026 | −0.0245 |
correlation_vis03_vis08 | −0.0333 | −0.0336 | 0.0003 | −0.0088 |
correlation_vis04_vis08 | 0.1711 | 0.1752 | −0.0041 | −0.0233 |
correlation_vis05_vis08 | 0.1682 | 0.1725 | −0.0042 | −0.0246 |
correlation_vis06_vis08 | 0.1598 | 0.1641 | −0.0044 | −0.0267 |
correlation_vis07_vis08 | 0.0535 | 0.0559 | −0.0024 | −0.0429 |
correlation_vis01_vis09 | 0.0271 | 0.0281 | −0.0010 | −0.0367 |
correlation_vis02_vis09 | −0.0062 | −0.0056 | −0.0007 | 0.1176 |
correlation_vis03_vis09 | −0.0413 | −0.0421 | 0.0009 | −0.0212 |
correlation_vis04_vis09 | 0.1158 | 0.1193 | −0.0035 | −0.0296 |
correlation_vis05_vis09 | 0.0896 | 0.0927 | −0.0031 | −0.0331 |
correlation_vis06_vis09 | 0.1692 | 0.1733 | −0.0042 | −0.0240 |
correlation_vis07_vis09 | 0.0153 | 0.0165 | −0.0013 | −0.0778 |
correlation_vis08_vis09 | 0.0567 | 0.0585 | −0.0018 | −0.0303 |
correlation_vis01_vis10 | 0.0231 | 0.0257 | −0.0027 | −0.1040 |
correlation_vis02_vis10 | 0.1266 | 0.1301 | −0.0035 | −0.0267 |
correlation_vis03_vis10 | 0.0215 | 0.0219 | −0.0003 | −0.0149 |
correlation_vis04_vis10 | 0.3116 | 0.3195 | −0.0079 | −0.0249 |
correlation_vis05_vis10 | 0.2384 | 0.2458 | −0.0074 | −0.0303 |
correlation_vis06_vis10 | 0.2959 | 0.3042 | −0.0083 | −0.0272 |
correlation_vis07_vis10 | 0.0629 | 0.0659 | −0.0030 | −0.0451 |
correlation_vis08_vis10 | 0.0932 | 0.0968 | −0.0036 | −0.0374 |
correlation_vis09_vis10 | 0.0780 | 0.0811 | −0.0032 | −0.0390 |
> table_se <- b_f_comparison |>
+ select(variable, ends_with("se")) |>
+ filter(!is.na(freq_se))
> gt(table_se) |>
+ fmt_number(decimals = 4) |>
+ tab_caption(
+ caption = md(
+ paste(
+ "Table 5. Comparison of parameter standard errors between",
+ "Bayesian and frequentist MMRMs."
+ )
+ )
+ ) |>
+ cols_label(
+ variable = "Variable",
+ bayes_se = "Bayesian",
+ freq_se = "Frequentist",
+ diff_se = "Difference",
+ diff_relative_se = "Relative"
+ )
Variable | Bayesian | Frequentist | Difference | Relative |
---|---|---|---|---|
intercept | 0.1709 | 0.1709 | −0.0001 | −0.0005 |
bcva_bl | 0.0022 | 0.0022 | 0.0000 | −0.0007 |
avisitvis02 | 0.0709 | 0.0707 | 0.0003 | 0.0040 |
avisitvis03 | 0.0675 | 0.0672 | 0.0004 | 0.0054 |
avisitvis04 | 0.0763 | 0.0764 | 0.0000 | −0.0006 |
avisitvis05 | 0.0867 | 0.0863 | 0.0004 | 0.0047 |
avisitvis06 | 0.0869 | 0.0865 | 0.0004 | 0.0050 |
avisitvis07 | 0.1078 | 0.1071 | 0.0007 | 0.0067 |
avisitvis08 | 0.1157 | 0.1145 | 0.0012 | 0.0105 |
avisitvis09 | 0.1302 | 0.1283 | 0.0018 | 0.0143 |
avisitvis10 | 0.1411 | 0.1400 | 0.0011 | 0.0075 |
raceblack | 0.0551 | 0.0550 | 0.0002 | 0.0030 |
racewhite | 0.0520 | 0.0520 | 0.0001 | 0.0011 |
avisitvis01:armcdtrt | 0.0635 | 0.0628 | 0.0007 | 0.0117 |
avisitvis02:armcdtrt | 0.0798 | 0.0798 | −0.0001 | −0.0007 |
avisitvis03:armcdtrt | 0.0922 | 0.0916 | 0.0005 | 0.0058 |
avisitvis04:armcdtrt | 0.1003 | 0.1004 | −0.0001 | −0.0009 |
avisitvis05:armcdtrt | 0.1150 | 0.1147 | 0.0003 | 0.0028 |
avisitvis06:armcdtrt | 0.1189 | 0.1189 | 0.0001 | 0.0007 |
avisitvis07:armcdtrt | 0.1387 | 0.1382 | 0.0006 | 0.0042 |
avisitvis08:armcdtrt | 0.1487 | 0.1474 | 0.0013 | 0.0086 |
avisitvis09:armcdtrt | 0.1651 | 0.1644 | 0.0008 | 0.0046 |
avisitvis10:armcdtrt | 0.1829 | 0.1815 | 0.0014 | 0.0076 |