BAWTO

Adverse Event Analysis

Many clinical trial publications list adverse events, in the reviewed prostate cancer clinical trials these adverse events were frequently not avaiable on clinicaltrials.gov. Trial adverse events were extracted for prostate cancer trials with a homologous recombination biomarker population in sysrev.com/p/70431:

Get the Data

The data for this analysis is derived from the 'Adverse_Event' table extracted in sysrev.com/p/70431. It can be retrive with the rsr package.

sranswers <- rsr::get_answers(70431) |> rsr::list_answers()
adverse_events <- sranswers$`Adverse Events` |>
  select(aid,Adverse_Event,Grade) |> 
  unnest(everything()) |> 
  mutate(across(2:3,~ trimws(as.character(.)))) 

DT::datatable(adverse_events)

This data needs to be combined and manipulated to generate the figures below. In principle this is all automated on github.com/insilica/bawto. To illustrate the figure genreation, we cache some of the tables including an overall adverse event counts table ae.tbl, a median rates table median.rates, and a table focusing on anemia anemia.tbl. Visit github.com/insilica/bawto to see the full analysis.

These tables are loaded below and the median rates table shared. To view the other table load this notebook in an IDE:

ae.tbl       <- readRDS(url("http://insilica.co.s3.amazonaws.com/bawto/resources/adverse_events.rds"))
median.rates <- readRDS(url("http://insilica.co.s3.amazonaws.com/bawto/resources/median.rates.rds"))
anemia.tbl   <- readRDS(url("http://insilica.co.s3.amazonaws.com/bawto/resources/anemia.rds"))
DT::datatable(median.rates)

Build the Figure

With the above tables generating figures is relatively easy. Patchwork provides methods for building margin plots above and to the right of heatmaps for adverse events. Styling can get fairly complex, below we have folded the code for the styling components so that it is easier to focus on the plot building, unfold the code to see how the style is built.

els = list(
  axis   = element_text(size=unit(3,"pt")),
  axis45 = element_text(angle=45,hjust=1,size=unit(3,"pt")),
  strip  = element_text(size=unit(6,"pt")))

colfunc <- colorRampPalette(c("green", "red"))

theme.A = \(plot){
  plot + scale_y_continuous(expand=c(0,0)) +
    scale_fill_manual(values=c("darkturquoise","firebrick3"),
                      guide= guide_legend(title = "A. grade", title.position = "top",direction="horizontal")) + 
    theme_bw() + xlab("") + ylab("") + 
    theme(axis.text.y=els$axis, axis.text.x=els$axis45, strip.text=els$strip)  
}

theme.B = \(plot){
  plot + xlab("") + ylab("") + 
    theme(axis.text.y = els$axis,axis.text.x = els$axis45, strip.text = els$strip) + 
    scale_fill_manual(
      values=c(colfunc(4),"darkgray","purple"),
      guide= guide_legend(title="B. rate",title.position = "top",direction="horizontal",nrow=2))
}

theme.C = \(plot){
  plot + theme_bw() + 
    scale_y_continuous(expand=c(0,0)) + 
    scale_fill_discrete(guide=guide_legend(title="C. treatment class",title.position = "top",direction="horizontal")) + 
    xlab("") + ylab("") + 
    theme(axis.text.x = els$axis, axis.text.y = els$axis, strip.text=els$strip)
}

Below 3 figures are generated.

A displays median adverse event rates for Androgen Receptor directed therapies (ARD) and PARP inhibitor therapies. Blue are grade 1/2 events, red are grade 3+ events.

B Gives a grid of heatmaps for adverse events by grade and therapy. Each row is a published prostate cancer trial and each column is an adverse event.

C provides the marginal rate of anemia (the adverse event with the greatest relative rate difference between therapies) for each clinical trial colored by therapy type and faceted by grade. Visit the publication for higher resolution figures.

A <- {
  median.rates |> 
    ggplot(aes(x=reorder(short_ae_name,-mean_rate), y=rate, fill=grade)) + 
    geom_col() + facet_grid( ~ treatment_class)
} |> theme.A()

B <- {
  plot <- ae.tbl |>
    ggplot(aes(x=reorder(event,-mean_rate), y=reorder(rg_name,-order), fill=rate_bucket)) + 
    geom_tile(col="black") + facet_grid(grade~treatment_class) 
} |> theme.B()

C <- {
  lblr  <- \(v){ list("grade 1/2"="anemia\ngrade 1/2", "grade 3+"="anemia\ngrade 3+")[v] }
  anemia.tbl |>  
    ggplot(aes(x=reorder(rg_name,-order),y=rate,fill=treatment_class)) + 
    geom_col(position="dodge") + coord_flip() + 
    facet_grid(grade ~., labeller=as_labeller(lblr))
} |> theme.C()

A + guide_area() + B + C + 
  plot_layout(heights = c(1,2),widths = c(3,1),guides = "collect") + 
  plot_annotation(tag_levels='A')
## Warning: Removed 2 rows containing missing values (position_stack).