kassambara / survminer

Survival Analysis and Visualization
https://rpkgs.datanovia.com/survminer/
506 stars 162 forks source link

ggsurvplot and cox model #109

Closed kassambara closed 7 years ago

kassambara commented 7 years ago

(e-mail from a survminer user)

Great package. I've got the cumulative incidence curve almost as I want to. It's just That I would like to change color of my two prediced curves. I've tried many different palette = "x", including "Dark2" and "RdBu", but only "hue" works, the others return Error: breaks and labels must have the same length

I base the curve on a coxph-object (i.e. predict.survfit.coxph) and also include strata() in the cox formula and use Surv(time1, time2, event) to allow late entry. I've checked so the curves are correct and the risk-table is correct too. But I really would like to change the color.

I attach the output and present the code bellow.

Would be very grateful if you could have a look.

b_strat_F_adj <- coxph(Surv(time, time_stop, outcome7) ~ strata(Fina) + psa_log*age_entry + age_entry + psa_log + PrevNegBiopsy, data = b1)

newdata <- data.frame(Fina = c(1, 0), PrevNegBiopsy = c(0, 0), age_entry = c(60, 60), psa_log = c(1, 1))

surv <- survfit(b_strat_F_adj, newdata=newdata)

qq <- ggsurvplot(surv, fun = "event", ylim = c(0, .03), censor = FALSE, risk.table = "absolute", legend = "bottom", legend.title = "Finasteride", legend.labs = c("Yes", "No"), risk.table.col = "strata", risk.table.y.text.col = TRUE, risk.table.y.text = FALSE, conf.int = TRUE, conf.int.style = "step",

palette = "Dark2")

2017-01-15_2236

kassambara commented 7 years ago

This error is reproducible using the heart data in the survival package

library(survival)
library(survminer)
cox_heart <- coxph(Surv(start, stop, event) ~ age + surgery + strata(transplant), heart)

newdata = data.frame(age = c(50, 50), surgery = c(1, 1), transplant = c("0", "1"))
surv <- survfit(cox_heart, newdata=newdata)

qq <- ggsurvplot(surv,
                 fun = "event",
                 censor = FALSE,
                 risk.table = "absolute",
                 legend = "bottom",
                 legend.title = "Transplant",
                 legend.labs = c("Yes", "No"),
                 risk.table.col = "strata",
                 risk.table.y.text.col = TRUE,
                 risk.table.y.text = FALSE,
                 conf.int = TRUE,
                 conf.int.style = "step",
                 palette = "Dark2"
)
qq 
pbiecek commented 7 years ago

The error is caused by color scales. In fact is is caused by this if (line 453)

     if(inherits(fit, "survfit.cox")) {
       legend.labs <- "All"
       risk.table.y.text.col <- FALSE
     }

For cox model the legend.labs shall be c("Yes", "No") but are overridden by "All". So then when the color scale is constructed (due to palette = "Dark2") the scale have two colors but one label (label="All").

Is the legend.labs <- "All" really needed?

kassambara commented 7 years ago

Thank you for this very good diagnostic! I should work on optimizing ggsurvplot() in handling the outputs of survfit.coxph()!

pbiecek commented 7 years ago

Regarding coxph models, By any chance, are you working on #67 (code suggested by markdanese)? (maybe it’s already included to survminer) It would be nice to have such curves (=I would like to use them ;-)). I can add them if you are not working on this already. I’m not a data.table user but markdanese’s code should be easy and straightforward to convert it to base R/dplyr.

kassambara commented 7 years ago

Hi @pbiecek ,

I'm not working on it.. So, it would be great if you can convert it and include it to survminer:-)!

kassambara commented 7 years ago

Now, ggsurvplot() works properly in the situation where strata() is included in the cox formula.

Example:

library(survival)
res.cox <- coxph(Surv(time, status) ~ age + strata(sex) + ph.ecog, data =  lung)

sex_df <- with(lung,
               data.frame(sex = c(1, 2), 
                          age = rep(mean(age, na.rm = TRUE), 2),
                          ph.ecog = c(1, 1)
               )
)
fit <- survfit(res.cox, newdata = sex_df)

library(survminer)
ggsurvplot(fit, conf.int = TRUE, legend.labs=c("Sex=1", "Sex=2"),
           risk.table = TRUE,
           palette = "Dark2",
           ggtheme = theme_minimal())

rplot01