Closed kassambara closed 8 years ago
In the current version it's possible to facet by strata, as follow:
require("survival")
library("survminer")
fit2 <- survfit( Surv(time, status) ~ rx, data = colon )
ggsurv <- ggsurvplot(fit2, conf.int = TRUE)
# Facet
ggsurv$plot + theme_bw()+facet_wrap(~strata)
We'll work on it to make faceting possible with a combination of factors.
To make faceting possible with a combination of factors, we'll update survminer as follow:
Add a new function surv_summary(): Compared to the default summary() function, surv_summary(), will create a data frame containing a nice summary from survfit results.
This (new) helper function will be used in ggsurvplot() to summarize survival curves.
In a situation, where survival curves have been fitted with one or more variables, surv_summary object contains extra columns representing the variables.
An example might be:
# Fit survival curves
require("survival")
fit <- survfit(Surv(time, status) ~ rx + adhere, data = colon)
# Summarize
res.sum <- surv_summary(fit)
head(res.sum)
time n.risk n.event n.censor surv std.err upper lower strata rx adhere 1 20 536 1 0 0.9981343 0.001867414 1.0000000 0.9944878 rx=Obs, adhere=0 Obs 0 2 43 535 1 0 0.9962687 0.002643394 1.0000000 0.9911204 rx=Obs, adhere=0 Obs 0 3 45 534 1 0 0.9944030 0.003240519 1.0000000 0.9881072 rx=Obs, adhere=0 Obs 0 4 59 533 1 0 0.9925373 0.003745345 0.9998501 0.9852780 rx=Obs, adhere=0 Obs 0 5 72 532 1 0 0.9906716 0.004191364 0.9988435 0.9825667 rx=Obs, adhere=0 Obs 0 6 77 531 1 0 0.9888060 0.004595738 0.9977529 0.9799393 rx=Obs, adhere=0 Obs 0
Note that, supplementary columns (rx, adhere) have been added.
This makes it possible to facet the output of ggsurvplot by strata or by some combinations of factors.
An example might be:
# Facet by strata
ggsurv$plot + theme_bw()+facet_wrap(~strata)
# Facet by treatment rx
ggsurv$plot + theme_bw()+facet_wrap(~rx)
That sounds great Alboukadel! Thanks so much for your effort and generosity to implement this feature, further improving what is already a stellar package.
Faceting should work now.
devtools::install_github("kassambara/survminer")
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# Facet ggsurvplot() output by
# a combination of factors
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# Fit (complexe) survival curves
#++++++++++++++++++++++++++++++++++++
require("survival")
fit3 <- survfit( Surv(time, status) ~ sex + rx + adhere,
data = colon )
# Visualize: plot survival curves by sex and facet by rx and adhere
#++++++++++++++++++++++++++++++++++++
ggsurv <- ggsurvplot(fit3, fun = "cumhaz", conf.int = TRUE)
ggsurv$plot +theme_bw() + facet_grid(rx ~ adhere)
It looks like this:
Best, /A
A magnificence masterpiece :O I'm amazed. Great that you are still working on survminer
and providing such an informative messages during the issue's conversation.
I am wondering how this can be displayed with risk tables? Do you think that 1 risk table under all plots is better than plotting as many risk tables as there are columns of graphs after faceting?
Thank you Marcin, I appreciate your positive comment!!
I will work on that, it should be possible to suggest something about facet + risk tables!
ggurvplot() returns a list of two different ggplots:
It's now possible to apply facet to the two components plot and table. I think that, it's not possible to combine items of two different facets.
In trying to answer to your question, survminer now makes it possible to apply faceting as follow.
If it's ok, then we can close this issue:-)! Best, /A
# Fit (complexe) survival curves
#++++++++++++++++++++++++++++++++++++
require("survival")
fit <- survfit( Surv(time, status) ~ sex + rx + adhere,
data = colon )
# Visualize
#++++++++++++++++++++++++++++++++++++
require("survminer")
ggsurv <- ggsurvplot(fit3, fun = "cumhaz", conf.int = TRUE,
risk.table = TRUE, risk.table.col="strata",
ggtheme = theme_bw())
# Faceting survival curves
curv_facet <- ggsurv$plot + facet_grid(rx ~ adhere)
curv_facet
# Faceting risk tables:
# Generate risk table for each facet plot item
ggsurv$table + facet_grid(rx ~ adhere, scales = "free")+
theme(legend.position = "none")
# Generate risk table for each facet columns
tbl_facet <- ggsurv$table + facet_grid(.~ adhere, scales = "free")
tbl_facet + theme(legend.position = "none")
# Arrange faceted survival curves and risk tables
g2 <- ggplotGrob(curv_facet)
g3 <- ggplotGrob(tbl_facet)
min_ncol <- min(ncol(g2), ncol(g3))
g <- gridExtra::rbind.gtable(g2[, 1:min_ncol], g3[, 1:min_ncol], size="last")
g$widths <- grid::unit.pmax(g2$widths, g3$widths)
grid::grid.newpage()
grid::grid.draw(g)
To add risk table in each facet item, we should implement an option in the future to place the risk table inside the Kaplan-Meier curve, so that risk table can propagate with facet items.
I think that it's not a good idea to place the risk table inside the KM curve, the final plot is unreadable. So we can close this issue.
I'm trying to reproduce this example, but using the code
require("survival")
require("survminer")
fit3 <- survfit( Surv(time, status) ~ sex + rx + adhere, data = colon )
ggsurv <- ggsurvplot(fit3, fun = "cumhaz", conf.int = TRUE,
risk.table = TRUE, risk.table.col="strata",
ggtheme = theme_bw())
ggsurv$plot + facet_grid(rx ~ adhere)
throws this error:
Error in f(...) : Aesthetics can not vary with a ribbon
I get the same message when trying on my own dataset.
Am I doing it wrong ?
try using strata sometimes the extraction of strata into column names can fail. I also show how you can do something similar more flexible in geom_km ( it understands, grouping, color, fill etc) up to you to decide how to split the plot using ggplot synthax without a survfit object. ( no risk table and other advanced features) also up to you to ensure variables are factor or continous etc.
require("survival")
#> Loading required package: survival
require("survminer")
#> Loading required package: survminer
#> Loading required package: ggplot2
#> Loading required package: ggpubr
#> Loading required package: magrittr
require("ggquickeda")
#> Loading required package: ggquickeda
#>
#> Attaching package: 'ggquickeda'
#> The following object is masked from 'package:base':
#>
#> +
fit3 <- survfit( Surv(time, status) ~ sex + rx + adhere, data = colon )
ggsurv <- ggsurvplot(fit3, fun = "cumhaz", conf.int = TRUE)$plot + facet_wrap(~ strata)
ggsurv
ggplot(colon, aes(time = time, status = status)) +
geom_km()+
geom_kmband()+
geom_kmticks()+
facet_grid(~ sex + rx + adhere)
ggplot(colon, aes(time = time, status = status,fill=sex,color=sex,group=sex)) +
geom_km()+
geom_kmband()+
geom_kmticks()+
facet_grid(rx ~ adhere)
Created on 2019-03-20 by the reprex package (v0.2.1)
try using strata sometimes the extraction of strata into column names can fail. I also show how you can do something similar more flexible in geom_km ( it understands, grouping, color, fill etc) up to you to decide how to split the plot using ggplot synthax without a survfit object. ( no risk table and other advanced features) also up to you to ensure variables are factor or continous etc.
require("survival") #> Loading required package: survival require("survminer") #> Loading required package: survminer #> Loading required package: ggplot2 #> Loading required package: ggpubr #> Loading required package: magrittr require("ggquickeda") #> Loading required package: ggquickeda #> #> Attaching package: 'ggquickeda' #> The following object is masked from 'package:base': #> #> + fit3 <- survfit( Surv(time, status) ~ sex + rx + adhere, data = colon ) ggsurv <- ggsurvplot(fit3, fun = "cumhaz", conf.int = TRUE)$plot + facet_wrap(~ strata) ggsurv
ggplot(colon, aes(time = time, status = status)) + geom_km()+ geom_kmband()+ geom_kmticks()+ facet_grid(~ sex + rx + adhere)
ggplot(colon, aes(time = time, status = status,fill=sex,color=sex,group=sex)) + geom_km()+ geom_kmband()+ geom_kmticks()+ facet_grid(rx ~ adhere)
Created on 2019-03-20 by the reprex package (v0.2.1)
OMG this is definitely what I want! ggsurvplot() is great but it's still not the real "facet". Both are great anyway, thanks!
How to facet the output by strata or some combination of factors , for example sex ~ treatment, like this: