Bayesian reanalysis of clinical trials

 # https://benjamin-andrew.shinyapps.io/andromeda_shock_bayesian/?fbclid=IwAR1qHXH4TdjT6h1APC0IS07tXcmRO-36UKvSMb_h8NRzH82TLw8zXXYqToo&mibextid=Zxz2cZ

plot_posterior <- function(est_type = 1, pt_est = 0.5, upper_ci = 0.9, ci_width = 0.95, hr_a = 10, hr_b = 30, or_a = 10, or_b = 30, trt_n = 50, ctrl_n = 50, theta_in = 1, sd_in = 0.42, hr_in = 0.5, pr_in = 0.05, ci_in = 89) {

library(tidyverse)

library(RColorBrewer)

  short_lab <- ifelse(est_type == 1, "HR", ifelse(est_type == 2, "OR", "RR"))

  long_lab <- ifelse(est_type == 1, "Hazard Ratio", ifelse(est_type == 2, "Odds Ratio", "Risk Ratio"))

  likelihood_p <- (1 - ((1 - ci_width) / 2))

  or_c <- trt_n - or_a

  or_d <- ctrl_n - or_b

  prior_theta <- log(theta_in)

  prior_sd <- sd_in

# Calculate Likelihood Parameters

  likelihood_theta <- ifelse(est_type == 1, log(pt_est),

                             ifelse(est_type == 2, log(((or_a + 0.5) * (or_d + 0.5)) / ((or_b + 0.5) * (or_c + 0.5))),

                                    log((or_a / (or_a + or_c)) / (or_b / (or_b + or_d)))))

  likelihood_sd <- ifelse(est_type == 1, sqrt((1 / hr_a) + (1 / hr_b)),

                          ifelse(est_type == 2, sqrt((1 / (or_a + 0.5)) + (1 / (or_b + 0.5)) + (1 / (or_c + 0.5)) + (1 / (or_d + 0.5))),

                                 sqrt((or_c / (or_a * (or_a + or_c))) + (or_d / (or_b * (or_b + or_d))))))

# Calculate Posterior Parameters

  post_theta <- ((prior_theta / (prior_sd)^2) + (likelihood_theta / likelihood_sd^2)) / 

    ((1 / (prior_sd)^2) + (1 / likelihood_sd^2))

  post_sd <- sqrt(1 / ((1 / (prior_sd)^2) + (1 / likelihood_sd^2)))

# Plot data

  x <- seq(-5, 3, by = 0.01)

  prior_plot <- dnorm(x, prior_theta, prior_sd)

  likelihood_plot <- dnorm(x, likelihood_theta, likelihood_sd)

  posterior_plot <- dnorm(x, post_theta, post_sd)

  plot_data <- tibble(

    x = rep(x, 3)

  ) %>%

    mutate(

      dist = rep(c("prior", "likelihood", "posterior"), each = nrow(.) / 3),

      y = c(prior_plot, likelihood_plot, posterior_plot),

      x = exp(x),

      y = exp(y)

    )

# Max xlim

  max_x <- max(likelihood_theta + (exp(likelihood_theta) * 1.5), 2)

# Credible interval

  lower_cred <- round(exp(qnorm((1 - (ci_in/100)) / 2, post_theta, post_sd)), 2)

  upper_cred <- round(exp(qnorm(1 - (1 - (ci_in/100)) / 2, post_theta, post_sd)), 2)

  mid_cred <- round(exp(qnorm(0.5, post_theta, post_sd)), 2)

# Plot

  ggplot(plot_data, aes(x = x, y = y, group = dist)) + 

    geom_vline(xintercept = 1, linetype = "dashed",

               color = "grey50", alpha = 0.75, size = 0.75) + 

    geom_line(aes(color = dist), size = 1.1) + 

    scale_color_brewer(name = NULL, type = "qual", palette = "Dark2",

                       breaks = c("likelihood", "prior", "posterior"),

                       labels = c("Likelihood", "Prior", "Posterior")) + 

    xlim(0, max_x) + 

    labs(

      x = long_lab,

      y = "Probability Density"

    ) + 

    annotate(geom = "text",

             label = paste("Posterior probability ", short_lab,

                           paste(" < 1: ", 

                                 round(pnorm(log(1), post_theta, post_sd, 

                                             lower.tail = TRUE), 3), sep = ""), sep = ""),

             x = max_x, y = max(plot_data$y), hjust = 1,

             fontface = "bold") + 

    annotate(geom = "text",

             label = paste("Posterior median (", ci_in,

                           paste("% credible interval): ",

                                 mid_cred,

                                 paste(" (", lower_cred, sep = ""),

                           paste(", ", upper_cred, sep = ""),

                           paste(")", sep = ""), sep = ""), sep = ""),

             x = max_x, y = max(plot_data$y) - (2 * max(plot_data$y)/25), hjust = 1,

             fontface = "bold") + 

    theme_classic() + 

    theme(

      legend.position = "bottom",

      text = element_text(family = "Gill Sans MT"),

      axis.ticks.y = element_blank(),

      axis.text.y = element_blank(),

      axis.title = element_text(size = 15),

      axis.text = element_text(size = 12),

      legend.text = element_text(size = 15)

    )

}


plot_posterior(est_type = 1, pt_est = 0.5, upper_ci = 0.9, ci_width = 0.95,

               hr_a = 10, hr_b = 30, or_a = 10, or_b = 30, trt_n = 50, ctrl_n = 50,

               theta_in = 1, sd_in = 0.42, hr_in = 0.5, pr_in = 0.05, ci_in = 89)

留言

這個網誌中的熱門文章

Bayesian reanalysis of ORBITA

Bayesian reanalysis with pymc3

Bayesian reanalysis of Apolipoprotein A1 Infusions