Swimmer plot#99
Conversation
DanChaltiel
left a comment
There was a problem hiding this comment.
That is amazing work Livia!
Here are a few comments to improve the existing code.
| adm <- recist %>% | ||
| left_join(enrolres %>% select(subjid, date_inclusion), by = "subjid") %>% | ||
| # filter(!is.na(rcresp), rcresp != "Progressive disease") %>% | ||
| filter(!is.na(rcresp)) %>% |
There was a problem hiding this comment.
Pourquoi filtrer les réponses NA ? On peut avoir une administration quand même non ?
There was a problem hiding this comment.
parce que apres pour simuler le reste des datset ca va etre difficil. Le dataset creer c est juste un example. Le statistician est censse en premier lieux preparer son final dataset avant de faire la swimmer plot.
| # filter(!is.na(rcresp), rcresp != "Progressive disease") %>% | ||
| filter(!is.na(rcresp)) %>% | ||
| arrange(subjid, rcdt) %>% # ensure ordered by patient and RECIST | ||
| group_by(subjid) %>% |
There was a problem hiding this comment.
tu peux utiliser l'argument .by dans mutate(), au lieu d'utiliser group_by() puis ungroup()
| ADMDT = if_else( | ||
| row_number() == 1, | ||
| pmin(date_inclusion + days(sample(5:15, 1)), rcdt), # 5–15 days after inclusion but before first RECIST | ||
| rcdt - days(sample(21:30, 1)) # subsequent admissions: 21–30 days before each RECIST |
There was a problem hiding this comment.
Pas mal !
Mais je me demande si ça ne fait pas des trucs bizarres parfois.
Je l'aurais fait en 2 étapes : d'abord ADMDT0 qui vaudra pmin(date_inclusion + days(sample(5:15, 1)), rcdt), puis ADMDT qui vaudra ADMDT0 + days(sample(21:30, 1)).
De cette manière, les administrations sont un peu plus découplées des RECIST, c'est plus proche de la réalité non ?
There was a problem hiding this comment.
chatgpt a un peu changer. Regarde
| # group_by(subjid) %>% | ||
| # mutate( | ||
| # # Assign ADMYN: 99% Yes, 1% No | ||
| # ADMYN = sample(c("Yes", "No"), n(), replace = TRUE, prob = c(0.99, 0.01)), |
There was a problem hiding this comment.
Ouais, j'aime bien l'idée de ADMYN mais c'est overkill pour le moment.
There was a problem hiding this comment.
oui j ai essaye et ca me donne quelque problem donc apres avoir perdu pas mal de temps decu j ai laisser tombe
| eot <- eot %>% | ||
| mutate( | ||
| # usually after last treatment date but before death | ||
| EOTLADDT = case_when( |
There was a problem hiding this comment.
Si tu pouvais ajouter des labels à tes tables simulées, ça facilitera beaucoup la lecture :
%>% apply_labels(EOTLADDT="Last treatment date")
Malheureusement, les labels de TrialMaster ne sont pas tous standardisés donc ce n'est pas toujours lisible
|
|
||
| set.seed(2025) | ||
|
|
||
| fu <- eot %>% |
There was a problem hiding this comment.
Je ne suis pas sûr de ce que tu as essayé de faire ici mais ça ne fait sans doute pas ce que tu voulais.
sample(1) vaut toujours 1 donc il n'a pas d'effet, mais sample(1:10) ferait planter la fonction.
Ensuite, plutôt que de mettre à NA selon une probabilité pour filtrer les NA, tu peux utiliser la fonction slice_sample() qui fait pareil en plus court :-)
En l'état tu pourrais remplacer par :
eot %>%
rowwise() %>%
mutate(
n_fu = sample(1), # number of follow-ups per subject
FUDT = sort(EOTLADDT + days(sample(4:180, n_fu, replace = FALSE)))
) %>%
ungroup() %>%
slice_sample(prop=0.3)There was a problem hiding this comment.
est ce que ce code :
mutate(
FUDT = if_else(
runif(n()) < 0.7, # 80% probability
as.Date(NA), # set to missing
FUDT # keep original
)
) %>%
fait la meme chose que slice_sample(prop=0.3)? du coup je change aussi pour le dataset eot?
| arrange(as.numeric(subjid), rcdt) %>% | ||
| mutate(ADMDT_first = first(ADMDT), .by = subjid) %>% | ||
| mutate(ADMDT_last = last(ADMDT), .by = subjid) %>% |
There was a problem hiding this comment.
C'est un peu dangereux de prendre first/last, il vaut mieux utiliser min/max
adm %>%
mutate(
ADMDT_first = min(ADMDT),
ADMDT_last = max(ADMDT),
group="Treatment Administration",
.by = subjid
)Mais dans la plupart des cas ça fera exactement la même chose.
D'ailleurs, tu ne sélectionnes pas ADMDT_last ?
There was a problem hiding this comment.
okay, j ai chnage. et oui je crois pas que j utilise ADMDT_last , mais je crois que je l"utilise pour simuler les dataset.
| mutate(visit=ifelse(group=="Treatment Administration",1, NA)) %>% | ||
| mutate(visit=ifelse(group=="Recist" & rcresp=="Complete response" ,2, visit))%>% | ||
| mutate(visit=ifelse(group=="Recist" & rcresp=="Partial response" ,2, visit))%>% | ||
| mutate(visit=ifelse(group=="Recist" & rcresp=="Stable disease" ,3, visit))%>% | ||
| mutate(visit=ifelse(group=="Recist" & rcresp=="Progressive disease" ,4, visit))%>% | ||
| mutate(visit=ifelse(group=="Recist" & rcresp=="Not Evaluable" ,5, visit))%>% | ||
| mutate(visit=ifelse(group=="End of treatment" ,6, visit)) %>% | ||
| mutate(visit=ifelse(group=="Death" ,7, visit)) %>% | ||
| mutate(visit=ifelse(group=="Alive at last follow up2" ,8, visit)) %>% | ||
| mutate(visit=ifelse(group=="Alive at last follow up" ,9, visit)) %>% | ||
| mutate(visit=ifelse(group=="Treatment period",10,visit )) %>% |
There was a problem hiding this comment.
ChatGPT: "stp, transforme ce code en un seul case_when"
There was a problem hiding this comment.
c vrai , parfois j'oublie ma grande amie...
|
|
||
| # Conversion de la variable visite en facteur | ||
|
|
||
| suivi$visit2 <- factor(suivi$visit, c(1:10), |
|
|
||
|
|
||
| # Final plot -------------------------------------------------------------- | ||
| # Problems in the simulated datas I think that makes the graph a bit weird. |
There was a problem hiding this comment.
For each problem that you can identify, you can write a little defensive program:
if(the_thing_is_weird){
cli_abort("You did something weird")
}There was a problem hiding this comment.
en fait j en ai plus besoin la mais effectivement je fais beaucoup de checks. Mais j ai du mal a utiliser ca.
grstat/R/ae_table_grade.R
Line 189 in 8c69458
grstat/R/waterfall_plot.R
Line 57 in 8c69458
Tu pars du principe que tes données d'input ont une certaine structure (e.g.
data1a une colonnecol1qui est de type numérique), il faut faire des checks pour que les utilisateurs aient un message d'erreur clair.suivi_fu$first_fudevrait toujours être 0 ?