knitr::opts_chunk$set(echo=FALSE, warning=FALSE,message=FALSE, fig.width=50, fig.height=100)
load_all("../../gemtc/gemtc") load_all("..") library(dplyr) filter <- dplyr::filter library(ggplot2) library(plotly) library(stringr) library(knitr) library(meta) source("theme.r") clean_aetype <- function(aetype){ aetype <- stringr::str_to_sentence(aetype) aetype[aetype=="Ggt increased"] <-"GGT increased" aetype[aetype=="Cpk increased"] <-"CPK increased" aetype[aetype=="Inr increased"] <-"INR increased" aetype[aetype=="Withdrawals because of aes"] <-"Withdrawals because of AEs" aetype }
opts_chunk$set(fig.width=15, fig.height=20, echo=FALSE) muffleError <- function(x,options) {} knit_hooks$set(error=muffleError)
aecount <- bpaearmtype %>% filter(!aetype %in% c("ANY ADVERSE EVENT", "SERIOUS ADVERSE EVENTS")) %>% group_by(aetype) %>% summarise(N=sum(N), count=sum(count)) %>% mutate(prop = count/N) %>% mutate(aetype=factor(aetype, levels=unique(aetype)[order(prop)])) %>% mutate(aetype = clean_aetype(aetype)) %>% mutate(pse = N*prop*(1-prop)) mares <- data.frame(aetype=unique(as.character(aecount$aetype))) mares[,c("totn","totr","totncon","totrcon", "or","orl","oru", "rd","rdl","rdu", "nmeno", "nbone", "nmenopre", "nmenopost", "nbonenone", "nboneall", "meno.orp","bone.orp","meno.rdp","bone.rdp", "ormeno","ormenol","ormenou", "orbone","orbonel","orboneu", "rdmeno","rdmenol","rdmenou", "rdbone","rdbonel","rdboneu", "orbonenone","orbonenonel","orbonenoneu", "orboneall","orbonealll","orboneallu", "ormenopre","ormenoprel","ormenopreu", "ormenopost","ormenopostl","ormenopostu", "rdbonenone","rdbonenonel","rdbonenoneu", "rdboneall","rdbonealll","rdboneallu", "rdmenopre","rdmenoprel","rdmenopreu", "rdmenopost","rdmenopostl","rdmenopostu", "totnmenopre", "totnmenopost", "totrmenopre", "totrmenopost", "totnbonenone", "totnboneall", "totrbonenone", "totrboneall", "totnconmenopre", "totnconmenopost", "totrconmenopre", "totrconmenopost", "totnconbonenone", "totnconboneall", "totrconbonenone", "totrconboneall" )] <- NA aetypes_meta <- setdiff(mares$aetype, "Withdrawals because of AEs") for (i in seq(along.with=aetypes_meta)){ bpma <- bpaeriskdiff %>% mutate(aetype = clean_aetype(aetype)) %>% filter(trtcon %in% c("100","101","103")) %>% filter(aetype==aetypes_meta[i]) %>% mutate(meno2 = ifelse(meno=="mixed", NA, as.character(meno)), meno2 = factor(meno2, levels=c("pre","post")), bonemeta2 = ifelse(bonemeta=="mixed", NA, as.character(bonemeta)), bonemeta2 = factor(bonemeta2, levels = c("none", "all"))) if (nrow(bpma) > 0){ mres <- metabin(count, N, rcon, ncon, studlab=study, data=bpma, sm="OR") mresrd <- metabin(count, N, rcon, ncon, studlab=study, data=bpma, sm="RD") mares[i,"nmeno"] <- sum(!is.na(bpma$meno2)) mares[i,"nmenopre"] <- sum(bpma$meno2=="pre", na.rm=TRUE) mares[i,"nmenopost"] <- sum(bpma$meno2=="post", na.rm=TRUE) if (mares[i,"nmeno"] > 0){ mrtry <- try(mregmeno <- metareg(mres, ~ meno2)) if (!inherits(mrtry, "try-error") && (length(coef(mrtry))>1)){ orsmeno <- exp(coef(summary(mregmeno)))[c("meno2post"),c("estimate","ci.lb","ci.ub")] mares$meno.orp[i] <- mregmeno$QMp mares[i,c("ormeno","ormenol","ormenou")] <- orsmeno ormenopre <- unlist(unclass(predict(mrtry, newmods = 0))[c("pred","ci.lb","ci.ub")]) ormenopost <- unlist(unclass(predict(mrtry, newmods = 1))[c("pred","ci.lb","ci.ub")]) mares[i,c("ormenopre","ormenoprel","ormenopreu")] <- exp(ormenopre) mares[i,c("ormenopost","ormenopostl","ormenopostu")] <- exp(ormenopost) } mrtryd <- try(mregmeno <- metareg(mresrd, ~ meno2)) if (!inherits(mrtryd, "try-error") && (length(coef(mrtryd))>1)){ rdsmeno <- coef(summary(mregmeno))[c("meno2post"),c("estimate","ci.lb","ci.ub")] mares$meno.rdp[i] <- mregmeno$QMp mares[i,c("rdmeno","rdmenol","rdmenou")] <- rdsmeno rdmenopre <- unlist(unclass(predict(mrtryd, newmods = 0))[c("pred","ci.lb","ci.ub")]) rdmenopost <- unlist(unclass(predict(mrtryd, newmods = 1))[c("pred","ci.lb","ci.ub")]) mares[i,c("rdmenopre","rdmenoprel","rdmenopreu")] <- rdmenopre mares[i,c("rdmenopost","rdmenopostl","rdmenopostu")] <- rdmenopost } } mares[i,"nbone"] <- sum(!is.na(bpma$bonemeta2)) mares[i,"nboneall"] <- sum(bpma$bonemeta2=="all", na.rm=TRUE) mares[i,"nbonenone"] <- sum(bpma$bonemeta2=="none", na.rm=TRUE) if (mares[i,"nbone"] > 0){ mrtry <- try(mregbone <- metareg(mres, ~ bonemeta2)) if (!inherits(mrtry, "try-error") && (length(coef(mrtry))>1)){ orsbone <- exp(coef(summary(mregbone)))[c("bonemeta2all"),c("estimate","ci.lb","ci.ub")] mares$bone.orp[i] <- mregbone$QMp mares[i,c("orbone","orbonel","orboneu")] <- orsbone orbonenone <- unlist(unclass(predict(mrtry, newmods = 0))[c("pred","ci.lb","ci.ub")]) orboneall <- unlist(unclass(predict(mrtry, newmods = 1))[c("pred","ci.lb","ci.ub")]) mares[i,c("orbonenone","orbonenonel","orbonenoneu")] <- exp(orbonenone) mares[i,c("orboneall","orbonealll","orboneallu")] <- exp(orboneall) } mrtryd <- try(mregbone <- metareg(mresrd, ~ bonemeta2)) if (!inherits(mrtryd, "try-error") && (length(coef(mrtryd))>1)){ rdsbone <- coef(summary(mregbone))[c("bonemeta2all"),c("estimate","ci.lb","ci.ub")] mares$bone.rdp[i] <- mregbone$QMp mares[i,c("rdbone","rdbonel","rdboneu")] <- rdsbone rdbonenone <- unlist(unclass(predict(mrtryd, newmods = 0))[c("pred","ci.lb","ci.ub")]) rdboneall <- unlist(unclass(predict(mrtryd, newmods = 1))[c("pred","ci.lb","ci.ub")]) mares[i,c("rdbonenone","rdbonenonel","rdbonenoneu")] <- rdbonenone mares[i,c("rdboneall","rdbonealll","rdboneallu")] <- rdboneall } } mares$totn[i] <- sum(bpma$N) mares$totr[i] <- sum(bpma$count) mares$totncon[i] <- sum(bpma$ncon) mares$totrcon[i] <- sum(bpma$rcon) mares$totnmenopre[i] <- sum(bpma$N[bpma$meno2=="pre"],na.rm=TRUE) mares$totnmenopost[i] <- sum(bpma$N[bpma$meno2=="post"],na.rm=TRUE) mares$totrmenopre[i] <- sum(bpma$count[bpma$meno2=="pre"],na.rm=TRUE) mares$totrmenopost[i] <- sum(bpma$count[bpma$meno2=="post"],na.rm=TRUE) mares$totnbonenone[i] <- sum(bpma$N[bpma$bonemeta2=="none"],na.rm=TRUE) mares$totnboneall[i] <- sum(bpma$N[bpma$bonemeta2=="all"],na.rm=TRUE) mares$totrbonenone[i] <- sum(bpma$count[bpma$bonemeta2=="none"],na.rm=TRUE) mares$totrboneall[i] <- sum(bpma$count[bpma$bonemeta2=="all"],na.rm=TRUE) mares$totnconmenopre[i] <- sum(bpma$ncon[bpma$meno2=="pre"],na.rm=TRUE) mares$totnconmenopost[i] <- sum(bpma$ncon[bpma$meno2=="post"],na.rm=TRUE) mares$totrconmenopre[i] <- sum(bpma$rcon[bpma$meno2=="pre"],na.rm=TRUE) mares$totrconmenopost[i] <- sum(bpma$rcon[bpma$meno2=="post"],na.rm=TRUE) mares$totnconbonenone[i] <- sum(bpma$ncon[bpma$bonemeta2=="none"],na.rm=TRUE) mares$totnconboneall[i] <- sum(bpma$ncon[bpma$bonemeta2=="all"],na.rm=TRUE) mares$totrconbonenone[i] <- sum(bpma$rcon[bpma$bonemeta2=="none"],na.rm=TRUE) mares$totrconboneall[i] <- sum(bpma$rcon[bpma$bonemeta2=="all"],na.rm=TRUE) mares$totr[i] <- sum(bpma$count) mares$totncon[i] <- sum(bpma$ncon) mares$totrcon[i] <- sum(bpma$rcon) mares[i,c("or","orl","oru")] <- exp(unlist(mres[c("TE.fixed","lower.fixed","upper.fixed")])) mares[i,c("rd","rdl","rdu")] <- unlist(mresrd[c("TE.fixed","lower.fixed","upper.fixed")]) } else mares[i,c("totn","totr","totncon","totrcon")] <- 0 } # Filter to those for which the OR or RD is prac and stat sig for a subgroup # 1.5 for ORs, and 0.02 for RDs mares <- mares %>% mutate( statsigbonerd = bone.rdp < 0.05 & !is.na(bone.rdp), statsigboneor = bone.orp < 0.05 & !is.na(bone.orp), statsigmenord = meno.rdp < 0.05 & !is.na(meno.rdp), statsigmenoor = meno.orp < 0.05 & !is.na(meno.orp), sigbonenone = (rdbonenone > 0.02 & !is.na(rdbonenone) & statsigbonerd) | (orbonenone > 1.5 & !is.na(orbonenone) & statsigboneor), sigboneall = (rdboneall > 0.02 & !is.na(rdboneall) & statsigbonerd) | (orboneall > 1.5 & !is.na(orboneall) & statsigboneor), sigmenopre = (rdmenopre > 0.02 & !is.na(rdmenopre) & statsigmenord) | (ormenopre > 1.5 & !is.na(ormenopre) & statsigmenoor), sigmenopost = (rdmenopost > 0.02 & !is.na(rdmenopost) & statsigmenord) | (ormenopost > 1.5 & !is.na(ormenopost) & statsigmenoor), datamenopre = sprintf("%s/%s vs %s/%s", totrmenopre, totnmenopre, totrconmenopre, totnconmenopre), datamenopost = sprintf("%s/%s vs %s/%s", totrmenopost, totnmenopost, totrconmenopost, totnconmenopost), databonenone = sprintf("%s/%s vs %s/%s", totrbonenone, totnbonenone, totrconbonenone, totnconbonenone), databoneall = sprintf("%s/%s vs %s/%s", totrboneall, totnboneall, totrconboneall, totnconboneall), orfmenopre = sprintf("%s (%s,%s)", round(ormenopre,2), round(ormenoprel,2), round(ormenopreu,2)), orfmenopost = sprintf("%s (%s,%s)", round(ormenopost,2), round(ormenopostl,2), round(ormenopostu,2)), rdfmenopre = sprintf("%s (%s,%s)", round(rdmenopre,2), round(rdmenoprel,2), round(rdmenopreu,2)), rdfmenopost = sprintf("%s (%s,%s)", round(rdmenopost,2), round(rdmenopostl,2), round(rdmenopostu,2)), orfbonenone = sprintf("%s (%s,%s)", round(orbonenone,2), round(orbonenonel,2), round(orbonenoneu,2)), orfboneall = sprintf("%s (%s,%s)", round(orboneall,2), round(orbonealll,2), round(orboneallu,2)), rdfbonenone = sprintf("%s (%s,%s)", round(rdbonenone,2), round(rdbonenonel,2), round(rdbonenoneu,2)), rdfboneall = sprintf("%s (%s,%s)", round(rdboneall,2), round(rdbonealll,2), round(rdboneallu,2)), nmenof = sprintf("%s/%s", nmenopre, nmenopost), nbonef = sprintf("%s/%s", nbonenone, nboneall) )
To investigate whether the adverse effects of bisphosphonates were modified by menopausal status or by the presence of bone metastases, the previous meta-analyses of the studies with direct comparisons of a bisphosphonate with a non-bisphosphonate control were extended to fixed effects meta-regression analyses [ ref Viechtbauer, W. (2010). Conducting meta-analyses in R with the "metafor" package. Journal of Statistical Software, 36(3), 1-48. ]. The studies were categorised according to whether they included pre-menopausal, post-menopausal women or a mixture, and according to whether the participants had bone metastases (no participants, all participants or a mixture). The studies with a mixture of patient types were excluded, then the treatment effect (log odds ratio or risk difference) was modified with a linear regression term contrasting "all metastatic patients" or "all post-menopausal patients", with none.
The meta-regression results for all adverse events were filtered to include only those where the contrast in the treatment effect between subgroups was statistically significant, and the treatment effect on adverse event risk for the higher-risk subgroup was practically significant (odds ratio > 1.5 or risk difference > 2%). The remaining results are presented in the two tables below.
The only significant subgroup contrast is for insomnia, though this result is likely to be unreliable as it is based on only 11 and 15 events in the two subgroups respectively. Moreover the estimated risk increase in post-menopausal women is only 2%.
options(width=150) cnames <- c("", "Studies (none/all metastatic)", "Pre-menopausal", "Post-menopausal", "Odds ratio", "Risk difference", "Odds ratio", "Risk difference", "OR", "RD") library(kableExtra) mares %>% filter(sigmenopre | sigmenopost) %>% mutate(meno.orp = round(meno.orp,2), meno.rdp=round(meno.rdp,2)) %>% select(aetype, nmenof, datamenopre, datamenopost, orfmenopre, rdfmenopre, orfmenopost, rdfmenopost, meno.orp, meno.rdp) %>% kable(col.names = cnames) %>% add_header_above(c(" " = 1, " " = 1, "Total number of events / number of patients, treated vs control" = 2, "Pre-menopausal" = 2, "Post-menopausal" = 2, "p-value for subgroup contrast"=2))
Cardiac events. Only non-metastatic patients appear to have adverse effects of biphosphonates (in terms of the odds ratio), but these results are based on very small numbers (only two studies of metastatic patients, with only 26 controls in total)
Dizziness. Adverse effects shown only for non-metastatic patients (odds ratio 2) though the corresponding risk increase is only 1%.
Fatigue. Adverse effects only for metastatic patients (OR 1.6, and risk difference 0.1)
Hypocalcaemia - Adverse effects only for metastatic patients (OR 2.1, and risk difference 0.06)
Increased bone pain - Adverse effects only for non-metastatic patients (OR 1.5 and risk difference 0.2)
Flu-like symptoms - Significant adverse effect only for non-metastatic patients (RD 0.2) though the sample sizes are small for both subgroups.
Neuralgia - result unlikely to be reliable due to tiny numbers of events.
Neutropenia - effect only for metastatic patients, with an estimated 5% risk difference, though note the sample sizes of the metastatic studies were small.
Osteonecrosis - effect only estimated in non-metastatic patients, but the result is unlikely to be reliable due to small numbers of events.
cnames[3:4] <- c("None metastatic", "All metastatic") mares %>% filter(sigbonenone | sigboneall) %>% mutate(bone.orp = round(bone.orp,2), bone.rdp=round(bone.rdp,2)) %>% select(aetype, nbonef, databonenone, databoneall, orfbonenone, rdfbonenone, orfboneall, rdfboneall, bone.orp, bone.rdp) %>% kable(col.names=cnames) %>% add_header_above(c(" " = 1, " " = 1, "Total number of events / number of patients, treated vs control" = 2, "None metastatic" = 2, "All metastatic" = 2, "p-value for subgroup contrast" = 2))
events_base <- c("increased bone pain", "HYPOCALCEMIA", "FATIGUE") brisk0 <- baseres %>% filter(aetype %in% events_base, patient == "Cancer") %>% arrange(match(aetype, events_base)) %>% pull(p) events_meta <- c("Increased bone pain", "Hypocalcemia", "Fatigue") maresbrisk <- mares %>% filter(aetype %in% events_meta) %>% select(aetype, orbonenone, orbonenonel, orbonenoneu, orboneall, orbonealll, orboneallu) %>% arrange(match(aetype, events_meta)) %>% mutate(brisk = brisk0) %>% mutate( trisknone = plogis(qlogis(brisk) + log(orbonenone)), trisknonel = plogis(qlogis(brisk) + log(orbonenonel)), trisknoneu = plogis(qlogis(brisk) + log(orbonenoneu)), triskall = plogis(qlogis(brisk) + log(orboneall)), triskalll = plogis(qlogis(brisk) + log(orbonealll)), triskallu = plogis(qlogis(brisk) + log(orboneallu)), treatedrisknone = sprintf("%s (%s,%s)", 100*round(trisknone,2), 100*round(trisknonel,2), 100*round(trisknoneu,2)), treatedriskall = sprintf("%s (%s,%s)", 100*round(triskall,2), 100*round(triskalll,2), 100*round(triskallu,2)) ) maresbrisk %>% select(aetype, treatedrisknone, treatedriskall) %>% arrange(match(aetype, events_meta)) ## increased bone pain, nonmeta ## OR 1.53 (1.26,1.85) RD 0.02 (0,0.04) ## treated (from RD) 13%(11%,17%) ## plogis(log(0.11/(1-0.11)) + log(c(1.53, 1.26, 1.85))) ## plogis(log(0.113/(1-0.113)) + log(c(1.525, 1.269, 1.848))) ## treated (from OR) 15% (12%, 18%)) ## ## hypocalc, metast ## baseline 4% ## OR 2.14 (1.19,3.85) RD 0.06 (0.03,0.08) ## plogis(log(0.04/(1-0.04)) + log(c(2.14, 1.19, 3.85))) ## treated (from RD) 10% (7%, 12%) ## treated (from OR) 8% (4%, 14%) ## ## fatigue, metast, ## baseline 10% ## OR 1.69 (1.24,2.29) RD 0.11 (0.06,0.17) ## plogis(log(0.1/(1-0.1)) + log(c(1.69, 1.24, 2.29))) ## treated (from RD) 21% (16%, 27%) ## treated (from OR) 16% (12%, 20% ) ##
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.