# /*--------------------------------------------------------------------------
# A tutorial on Bayesian meta-analysis of health state utilities
# --------------------------------------------------------------------------*/

# /*--------------------------------------------------------------------------
# STEP 1: Set-up the data in R
# --------------------------------------------------------------------------*/

# load the packages

library(brms)
library(mfp)
library(mice)
library(bayesplot)
library(shinystan)
library(tidybayes)
library(ggplot2)

# load the data 

dat <- read.csv("Utilities.csv")


# /*--------------------------------------------------------------------------
# STEP 2: Employ methods to impute standard deviations
# --------------------------------------------------------------------------*/

# fit a fractional polynomial regression model

sd.model1 <-  mfp(formula = sd ~ fp(utility), data = dat)

# examine the results

sd.model1

# extract the coefficients of the best model

coef <- coef(sd.model1)

# generate the equation and impute missing standard deviations

dat$sd.imp1 <- ifelse(is.na(dat$sd), (coef[1] + coef[2]*dat$utility^1), dat$sd)

# calculate the standard error 

dat$se.imp1 <- dat$sd.imp1/sqrt(dat$n)


# /*--------------------------------------------------------------------------
# STEP 3: Define the priors
# --------------------------------------------------------------------------*/

# define the priors

priors.model1 <- c(prior(normal(0.5,0.05), class = Intercept), 
                   prior(cauchy(0,0.5), class = sd))

# conduct prior predictive check

fit.prior <- brm(formula = utility | se(se.imp1) ~ 1 + (1|studyid),
                 data = dat,
                 prior = priors.model1,
                 iter = 4000,
                 sample_prior = "only")

# examine the plot

pp_check(fit.prior, ndraws = 50)


# /*--------------------------------------------------------------------------
# STEP 4: Fit the model
# --------------------------------------------------------------------------*/

# fit the model 

fit.model1 <- brm(formula = utility | se(se.imp1) ~ 1 + (1|studyid),
                  data = dat,
                  prior = priors.model1,
                  iter = 4000)


# /*--------------------------------------------------------------------------
# STEP 5: Diagnose model convergence
# --------------------------------------------------------------------------*/

# examine rhat and ess

summary(fit.model1)

# create a trace plot

plot(fit.model1, variable = c("b_Intercept","sd_studyid__Intercept")) 

mcmc_trace(fit.model1, pars = c("b_Intercept","sd_studyid__Intercept"))

# conduct posterior predictive checks

pp_check(fit.model1, ndraws = 50)

# further checks through shinystan

launch_shinystan(fit.model1)


# /*--------------------------------------------------------------------------
# STEP 6: Interpret the results
# --------------------------------------------------------------------------*/

# examine the pooled effect size and between-study heterogeneity

summary(fit.model1)

# examine the deviation of each study from the overall effect size

ranef(fit.model1)

# extract parameters of interest from the fitted model

model1.post <- posterior_samples(fit.model1, pars = "b_Intercept")

# rename the parameter

names(model1.post) <- "utility"

# explore posterior probabilities (manual)

(sum(model1.post$utility < 0.80) / length(model1.post$utility))*100

(sum(model1.post$utility < 0.70) / length(model1.post$utility))*100

# explore posterior probabilities (using ecdf)

model1.ecdf <- ecdf(model1.post$utility)

model1.ecdf(c(0.80, 0.70))



# /*--------------------------------------------------------------------------
# STEP 7: Perform sensitivity analysis
# --------------------------------------------------------------------------*/

# [1] using a more informative prior for the effect size

# define a more informative prior for the intercept

priors.model2 <- c(prior(normal(0.6,0.03), class = Intercept), 
                   prior(cauchy(0,0.5), class = sd))

# re-fit the model 

fit.model2 <- brm(formula = utility | se(se.imp1) ~ 1 + (1|studyid),
                  data = dat,
                  prior = priors.model2,
                  iter = 4000)

# perform model diagnostics and examine results

summary(fit.model2)


# [2] multiple imputation before model fitting using mice

# calculate the standard error for available studies

dat$se <- dat$sd/sqrt(dat$n)

# use mice function to generate 5 sets of imputed SEs

dat.mice <- mice(dat[,c("studyid","utility","se")], m = 5, print = FALSE)

# re-fit the model

fit.model3 <- brm_multiple(formula = utility | se(se) ~ 1 + (1|studyid),
                           data = dat.mice,
                           prior = priors.model1,
                           iter = 4000)

# perform model diagnostics and examine results

summary(fit.model3)


# [3] excluding studies with missing SDs

# re-fit the model

fit.model4 <- brm(formula = utility | se(se) ~ 1 + (1|studyid),
                  data = dat,
                  prior = priors.model1,
                  iter = 4000)

# perform model diagnostics and examine results

summary(fit.model4)



# /*--------------------------------------------------------------------------
# generate forest plot

library(tidybayes)
library(dplyr)
library(ggplot2)
library(ggridges)
library(glue)
library(stringr)
library(forcats)

# extract study-specific effect sizes: average plus deviations from each study

model1.draws <- spread_draws(fit.model1, r_studyid[studyid,], b_Intercept) %>% 
  mutate(b_Intercept = r_studyid + b_Intercept)

# extract average effect size

model1.pe.draws <- spread_draws(fit.model1, b_Intercept) %>% 
  mutate(studyid = "Pooled effect")

# combine average and study-specific effect sizes

model1.data <- bind_rows(model1.draws, model1.pe.draws) %>% 
  ungroup() %>%
  mutate(studyid = str_replace_all(studyid, "[.]", " ")) %>% 
  mutate(studyid = reorder(studyid, b_Intercept))

# generate data frame of summary numbers

model1.summary <- group_by(model1.data, studyid) %>% 
  mean_qi(b_Intercept)

# draw the plot

ggplot(aes(b_Intercept, relevel(studyid, "Pooled effect", after = Inf)), 
       data = model1.data) +
  scale_x_continuous(limits = c(0.3, 1), breaks = seq(0.50, 1, by=0.25)) +
  
  # add vertical lines for pooled effect and CrI
  geom_vline(xintercept = fixef(fit.model1)[1, 1], 
             color = "gray20", size = 1) +
  geom_vline(xintercept = fixef(fit.model1)[1, 3:4], 
             color = "gray20", linetype = 2) +
  
  # add densities
  geom_density_ridges(fill = "lightblue", 
                      rel_min_height = 0.01, 
                      col = NA, scale = 1,
                      alpha = 0.8) +
  geom_pointintervalh(data = model1.summary, 
                      size = 1) +
  
  # add text and labels
  geom_text(data = mutate_if(model1.summary, 
                             is.numeric, round, 2),
            aes(label = sprintf("%.2f [%.2f, %.2f]", b_Intercept, .lower, .upper), 
                x = Inf), hjust = "inward") +
  labs(x = "Utility", 
       y = element_blank()) +
  theme_tidybayes() +
  theme(text = element_text(size = 15)) 
# --------------------------------------------------------------------------*/


# /*--------------------------------------------------------------------------
# Frequentist meta-analysis comparison
# --------------------------------------------------------------------------*/

library(metafor)

# Using the SEs calculated from fractional polynomial regression
fma.1 <- rma(yi = utility, sei = se.imp1, data = dat, method = "DL")
fma.1

# Using the SEs calculated using multiple imputation using chained equations
fma.2 <- with(dat.mice, rma(yi = utility, sei = se, method = "DL"))
fma.2.pooled <- summary(pool(fma.2))
fma.2.pooled

# Excluding studies with missing SEs
fma.3 <- rma(yi = utility, sei = se, data = dat, method = "DL")
fma.3
