String wrapping text data in risk table in surv_miner for ggplot2
Asked Answered
T

1

0

I have the following risk table for a Kaplan Meier curve constructed with surv_miner in RStudio:

Kaplan Meier curve

I would like to string wrap the text in the risk table so that the number is on top, and the percentage (in parenthesis) is on another line below the number, so that they all fit in the table. I tried using the stringr package, but I don't quite know how to incorporate that into the theme. Any help would be appreciated. I've posted just my code, since it is a bit tricky to add the actual survival data. However, if the actual data is needed, I will post some dummy data. Thank you in advance.

require("survival")
require("ggplot2")
require("survminer")

fit <- survfit(Surv(Time, Survival) ~ Gender_bin, data = d)
ggsurvplot(fit,
           data = d, 
           pval = TRUE,
           legend.title = "Gender", legend.labs = c("Male", "Female"),
           xlab="Time (years)", ylab="Survival", 
           ggtheme = 
             theme_bw() + 
             theme(plot.title = element_text(hjust = 0.5, face = "bold")) +
             theme(axis.text=element_text(size=14), axis.title=element_text(size=16), axis.title.x=element_blank()) +
             theme(legend.background = element_rect(fill="gray95", size=.5), 
                   legend.text=element_text(size=14), legend.title=element_text(size=14)) +
             theme(aspect.ratio=1),
           xlim = c(0,10), 
           break.time.by = 2.5, 
           legend = c(0.9,0.8),
           risk.table = "abs_pct",
           fontsize = 3.5,
           tables.theme = theme_bw() + theme(aspect.ratio = 0.14) + 
             theme(axis.text=element_text(size=14), axis.title=element_text(size=14)) +
             theme(axis.title.y=element_blank()) +
             theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()))

surv_median(fit)$median
Teetotum answered 21/4, 2018 at 19:7 Comment(1)
This will be a fairly complex task. You will need to find the function that plots the risk table and then figure out the name of the object holding the entries of that table that is internal to the ggplot-object. Then you will need to figure out if the items are held as characters or if there a special function to print the percentages from numeric data. Looking at some of the code I think some names to search for are "mapping" and "survsummary". Personally, I find the plotting routines used by the survival package to be more accessible to this sort of hacking.Russianize
R
1

Got some hacking to apparently work. Decided to use the code you provided with the dataset that is used in the example section of ggsurvplot. Searched for a section that printed the numbers and percentages in parentheses. Looked at:

? ggsurvtable   # the help page
ggsurvtable    # the code
# noticed a call to .plot_survtable(...) assumed it was not exposed for viewing
getAnywhere(.plot_survtable)
# found a section that looked like it would do the work:
else if (survtable == "risk.table") {
    pct.risk <- abs_pct.risk <- n.risk <- NULL
    llabels <- switch(risk.table.type, percentage = round(survsummary$n.risk * 
        100/survsummary$strata_size), abs_pct = paste0(survsummary$n.risk, 
        " (", survsummary$pct.risk, ")"), nrisk_cumcensor = paste0(survsummary$n.risk, 
        " (", survsummary$cum.n.censor, ")"), nrisk_cumevents = paste0(survsummary$n.risk, 
        " (", survsummary$cum.n.event, ")"), survsummary$n.risk)
    survsummary$llabels <- llabels
    mapping <- aes(x = time, y = rev(strata), label = llabels, 
        shape = rev(strata))
}

So then I copied the code and assigned an edited version with "\n" instead of " " in front of each of those "("'s since the counts were first and the pct's were second.

 .plot_survtable <- 
    # the copied and modified code went here

Then I tried to assign the correct environment:

environment(.plot_survtable) <- environment(ggsurvplot)

Tested. Failed to perform as desired so checked the environment assignment and saw that I probably needed to use assignInNamespace instead of environment<-:

 getAnywhere(.plot_survtable)
#2 differing objects matching ‘.plot_survtable’ were found
#in the following places
#  .GlobalEnv
#  namespace:survminer
#Use [] to view one of them
 ?assignInNamespace   # to check the argument list and their types
 assignInNamespace('.plot_survtable', .plot_survtable, "survminer" )

Tested again and now am claiming success!!

enter image description here

The limits were off because I used your code (predicated on years) with an object that had a different time scale (days or months).

Russianize answered 23/4, 2018 at 18:3 Comment(1)
This is great! I had given up and was going to just use the numbers at risk. I haven't had time to incorporate this into my code yet, but I imagine I'll be able to figure it out. Thank you so much!Teetotum

© 2022 - 2024 — McMap. All rights reserved.