-
Notifications
You must be signed in to change notification settings - Fork 21
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
Feature request: Combine multiple survfits #212
Comments
Hi @DanChaltiel , thanks for the post! I think this is something that people would need, so we should think on the best way to implement. Certainly, the easiest way for me to maintain is ask the users to do some pre-processing and create a data frame that is one line per subject per outcome. The data frame would include a column indicating which outcome the row is associated with. We can then pass that data frame to Maybe we simply add a helper function to do this pre-processing? Minimally, we can add an example to the gallery showing how to do the pre-processing. What do you think? library(ggsurvfit)
#> Loading required package: ggplot2 packageVersion("ggsurvfit")
#> [1] '1.1.0' # create a stacked data frame with 2 outcomes
stacked_adtte <-
adtte |>
dplyr::select(USUBJID, PARAM, AVAL, CNSR) %>%
dplyr::bind_rows(
.,
dplyr::mutate(
.,
AVAL = AVAL / (1 + runif(dplyr::n())),
PARAM = "Overall survival (years)"
)
)
survfit2(Surv_CNSR(AVAL, CNSR) ~ PARAM, data = stacked_adtte) |>
ggsurvfit() +
add_confidence_interval() +
add_risktable() +
scale_ggsurvfit() Created on 2024-05-17 with reprex v2.1.0 |
Oh you are right, you can simply stack the data! I'm not sure about how the interface should look like though. In the end, you would input your couples somehow like this: survs = list(
"Overall survival (years)"=c("os.time", "os.status"),
"Progression-free survival (years)"=c("pfs.time", "pfs.status")
)
stacked_adtte = stack_surv(adtte, survs=survs) |
Couple of things to consider:
Anyway, I'll leave this issue open for now. But to be honest, no plans to implement in the immediate future (just to set expectations!) |
No problem, this is perfectly understandable! library(tidyverse)
library(ggsurvfit)
stack_surv = function(data, surv_list){
surv_list %>%
imap(~{
if(length(.x)==2){
df = data %>%
select(stacked_time = all_of(.x[1]),
stacked_event = all_of(.x[2])) %>%
mutate(stacked_survtype=.y)
} else if (length(.x) == 3){
df = data %>%
select(stacked_time = all_of(.x[1]),
stacked_time2 = all_of(.x[2]),
stacked_event =all_of(.x[3])) %>%
mutate(stacked_survtype=.y)
} else {
stop("Length 2 or 3 only")
}
}) %>%
list_rbind()
}
set.seed(42)
df_surv = survival::lung %>%
as_tibble() %>%
mutate(
time_os = time,
event_os = status==2,
time_pfs = time / (1 + runif(dplyr::n())),
event_pfs = ifelse(runif(dplyr::n())>0.3, event_os, 1),
time_efs = time_pfs / (1 + runif(dplyr::n())),
event_efs = ifelse(runif(dplyr::n())>0.3, event_pfs, 1),
)
#Right censoring
surv_list = list(
"Overall survival"=c("time_os", "event_os"),
"Progression-free survival"=c("time_pfs", "event_pfs"),
"Event-free survival"=c("time_efs", "event_efs")
)
stack_surv(df_surv, surv_list) %>%
survfit2(formula=Surv(stacked_time, stacked_event) ~ stacked_survtype,
data = .) %>%
ggsurvfit() +
add_confidence_interval() +
add_risktable() +
scale_ggsurvfit() #Interval censoring (dummy)
surv_list2 = list(
"Overall survival"=c("time_os", "time_pfs", "event_os"),
"Progression-free survival"=c("time_os", "time_pfs", "event_pfs")
)
stack_surv(df_surv, surv_list2) %>%
survfit2(formula=Surv(stacked_time, stacked_event) ~ stacked_survtype,
data = .) %>%
ggsurvfit() +
add_confidence_interval() +
add_risktable() +
scale_ggsurvfit() Created on 2024-05-18 with reprex v2.1.0 |
Is your feature request related to a problem? Please describe.
When I'm only describing the survival of a population (i.e. with no grouping variable), I would like to be able to show both OS and PFS on the same graph.
Describe the solution you'd like
The solution is described in kassambara/survminer#195.
Describe alternatives you've considered
Alternative solutions would be (1) to use
survminer
, but the project is unfortunately not maintained anymore and I like the interface ofggsurvfit
better, or (2) to plot both graphs separately.Additional context
![image](https://private-user-images.githubusercontent.com/15105152/331600906-a66faea9-87f2-4190-b10c-f54af3d6159a.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzkyOTc1MTgsIm5iZiI6MTczOTI5NzIxOCwicGF0aCI6Ii8xNTEwNTE1Mi8zMzE2MDA5MDYtYTY2ZmFlYTktODdmMi00MTkwLWIxMGMtZjU0YWYzZDYxNTlhLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjExVDE4MDY1OFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTkxNjczMzVlOTY5YTcyZjViZDBmNTU0YzU5NzA2ODVlOTAwYjRmOWMyYjRlNjk2M2Q3MDIyYmE1YzUzNmMxNjkmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.4tirzpOti0LwOmF8XgiPKUjPaDtnlXZAd2Dvm8qjlcQ)
Here is a screenshot of the above-mentioned issue:
The text was updated successfully, but these errors were encountered: