Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cens count graph under risk table #18

Closed
MarcinKosinski opened this issue Feb 22, 2016 · 20 comments
Closed

cens count graph under risk table #18

MarcinKosinski opened this issue Feb 22, 2016 · 20 comments

Comments

@MarcinKosinski
Copy link
Contributor

Once I've seen an interesting idea of adding counts of censored observation through time.
@prostkop have prepared such graph on a lecture Technics of Data Visualizations (held on Warsaw University of Technology) https://github.com/pbiecek/TechnikiWizualizacjiDanych/blob/master/MINI_MIMUW_2014/Miniaturka/Faza%203/Szewczyk_Prostko_Ryciak_Ryciuk/3.png

I think it could be a good additional feedback to survival curves, so that one could realize: how do survival curves look like, what is the number of risk set AND what is the cause that the risk set become smaller: is it caused by events or by censored events ?

So the final ggsurvplot could consist of 3 plots: KM-curves, risk.table + cens density/barplot?

@kassambara
Copy link
Owner

The final ggsurvplot would look like this:

library(RTCGA) 
library(RTCGA.clinical)
library(survminer)

BRCAOV.survInfo <- survivalTCGA(BRCA.clinical, OV.clinical, 
                                extract.cols = "admin.disease_code") 
# Survival curves + risk table
fit <- survfit(Surv(times, patient.vital_status)~admin.disease_code,
               data = BRCAOV.survInfo)
surv.curv <- ggsurvplot(fit, pval = TRUE, conf.int = TRUE,
           risk.table = TRUE, legend.labs = c("brca", "ov"))

# n.censor.plot
d <- data.frame(time = fit$time,
                n.censor = fit$n.censor,
                strata = as.factor(rep(names(fit$strata), fit$strata)))

ncensor.plot <- ggplot(d, aes(time, n.censor)) + 
  geom_bar(aes(color = strata, fill = strata), stat = "identity", position = "dodge") +
  theme_classic() +  theme(legend.position = "none") 

# Arrange plots
gridExtra::grid.arrange(surv.curv$plot, surv.curv$table, ncensor.plot, heights = c(0.5, 0.25, 0.25))

rplot

Do you have any suggestion about the plot?
Thanks:-)

@MarcinKosinski
Copy link
Contributor Author

@prostkop what do You think about that :)?

@MarcinKosinski
Copy link
Contributor Author

cens.density = FALSE by defualt :) for me it looks interesting. I am wondering whether bars could be replaced with geom_denisty? What do You think? And You @prostkop?

Marcin Kosinski

Dnia 25.02.2016 o godz. 13:10 Alboukadel KASSAMBARA notifications@github.com napisał(a):

The final ggsurvplot would look like this:

library(RTCGA)
library(RTCGA.clinical)
library(survminer)

BRCAOV.survInfo <- survivalTCGA(BRCA.clinical, OV.clinical,
extract.cols = "admin.disease_code")

Survival curves + risk table

fit <- survfit(Surv(times, patient.vital_status)~admin.disease_code,
data = BRCAOV.survInfo)
surv.curv <- ggsurvplot(fit, pval = TRUE, conf.int = TRUE,
risk.table = TRUE, legend.labs = c("brca", "ov"))

n.censor.plot

d <- data.frame(time = fit$time,
n.censor = fit$n.censor,
strata = as.factor(rep(names(fit$strata), fit$strata)))

ncensor.plot <- ggplot(d, aes(time, n.censor)) +
geom_bar(aes(color = strata, fill = strata), stat = "identity", position = "dodge") +
theme_classic() + theme(legend.position = "none")

Arrange plots

gridExtra::grid.arrange(surv.curv$plot, surv.curv$table, ncensor.plot, heights = c(0.5, 0.25, 0.25))

Do you have any suggestion about the plot?
Thanks:-)


Reply to this email directly or view it on GitHub.

@MarcinKosinski
Copy link
Contributor Author

I think this 3rd plot should have the same width of axis as the first 2 containing survival curves and risk table

@prostkop
Copy link

Definitely, last plot should be in line with others. In addition, on the 3rd plot number of censoring is hardly visible, because of a peak in the beginning of the study. Maybe, some "algorithm" should be applied to mark "outlying" bars and decrease their heights. But essentially, it is very nice plot :)

@MarcinKosinski
Copy link
Contributor Author

And in my opinion colours of the last plot should vary from the colours of the survival curves, so to avoid confusion :)

@kassambara
Copy link
Owner

Yes, I completely agree with you!! This was a quick arrangement of the plots for discussion... I'll work in the script to improve the final output!

Thanks :)!

@MarcinKosinski
Copy link
Contributor Author

Hey, have you tried working on that :)?

@kassambara
Copy link
Owner

Hi Marcin,

I think that plotting the number of censor events, at each time point, can be really unreadable in a situation where you have a large cohort of patients with multiple groups.

For example (option 1):

library(survival)
library(survminer)
fit <- survfit( Surv(time, status) ~ rx + adhere,
                 data = colon )
surv.curv <- ggsurvplot(fit, risk.table = TRUE, risk.table.col = "strata",
                      break.time.by = 500)
surv.curv

rplot

The plot of censor events:

# ncensor data
d <- data.frame(time = fit$time,
                n.censor = fit$n.censor,
                strata = as.factor(rep(names(fit$strata), fit$strata)))

ggplot(d, aes(time, n.censor)) + 
  geom_bar(aes(color = strata, fill = strata), stat = "identity", position = "dodge") +
  theme_bw() +
  ggplot2::theme(legend.position = "none")

rplot01

However, we can plot the number of censor event at specific time points to make the plot more readable (option 2):

times <- ggplot_build(surv.curv$plot)$panel$ranges[[1]]$x.major_source

# n.censor.plot
fit_summary <- summary(fit, times = times, extend = TRUE)
d <- data.frame(time = as.factor(fit_summary$time),
                n.censor = fit_summary$n.censor,
                strata = factor(fit_summary$strata)
                  )

# bar plot of censor events
ggplot(d, aes(time, n.censor)) + 
  geom_bar(aes(color = strata, fill = strata), stat = "identity", position = "dodge") +
  theme_classic() +
  ggplot2::theme(legend.position = "none")

# line plot of censor events
d$time <- fit_summary$time
ggplot(d, aes(time, n.censor)) + 
  geom_line(aes(color = strata))+
  theme_classic() +
  ggplot2::theme(legend.position = "none")

Bar plot:

rplot02

Line plot:

rplot03

The final plot would look like as follow:

# censor plot
cens.plot <- ggplot(d, aes(time, n.censor)) + 
  geom_line(aes(color = strata))+
  theme_classic() +
  ggplot2::theme(legend.position = "none")+
  coord_cartesian(xlim = c(0, max(fit$time))) +
  ggplot2::scale_x_continuous(breaks = times)+
  theme(legend.key.height = NULL, legend.key.width = NULL,
       legend.key = element_rect(colour = NA, fill = NA),
       legend.text = element_text(colour = NA),
       legend.title = element_text(colour = NA)) +
  guides(color = FALSE)

# Arrange plots
x <- list(ncensor = cens.plot, table = surv.curv$table, plot = surv.curv$plot)
plots <- rev(x)
grobs <- widths <- list()
for (i in 1:length(plots)) {
  grobs[[i]] <- ggplotGrob(plots[[i]])
  widths[[i]] <- grobs[[i]]$widths[2:5]
}
maxwidth <- do.call(grid::unit.pmax, widths)
for (i in 1:length(grobs)) {
  grobs[[i]]$widths[2:5] <- as.list(maxwidth)
}
do.call(gridExtra::grid.arrange, c(grobs, nrow = 3, heights = list(c(0.5, 0.25, 0.25))))

rplot05

What do you think about option 2?

@MarcinKosinski
Copy link
Contributor Author

I think line plot and barplot are great ideas :) There could be a parameter censor.type = c('line', 'barplot') ? Great job!

@prostkop do you have any suggestions?

@kassambara
Copy link
Owner

Ok! I'm adding these options in ggsurvplot function:-)!

@MarcinKosinski
Copy link
Contributor Author

Great! Thanks :)

2016-03-23 17:26 GMT+01:00 Alboukadel KASSAMBARA notifications@github.com:

Ok! I'm adding these options in ggsurvplot function:-)!


You are receiving this because you authored the thread.
Reply to this email directly or view it on GitHub
#18 (comment)

@prostkop
Copy link

Sorry for a litle delay. Indeed, plot looks really tidy and nice. I don't have time to run your example, but do you choose some specific time points for n.cesoring plot and between these points linear interpolations is used ? How about using all time points with censoring ? Probably, plot will be more irregular, but maybe more reliable ?

@MarcinKosinski
Copy link
Contributor Author

@kassambara can we close this issue? Is that feature avaiable?

@kassambara
Copy link
Owner

Hi!!
I will finalize this in v0.2.2. I planed to submit v0.2.1 to CRAN tomorrow. I updated the Readme.Rmd and built a staticdocs (http://www.sthda.com/english/rpkgs/survminer/) so that users can check out the documentation and usage examples of each function in survminer package.

@MarcinKosinski
Copy link
Contributor Author

Wow, this looks great. Can you explain how this was created and is it the
same tool as for ggplo2 documentation?

  1. I was about to suggest you to use readthedocs for
    documentation - what do you think about that?
    1a) I was also thinking about a website for survminer package. It can be
    hosted on github pages (or wherever you have bought hosting). It can be
    done in jekyll (using jekyll-knitr (motivation, themes to choose from). I have experience with jekyll since I have
    created 2 websites using that tool
  1. Thanks for adding me to authors. This is like an award for me, since
    this package is really great (and even though survMisc is available on
    CRAN again) . I was showing this package during "R workshops for young
    biotechnologists" that I have lead today and yesterday in Warsaw.
    Moreover, I would like to contribute more with this package.
    2a) I think to have complete cox analysis we could also add something like
    ggcoxNAME for full (simple) coxph model diagnostics like plots of
    residuals vs linear combinations of explanatory variables.

  2. I know that you were planning to blog about survminer soon. I also was
    thinking about additional blog post. More posts, more users :) Maybe it
    would be good not to post our both posts in the same week?

I know I've mentioned a lot of topics. You can split answers to separate
issues.

PS. Have you thought about attending eRum :) http://erum.ue.poznan.pl/?

2016-04-22 0:04 GMT+02:00 Alboukadel KASSAMBARA notifications@github.com:

Hi!!
I will finalize this in v0.2.2. I planed to submit v0.2.1 to CRAN
tomorrow. I updated the Readme.Rmd and built a staticdocs (
http://www.sthda.com/english/rpkgs/survminer/) so that users can check
out the documentation and usage examples of each function in survminer
package.


You are receiving this because you authored the thread.
Reply to this email directly or view it on GitHub
#18 (comment)

@kassambara
Copy link
Owner

kassambara commented Apr 22, 2016

I used the R package staticdocs, developed by Hadley Wickham, to build survminer documentation website. ggplot2 online documentation has been built using the same package.

The job is simply done using the following R code:

staticdocs::build_site(pkg =  "local/path/to/survminer", site_path = "path/to/site/directory")
  1. It would be nice to build a website for survminer. I have not tried yet jekyll but I have to:-)! I think that hosting on github is the best option.

  2. You have made significant contributions to the package. Thank you for your great work!!

  3. I agree with you (see Blog post about the short history of how survival plots were improved between survminer ver 0.1 and ver 0.2? #34 )

PS. I'm not sure to attend eRum

Best,
A.

@MarcinKosinski
Copy link
Contributor Author

I think this is still an interesting feature and we could think about it in ver 0.2.3 ? :)

@kassambara
Copy link
Owner

New argument 'ncensor.plot' added to ggsurvplot(). A logical value. If TRUE, the number of censored subjects at time t is plotted. Default is FALSE.

require("survival")
fit<- survfit(Surv(time, status) ~ sex, data = lung)
ggsurvplot(fit, risk.table = TRUE, ncensor.plot = TRUE, risk.table.height = 0.35)

rplot

@MarcinKosinski
Copy link
Contributor Author

Marvelous :) Keep going @kassambara
Your on a programming spree :D

kassambara pushed a commit that referenced this issue Jan 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants
@kassambara @MarcinKosinski @prostkop and others