Using Bayesian Methods to Augment the Interpretation of Critical Care Trials. An Overview of Theory and Example Reanalysis of the Alveolar Recruitment for Acute Respiratory Distress Syndrome Trial 20

#### Bayesian priors ####

##### LOAD PACKAGES ####

library(tidyverse) 

library(insight)

library(bayestestR)

library(cowplot)

library(brms)

library(broom)

library(parameters)

####Analysis for ART — LR and Flat Prior####

#Traditional LR:

db$dead<-as.factor(ifelse(db$death==”yes”,1,0))

art.lr<-glm(dead~group,family=”binomial”,data=db) summary(art.lr)

exp(confint(art.lr))

#Flat prior analysis

flat_prior<-prior(normal(0,1000), class = “b”) art.flat <- brm(

dead ~ group,

data = db,

prior = flat_prior,

family = “bernoulli”,

seed = 123 # Adding a seed makes results reproducible.

)

#Uses insight package to sample posteriors

posteriors <- insight::get_parameters(art.flat,iterations=10^5)

#Summarizes the flat prior analysis art.flat.summary<-summary(art.flat) mean_eff<-art.flat.summary$fixed[2,1] mean_sd<-art.flat.summary$fixed[2,2]

#Some summaries using for plot legend any_harm<-sum(posteriors$b_groupART>0)/nrow(posteriors)

severe_harm<-sum(posteriors$b_groupART>log(1.25))/nrow(posteriors)

rope1<-sum(posteriors$b_groupART<log(1.1)|posteriors$b_groupART<log(1/1.1))/nrow(posteriors)

#Figure 1

temp.plot<-ggplot(posteriors, aes(x = b_groupART)) + geom_density()

p <- ggplot_build(temp.plot) # < — — INSTEAD OF `p <- print(m)`

plot.data<-p$data[[1]][,c(1,2)]

plot.data

fig1<-ggplot(plot.data, aes(x = x,y=y,group=1)) +

geom_line(size=1) +

geom_area(mapping = aes(x = ifelse(x>0, x, 0)), fill = “#FFB266") + geom_area(mapping = aes(x = ifelse(x<0, x, 0)), fill = “lightblue”) + geom_area(mapping = aes(x = ifelse(x>log(1.25), x, 0)), fill = “#FF9933") + geom_segment(inherit.aes = FALSE,

data=subset(plot.data,x>log(1/1.1)&x<log(1.1))[seq(1, nrow(subset(plot.data,x>log(1/1.1)&x<log(1.1))), 5), ],

aes(x=x,y=0,xend=x,yend=y))+ geom_vline(xintercept=0, color=”black”, linetype=1)+ geom_vline(xintercept=log(1.25), color=”#FF9933", linetype=1)+ geom_hline(yintercept=0,color=”black”,linetype=1)+ theme_cowplot()+

labs(x=”log(OR)”,y=””)+

scale_x_continuous(expand = c(0, 0),labels=seq(-0.2,0.6,by=0.1),breaks=seq(-0.2,0.6,by=0.1)) + scale_y_continuous(expand = c(0, 0))+

coord_cartesian(xlim=c(-0.25,0.75),ylim=c(0,3.5))+

annotate(“text”,x=0.35,y=3.2,label=paste0(“P(severe harm) = “,round(severe_harm,2),” “,sprintf(‘\u21d2')))+ annotate(“text”,x=0.1,y=3.2,label=paste0(“P(harm) = “,round(any_harm,2),” “,sprintf(‘\u21d2')))+ annotate(“text”,x=-0.1,y=3.2,label=paste0(sprintf(‘\u21d0'),” “,”P(benefit) = “,1-round(any_harm,2)))+

# annotate(“rect”, xmin = -0.06, xmax = 0.06, ymin = 0.06, ymax = 0.18,fill=”white”)+ annotate(“label”,x=0,y=0.1,label=paste0(“ROPE =”,

round(sum(posteriors$b_groupART<log(1.1)|posteriors$b_groupART<log(1/1.1))/nrow(posteriors),2)))

#Defining priors for Table 1 — Checks the probability for given values. You can play around if you want.

#Neutral Moderate: N(0,0.355) pnorm(log(2),mean = 0,sd=0.355)

#Neutral strong: N(0,0.205) pnorm(log(1.5),mean = 0,sd=0.205)

#Optimistic Weak: N(-0.41,0.77) pnorm(0,mean = log(0.66),sd=0.77)

#Optimistic Moderate: N(-0.41,0.40) pnorm(0,mean = log(0.66),sd=0.40)

#Optimistic Strong: N(-0.41,0.253) pnorm(0,mean = log(0.66),sd=0.253)

#Pessimistic Weak: N(0.41,0.77) pnorm(0,mean = -log(0.66),sd=0.77)

#Optimistic Moderate: N(0.41,0.40) pnorm(0,mean = -log(0.66),sd=0.40)

#Optimistic Strong: N(0.41,0.253) pnorm(0,mean = -log(0.66),sd=0.253)

#Beginning of ART Reanalysis

#Priors

m1priors <- prior(normal(0,.355), class = “b”) #Moderate strength skeptical prior

m2priors <- prior(normal(-0.4155,0.40), class = “b”)#Moderate strength optimistic prior

m3priors <- prior(normal(0.4155,0.80), class = “b”) #Weak strength skeptical prior

#Neutral prior m1 <- brm(

death ~ group,

data = db,

prior = m1priors,

family = “bernoulli”,

seed = 123 # Adding a seed makes results reproducible.

)

#Optimistic prior

m2 <- brm(

death ~ group, data = db,

prior = m2priors,

family = “bernoulli”,

seed = 123 # Adding a seed makes results reproducible.

)

#Pessimistic prior

m3 <- brm(

death ~ group,

data = db,

prior = m3priors,

family = “bernoulli”,

seed = 123 # Adding a seed makes results reproducible.

)

#Group results in a data frame

results<-as.data.frame(rbind(model_parameters(m1,ci = 0.95,exponentiate = FALSE,rope_range = c(-0.1,0.1)),

model_parameters(m2,ci = 0.95,exponentiate = FALSE,rope_range = c(-0.1,0.1)), model_parameters(m3,ci = 0.95,exponentiate = FALSE,rope_range = c(-0.1,0.1)))[c(2,4,6),])

posteriors.m1 <- insight::get_parameters(m1)[,2] posteriors.m2 <- insight::get_parameters(m2)[,2] posteriors.m3 <- insight::get_parameters(m3)[,2]

posterior.list<-list(posteriors.m1,posteriors.m2,posteriors.m3) map(posterior.list,~sum(.>log(1.25))/length(.)) map(posterior.list,~(quantile(exp(.),probs = c(0.025,0.5,0.975))))

#Plotting priors and posteriors

panelA<-ggplot(data = data.frame(x = c(-2, 2)), aes(x)) +

stat_function(fun = dnorm, n = 1000, args = list(mean = 0, sd = .355),linetype=2)+ stat_function(fun = dnorm, n = 1000, args = list(mean = summary(m1)$fixed[2,1],

sd = summary(m1)$fixed[2,2]),linetype=1)+ geom_area(stat = “function”, fun = dnorm,

args = list(mean = summary(m1)$fixed[2,1], sd = summary(m1)$fixed[2,2]),

fill = “darkgray”, xlim = c(log(1.25), 1.5),alpha=0.9)+ geom_area(stat = “function”, fun = dnorm,

args = list(mean = summary(m1)$fixed[2,1], sd = summary(m1)$fixed[2,2]),

fill = “gray”, xlim = c(log(1/1.1), log(1.1)),alpha=0.7)+ geom_vline(xintercept=0, color=”black”, linetype=1)+ geom_vline(xintercept=log(1.25), color=”black”, linetype=3)+ scale_x_continuous(expand = c(0, 0)) + scale_y_continuous(expand = c(0, 0))+ theme_minimal()+

labs(x=”log(OR)”,y=””)

panelB<-ggplot(data = data.frame(x = c(-2, 2)), aes(x)) +

stat_function(fun = dnorm, n = 1000, args = list(mean = -0.4155, sd = .42),linetype=2)+ stat_function(fun = dnorm, n = 1000, args = list(mean = summary(m2)$fixed[2,1],

sd = summary(m2)$fixed[2,2]),linetype=1)+ geom_area(stat = “function”, fun = dnorm,

args = list(mean = summary(m2)$fixed[2,1], sd = summary(m2)$fixed[2,2]),

fill = “darkgray”, xlim = c(log(1.25), 1.5),alpha=0.9)+ geom_area(stat = “function”, fun = dnorm,

args = list(mean = summary(m2)$fixed[2,1], sd = summary(m2)$fixed[2,2]),

fill = “gray”, xlim = c(log(1/1.1), log(1.1)),alpha=0.7)+ geom_vline(xintercept=0, color=”black”, linetype=1)+ geom_vline(xintercept=log(1.25), color=”black”, linetype=3)+ scale_x_continuous(expand = c(0, 0)) + scale_y_continuous(expand = c(0, 0))+ theme_minimal()+

labs(x=”log(OR)”,y=””)

panelC<-ggplot(data = data.frame(x = c(-2, 2)), aes(x)) +

stat_function(fun = dnorm, n = 1000, args = list(mean = 0.44, sd = .77),linetype=2)+ stat_function(fun = dnorm, n = 1000, args = list(mean = summary(m3)$fixed[2,1],

sd = summary(m3)$fixed[2,2]),linetype=1)+ geom_area(stat = “function”, fun = dnorm,

args = list(mean = summary(m3)$fixed[2,1], sd = summary(m3)$fixed[2,2]),

fill = “darkgray”, xlim = c(log(1.25), 1.5),alpha=0.9)+ geom_area(stat = “function”, fun = dnorm,

args = list(mean = summary(m3)$fixed[2,1], sd = summary(m3)$fixed[2,2]),

fill = “gray”, xlim = c(log(1/1.1), log(1.1)),alpha=0.7)+ geom_vline(xintercept=0, color=”black”, linetype=1)+ geom_vline(xintercept=log(1.25), color=”black”, linetype=3)+ scale_x_continuous(expand = c(0, 0)) + scale_y_continuous(expand = c(0, 0))+ theme_minimal()+

labs(x=”log(OR)”,y=””)

####Bayesian Metanalysis####

library(bayesmeta)

y<-c(summary(m1)$fixed[2,1],summary(m2)$fixed[2,1],summary(m3)$fixed[2,1]) sigma<-c(summary(m1)$fixed[2,2],summary(m2)$fixed[2,2],summary(m3)$fixed[2,2])

l1<-c(“Neutral”,”Optimistic”,”Pessimistic”)

meta1<-bayesmeta(y=y, sigma=sigma,mu.prior=c(0,0.355), label=l1,tau.prior = “DuMouchel”)

plot(meta1,which=1) plot(meta1,which=2,prior=TRUE)

plot(meta1,which=3,main=””,prior = TRUE) plot(meta1,which=4,main=””,prior = TRUE)

meta1_recorded<-forest(meta1,trans=exp, refline=1, xlab=”Odds ratio”) meta1_recorded<-as.data.frame(meta1_recorded) meta1_recorded$name<-rownames(meta1_recorded) meta1_recorded<-meta1_recorded[-5,] colnames(meta1_recorded)<-c(“Low”,”Est”,”High”,”name”) meta1_recorded<-ggplot(meta1_recorded,aes(x=Est,y=name))+

geom_point()+ geom_errorbarh(aes(xmin=Low,xmax=High),height=0)+ coord_cartesian(xlim=c(-0.5,1))+ geom_vline(xintercept=0,linetype=2)+ theme_minimal()+

labs(x=”log(OR); 95% CrI”,y=””)

meta1$I2(tau=0.1) meta1$summary[2,1]

dens.res<-data.frame(tau=seq(0,0.3,length.out = 1000), i2=meta1$I2(seq(0,0.3,length.out = 1000)))

meta2_recorded<-ggplot(dens.res,aes(x=tau,y=i2,group=1))+ geom_line()+ geom_vline(xintercept=meta1$summary[2,1],linetype=2)+ geom_hline(yintercept=meta1$I2(meta1$summary[2,1]),linetype=2)+ theme_minimal()%+replace%theme(panel.grid = element_blank(),

panel.grid.major = element_blank(),

legend.position = “”)+ labs(x=”Tau”,y=”I2")+

labs(subtitle = paste0(“For median Tau, “,

round(meta1$I2(meta1$summary[2,1])*100,2),

“%\nof heterogeneity is explained by priors”))

plot_grid(meta1_recorded,meta2_recorded,

labels=c(“A”,”B”), nrow=1)

留言

這個網誌中的熱門文章

可轉移性、普遍性、代表性和外部有效性

頻率學派 vs 貝氏學派

貝氏分析計算器