#library(pander) #library(printr) #library(wakefield) suppressPackageStartupMessages(suppressMessages(suppressWarnings({ library(dplyr) library(ggplot2) library(riskscorer) library(wakefield) library(threejs) }))) knitr::opts_chunk$set(fig.width = 6, fig.height = 5, cache=FALSE, echo = FALSE)
The package riskscorer is a set of functions to provide an easy programmatical interface to clinical risk models. It supports fuzzy argument matching and is webservice ready via plumber decoration. A the moment two operative risk scores in cardiac surgery are implemented:
The following less used scores are under development:
The programmatical interface can be used in various scenarios:
The simulated patients have the following characteristics:
The graphs plot the probability of 30d mortality against the left ventricular function and creatinine value.
n = 5#23 grid_df <- expand.grid(crea = rep(seq(0.8, 3, length.out = n)), lvef = rep(seq(10, 60, length.out = n)), gender = c("Male", "Female")) df_sim <- grid_df %>% as.data.frame %>% as.tbl df_sim$age = 75 df_sim$proc_cabg = TRUE df_sim$proc_valve = "AVR" df_sim$chf_2w = TRUE df_sim$height_cm = 170 df_sim$weight_kg = 75 sims <- df_sim %>% group_by(lvef, crea, gender) %>% do( calc_sts(proc_valve = .$proc_valve, proc_cabg = .$proc_cabg, age = .$age, gender = .$gender, chf_2w = .$chf_2w, crea = .$crea, height_cm = .$height_cm, weight_kg = .$weight_kg, lvef = .$lvef) #data_frame(proc_valve = .$VALVE, proc_cabg = .$CABG, age = .$Age, gender = .$Sex, crea = .$crea, lvef = .$lvef) ) sims_long <- tidyr::gather(data = sims, key = Risk, value = probability, Mortality:Short_LOS) prom <- sims_long %>% dplyr::filter(Risk == "Mortality") threejs::scatterplot3js(y = prom$crea, x= prom$lvef, z = prom$probability, color = ifelse(prom$gender == "Male", "lightblue", "red"), grid ="TRUE", labels=sprintf("Sex=%s, Crea=%.2f mg/dL, LVEF=%.2f %%, PROM=%.2f %%", prom$gender, prom$crea, prom$lvef, prom$probability*100), renderer = "canvas") #plotly::3d # plot3D::scatter3D(y = prom$crea, x= prom$lvef, z = prom$probability) # plot3D::scatter3D(y = prom$crea, x= prom$lvef, z = prom$probability, # phi = 40, theta = 70) # plot3D::scatter3D(y = prom$crea, x= prom$lvef, z = prom$probability, # phi = 0, theta = 70) # plot3D::scatter3D(y = prom$crea, x= prom$lvef, z = prom$probability, # phi = -20, theta = 70) # plot3D::scatter3D(y = prom$crea, x= prom$lvef, z = prom$probability, # phi = -30, theta = 70) # prom_gen <- prom %>% dplyr::filter(gender == "Female") # plot3D::scatter3D(y = prom_gen$crea, x= prom_gen$lvef, z = prom_gen$probability, # theta = 50, phi = 10, ticktype = "detailed", bty = "f", # zlim = c(0, 0.1), d=2, pch=1, # main ="STS Scores", # xlab = "LVEF [%]", # ylab = "Crea [mg/dL]", # zlab = "STS PROM %", # clab = "STS PROM %") # prom_gen <- prom %>% dplyr::filter(gender == "Male") # plot3D::scatter3D(y = prom_gen$crea, x= prom_gen$lvef, z = prom_gen$probability, # theta = 50, phi = 10, pch = 16, add = TRUE, colkey = FALSE) # library(ggplot2) # ggplot(prom, aes(x = lvef, y = crea, z = probability, fill = probability)) + # facet_wrap(~ gender) + # geom_raster() + # scale_fill_gradient("STS PROM %", low = "red", high = "yellow") + # geom_contour(color = "black", bins = 20) + # labs(x = "LVEF [%]", y = "Crea [mg/dL]") + # theme_minimal() # # # library(lattice) # lattice::wireframe(probability ~ lvef + crea, data = prom, # groups = gender, # drape = TRUE, # colorkey = TRUE, # shade = FALSE, # xlab = "LVEF [%]", # ylab = "Crea [mg/dL]", # zlab = "STS PROM %") # # scatterplot3d::scatterplot3d(y = prom$crea, # x= prom$lvef, # z = prom$probability, # #highlight.3d=TRUE, # grid = TRUE, pch=16, # box = FALSE,#type = "l", # color = ifelse(prom$gender == "Male", "blue", "red"))
The simulated patients have the following characteristics:
The graphs plot the probability of each risk category against the gender and creatinine value.
n = 3#23 grid_df <- expand.grid(crea = rep(seq(0.8, 3, length.out = n)), gender = c("Male", "Female")) df_sim <- grid_df %>% as.data.frame %>% as.tbl df_sim$age = 75 df_sim$lvef = 45 df_sim$proc_cabg = TRUE df_sim$proc_valve = "AVR" df_sim$chf_2w = TRUE df_sim$height_cm = 170 df_sim$weight_kg = 75 sims <- df_sim %>% group_by(crea, gender) %>% do( calc_sts(proc_valve = .$proc_valve, proc_cabg = .$proc_cabg, age = .$age, gender = .$gender, chf_2w = .$chf_2w, crea = .$crea, height_cm = .$height_cm, weight_kg = .$weight_kg, lvef = .$lvef) ) sims_long <- tidyr::gather(data = sims, key = Risk, value = probability, Mortality:Short_LOS) qplot(x = crea, y = probability, facets = ~gender, color = Risk, data = sims_long, geom = c("line")) + theme_bw() qplot(x = crea, y = probability, facets = ~Risk, color = gender, data = sims_long, geom = c("line")) + theme_bw()
The simulated patients have the following characteristics:
set.seed(5) n = 3 df_sim_tavi <- r_data_frame( n = n, age(x = 78:100), sex, lvef = round(rnorm(n = n, mean = 50, sd = 10), digits = 0), crea = round(rnorm(n = n, mean = 1.2, sd = 0.2), digits = 3), valid(name = "chf_2w", prob = c(0.1,0.9)) ) df_sim_tavi$Patient = 1:(nrow(df_sim_tavi)) df_sim_tavi$CABG = FALSE df_sim_tavi$VALVE = "AVR" df_sim_cabg <- r_data_frame( n = n, age(x = 40:70), sex, lvef = round(rnorm(n = n, mean = 50, sd = 10), digits = 0), crea = round(rnorm(n = n, mean = 0.8, sd = 0.1), digits = 3), valid(name = "chf_2w", prob = c(0.8,0.2)) ) df_sim_cabg$Patient = (nrow(df_sim_tavi)+1):(nrow(df_sim_tavi) + nrow(df_sim_cabg)) df_sim_cabg$CABG = TRUE df_sim_cabg$VALVE = FALSE sims <- rbind(df_sim_cabg, df_sim_tavi) %>% group_by(Patient) %>% do( calc_sts(proc_valve = .$VALVE, proc_cabg = .$CABG, age = .$Age, gender = .$Sex, chf_2w = .$chf_2w, crea = .$crea, lvef = .$lvef) #data_frame(proc_valve = .$VALVE, proc_cabg = .$CABG, age = .$Age, gender = .$Sex, crea = .$crea, lvef = .$lvef) ) tab_view <- sims %>% dplyr::rename(STS_Risk_Model = Procedure) %>% dplyr::arrange(Patient, Mortality) knitr::kable(tab_view %>% dplyr::select(Patient, Risk_Model = STS_Risk_Model, Mort = Mortality, Mort_Morb = Morbidity_Mortality , Stroke = Perm_Stroke, Long_Vent = Prolong_Vent, ReOP=Reoperation, Renal_failure, DSW_Infect=DSW_Infection, Long_LOS)) # library(dendextend) # km <- kmeans(dplyr::select(tab_view, -Patient, -STS_Risk_Model) %>% dist, centers = 2) # km # dend <- dplyr::select(tab_view, -Patient, -STS_Risk_Model) %>% dist(method = "maximum") %>% hclust(method = "average") %>% as.dendrogram # dend %>% set("branches_k_color") %>% plot # dend %>% set("branches_k_color") %>% rect.dendrogram(k=2, border = 8, lty = 5, lwd = 2) %>% plot p <- radial_plot(sims %>% dplyr::select(-Short_LOS, -Procedure) %>% dplyr::rename(group = Patient) %>% as.data.frame, grid.min = 0, grid.max = 0.3,legend.title = "Patient", plot.extent.x = 1.7, plot.extent.y = 1.2, label.centre.y = FALSE, centre.y = -0.1, group.line.width = 0.1, group.point.size = 2 ) p
The STS(The Society of Thoracic Surgeons) score is a collection of validated risk models that are regulary updated based on the broad data base of the STS.The online STS adult cardiac surgery risk calculator is an Angular single page application, which collects the parameters and commincates via JSON to a a web-service("http://riskcalc.sts.org/stswebriskcalc/v1/calculate/stsall ") to obtain the scores.
The STS score calculation in the riskscorer package is realized by providing a user friendly programmatical interface to the web-service. The programming interface is able to handle most of data codings automatically. Simple heuristics translate common clinical factor codings. For example "Female", "female" or "f" will all be detected as female gender. Boolean variables such as '0', '1', 'True', 'T', "Y", "Yes" will be detected. Each parameter is described in detail at the corresponding function documentation. Once the score is calculated, a data frame is returned, making it easy to work with the pipe and dplyr.
Terms of use of STS web calculator does not permit the use of the web-service at the moment of writing this vignette. Keep in mind, that this might change and consider to check the terms of use at the STS score website before using the function.
Thanks to the fantastic plumber package, every score calculation function can be easily used as a web service. The hosting of such a service is well documented at the plumber documentation.
The risk calculation of the EuroScore II is based on a logistic regression model and the coefficients are published in doi:10.1093/ejcts/ezs043. Therefor one can easily use the published coefficients and impose a robust R interface over the model.
n = 5 grid_df <- expand.grid(crea = rep(seq(0.8, 3, length.out = n)), lvef = rep(seq(10, 60, length.out = n)), gender = c("Male", "Female")) df_sim <- grid_df %>% as.data.frame %>% as.tbl v_cc_eGFR <- Vectorize(cc_eGFR) df_sim$age = 75 df_sim$proc_cabg = TRUE df_sim$proc_valve = TRUE df_sim$urgency = "elective" df_sim$height_cm = 170 df_sim$weight_kg = 75 df_sim$sPAP = 33 df_sim$renal = v_cc_eGFR(crea = df_sim$crea, weight = df_sim$weight_kg, age = df_sim$age, sex = df_sim$gender) sims <- df_sim %>% group_by(lvef, crea, gender) %>% do( data_frame(Mortality = calc_esII(valve_surgery = .$proc_valve, CABG = .$proc_cabg, age = .$age, gender = .$gender, renal = .$renal, sPAP = .$lvef, urgency = .$urgency, lv = .$lvef)) #data_frame(proc_valve = .$VALVE, proc_cabg = .$CABG, age = .$Age, gender = .$Sex, crea = .$crea, lvef = .$lvef) ) #sims_long <- tidyr::gather(data = sims, key = Risk, value = probability, Mortality:Short_LOS) threejs::scatterplot3js(y = sims$crea, x= sims$lvef, z = sims$Mortality, color = ifelse(sims$gender == "Male", "lightblue", "red"), grid ="TRUE", labels=sprintf("Sex=%s, Crea=%.2f mg/dL, LVEF=%.2f %%, PROM=%.2f %%", sims$gender, sims$crea, sims$lvef, sims$Mortality*100), renderer = "canvas") #qplot(x = lvef, y = Mortality, facets = ~gender, color = crea, data = sims, geom = c("point")) + theme_bw() middle <- function(x) { r <- range(x) (abs(r[2] - r[1])/2) + r[1] } ggplot(data = sims, aes(x=lvef, y=crea, fill=Mortality)) + geom_tile() + theme_minimal() + #geom_point(aes(size = Mortality)) + facet_wrap(facets = ~ gender) + scale_fill_gradient2(low = "blue", high = "red", mid = "white", midpoint = middle(sims$Mortality), space = "Lab", name="EuroScore II\nMortality")
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.