From 12728a45dfdf625c267ad3fda33dde2c15c02658 Mon Sep 17 00:00:00 2001 From: Daniel Sabanes Bove Date: Mon, 25 May 2026 18:12:04 +0800 Subject: [PATCH 01/11] start design doc for non-normal outcomes --- misc/.gitignore | 2 + misc/design_other_outcomes.qmd | 95 ++++++++++++++++++++++++++++++++++ misc/references.bib | 23 ++++++++ 3 files changed, 120 insertions(+) create mode 100644 misc/.gitignore create mode 100644 misc/design_other_outcomes.qmd create mode 100644 misc/references.bib diff --git a/misc/.gitignore b/misc/.gitignore new file mode 100644 index 00000000..5f105288 --- /dev/null +++ b/misc/.gitignore @@ -0,0 +1,2 @@ +*_files/ +*.html diff --git a/misc/design_other_outcomes.qmd b/misc/design_other_outcomes.qmd new file mode 100644 index 00000000..2d824e35 --- /dev/null +++ b/misc/design_other_outcomes.qmd @@ -0,0 +1,95 @@ +--- +bibliography: references.bib +--- + +# Design doc for extending to other outcomes (count, survival, binary) + +Currently, `rbmi` only supports continuous endpoints. However, also for other commonly used endpoints, in particular count, survival and binary endpoints, multiple imputation is often needed. Both the name of the `rbmi` package, as well as the structure of the workflow, would also fit these other endpoint methods for (reference based) multiple imputation. + +## Methodology overview + +Here is a first high level overview of important references for the non-continuous endpoints: + +- Count: + - @keene2014 is the basic proposal for Bayesian multiple imputation for negative binomial count data, covering two time periods: before and after discontinuing the trial and treatment at the same time. + - @roger2019 extends this to more than two time periods, in particular a third time period where patients are still continuing the trial, but have stopped treatment already. So this is the more general setting. +- Survival: + - TODO +- Binary: + - TODO + +### Outcome structure + +For the current longitudinal continuous outcome, the structure is that of multiple visits (i.e. preplanned time-points) with a continuous outcome at each visit. This is the same for binary outcomes (e.g. response, relapse, etc.), which are often also measured at the same time-points as the continuous outcomes. +Missing data occurs because of intercurrent events or missed visits, and the missingness is defined for each visit. + +For count outcomes, the structure is different: In the best case where a patient starts treatment and continues it until the end of the trial, we have a single count at the end of the trial. If we have treatment discontinuation and trial drop-out, we can have a maximum of three time periods: (1) before discontinuing the trial and treatment, (2) after discontinuing the treatment but still in the trial, and (3) after discontinuing the trial and treatment. +After discontinuing the trial, we cannot observe the outcome any longer, and therefore we have missing data for the count outcome in period (3). + +For survival outcomes, the structure is similar as for count outcomes: Ideally we have a single survival time at the end of the trial (either the patient had an event before, or the patient is censored at the end of the trial). If we have treatment discontinuation and trial drop-out, we can again have a maximum of three time periods as for count outcomes. At the time of trial discontinuation the patient becomes immediately censored. + +### Available imputation methods + +For count outcomes, we focus on Bayesian multiple imputation for negative multinomial count data. + +TODO survival and binary outcomes. + +In the Bayesian multiple imputation methods, we can always use the `rbmi` workflow steps: + +- Draw: Fit the initial imputation model via MCMC and draw parameters from the posterior distribution. +- Impute: Use the drawn parameters and the assumed model to impute the missing data for each parameter draw. +- Analyse: Analyse each of the imputed datasets with a (fast) analysis model, and save relevant estimators. +- Pool: Pool the estimators across the imputed datasets to get a single point estimate and confidence interval. + +For `rbmi` this means that the other imputation methods, such as conditional mean imputation, are (for now) not relevant and therefore not supported. + +## User interface generalization + +### Data + +- For count and survival outcomes, the same `expand_locf()` function can be used: Instead of the visit variable, we use a "period" or "phase" variable, which indicates whether the patient is in period (1), (2) or (3) as described above. +- For count outcomes, we have then in addition a "count" variable, capturing counts for each of the three periods, as well as a "duration" variable capturing the duration of each period (e.g. in years). +- For survival outcomes, we also need in addition two variables: + - The "event" variable, which is a binary variable indicating whether the patient had an event in the time period or continued without an event (i.e. censored if next time period is not observable) + - The "time" variable, which captures either the time to event in the period where there was an event, or the duration of the period if there was no event (i.e. censored). + +### Draws + +The `draws()` function needs to take the following inputs: + +- `outcome`: The outcome type, which defaults to "continuous" (current implementation), but can now also be "count", "survival" or "binary". +- `data`: The whole data as described above +- `data_ice`: The data with intercurrent events (ICE) time points (that lead to discontinuation of follow up) and imputation strategies, which include: + - Missing At Random: "MAR" + - Jump to Reference: "JR" + - Copy Reference: "CR" + - Copy Increments from Reference: "CIR" + - Last Mean Carried Forward: "LMCF" +- `data_treatment_ice`: Only needed for count and survival outcomes, the data with treatment discontinuation time points and corresponding off-treatment imputation strategies. + - TODO: We might need to be able to specify different strategies here +- `vars`: In addition to the existing variables, where we use `outcome` to capture counts and binary outcomes, we also need `event` and `time` for survival outcomes, and `duration` for count outcomes. +- `method`: For now we will only support `method_bayes()`, but could later support additional methods via corresponding `method_*()` constructors. + +### Impute + +The `impute()` function takes the `draws` object and the reference group mapping, and internally produces the imputed data sets. +For this to work correctly with different outcome types, the `draws` object needs to have a second (or a more specific) class indicating the outcome type, e.g. `draws_continuous`, `draws_count`, `draws_survival` and `draws_binary`. The `impute()` function can then dispatch on this second class to use the correct imputation method for the different outcome types. + +Similarly, the result of the `impute()` call needs to have a second class indicating the outcome type, e.g. `imputation_continuous`, `imputation_count`, `imputation_survival` and `imputation_binary`. This allows the `analyse()` function to dispatch on the correct analysis method for the different outcome types. + +### Analyse + +In the last step of the workflow, the user chosen analysis model is applied to each of the imputed datasets, and the relevant estimators are saved for pooling. Because we can dispatch on the outcome type, we might have slightly different arguments supported here. +For example, we will need to check whether a delta adjustment makes sense for the non-normal outcomes. + +In addition, `rbmi` can provide the standard analysis functions for the different outcome types. For example, for count outcomes we can provide a `neg_bin_regression` function, for survival outcomes a `cox_regression()` function, and for binary outcomes a `logistic_regression()` function. + +### Pool + +Here we just want to use Rubin's rules to pool the Bayesian multiple imputation results across the imputed datasets. + +We might want to add an argument `df` or so to define the calculation of the degrees of freedom, because SAS uses a different method and we might want to be able to reproduce that with `rbmi` if needed. + +## Internal structure adaptation + +## References diff --git a/misc/references.bib b/misc/references.bib new file mode 100644 index 00000000..a4e7f81a --- /dev/null +++ b/misc/references.bib @@ -0,0 +1,23 @@ +@article{roger2019, +author = {Roger, James H. and Bratton, Daniel J. and Mayer, Bhabita and Abellan, Juan J. and Keene, Oliver N.}, +title = {Treatment policy estimands for recurrent event data using data collected after cessation of randomised treatment}, +journal = {Pharmaceutical Statistics}, +volume = {18}, +number = {1}, +pages = {85-95}, +keywords = {recurrent event, estimand, treatment policy, imputation, missing data}, +doi = {10.1002/pst.1910}, +year = {2019} +} + +@article{keene2014, +author = {Keene, Oliver N. and Roger, James H. and Hartley, Benjamin F. and Kenward, Michael G.}, +title = {Missing data sensitivity analysis for recurrent event data using controlled imputation}, +journal = {Pharmaceutical Statistics}, +volume = {13}, +number = {4}, +pages = {258-264}, +keywords = {missing, sensitivity, recurrent event, exacerbation, multiple imputation, MNAR}, +doi = {10.1002/pst.1624}, +year = {2014} +} From 6c18f435b81307776dc44e59dcfabba6f3309f2b Mon Sep 17 00:00:00 2001 From: Daniel Sabanes Bove Date: Mon, 25 May 2026 21:19:46 +0800 Subject: [PATCH 02/11] add internal adaptation considerations --- misc/design_other_outcomes.qmd | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/misc/design_other_outcomes.qmd b/misc/design_other_outcomes.qmd index 2d824e35..35c920b4 100644 --- a/misc/design_other_outcomes.qmd +++ b/misc/design_other_outcomes.qmd @@ -92,4 +92,38 @@ We might want to add an argument `df` or so to define the calculation of the deg ## Internal structure adaptation +### Draws + +The `draws()` function needs to be adapted as described above for the user interface. Internally, this means both the generic function as well as the `draws.bayes()` method need to be changed, while the other methods can almost stay as is (they should just assert that the outcome type is "continuous"). + +Internally, `draws.bayes()` can then dispatch on the outcome type for the correct code path, keeping the current behavior as is for the "continuous" outcome type. In particular, the `fit_mcmc()` function need to also dispatch on the different outcome types, to fit the correct imputation model and draw parameters from the posterior distribution: Instead of calling `fit_mmrm()` for the continuous outcome type, we can call `fit_neg_multinom()` for the count outcome type e.g. However, many of the logistics around the MCMC fitting and parameter drawing can be kept the same across the different outcome types, so we can reuse a lot of code here. + +The new fitting functions would use new Stan code from `inst/stan/` for the different outcome types, which would be added to the package. + +Also the post-processing is slightly different depending on outcome. Finally, the `as_draws()` constructor now also attaches the additional class for the outcome type, as described above. + +### Impute + +For the `impute()` function, we primarily need to change the `impute.random()` method, which needs to dispatch on the outcome type for the correct code path. This means changing `impute_internal()` and the workhorse `impute_data_individual()`, which currently calls `impute_outcome()` which in turn generates multivariate normal samples. In contrast, for the count outcome type e.g., we would need to generate negative binomial samples at the end. + +For both the `draws()` and `impute()` steps, we will need to make sure we use the two data sets for intercurrent events and treatment discontinuation correctly for count and survival outcomes. + +### Analyse + +Looking at the `analyse()` function's stack [here](https://github.com/openpharma/rbmi/blob/main/R/analyse.R) it seems that most of the code won't need to be adapted a lot. The dispatching on outcome type will matter for small things like the initial input validation only. The most important additions will be the outcome type specific analysis functions, supplementing the existing [ANCOVA](https://github.com/openpharma/rbmi/blob/main/R/ancova.R) function. + +### Pool + +There is not much to change here. +As mentioned above we might want to have a `df` argument to be able to optionally choose the simpler degrees of freedom calculation, along these lines (compare [here](https://documentation.sas.com/doc/en/statug/latest/statug_mianalyze_details08.htm)): + +```{r} +#| eval: false +df_sas <- (M - 1) * (1 + within_var / ((1 + 1/M) * between_var))^2 +df_sas +t_crit_sas <- qt(1 - alpha/2, df_sas) +ci_lower_sas <- coef_hat - t_crit_sas * coef_se +ci_upper_sas <- coef_hat + t_crit_sas * coef_se +``` + ## References From f39ba357b318551c097ae0cb9129f3d74866b2c6 Mon Sep 17 00:00:00 2001 From: Daniel Sabanes Bove Date: Thu, 4 Jun 2026 14:35:29 +0800 Subject: [PATCH 03/11] add survival references --- misc/design_other_outcomes.qmd | 57 ++++++++++++++++++++++++++++------ misc/references.bib | 50 +++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 9 deletions(-) diff --git a/misc/design_other_outcomes.qmd b/misc/design_other_outcomes.qmd index 35c920b4..a28c1097 100644 --- a/misc/design_other_outcomes.qmd +++ b/misc/design_other_outcomes.qmd @@ -10,13 +10,50 @@ Currently, `rbmi` only supports continuous endpoints. However, also for other co Here is a first high level overview of important references for the non-continuous endpoints: -- Count: - - @keene2014 is the basic proposal for Bayesian multiple imputation for negative binomial count data, covering two time periods: before and after discontinuing the trial and treatment at the same time. - - @roger2019 extends this to more than two time periods, in particular a third time period where patients are still continuing the trial, but have stopped treatment already. So this is the more general setting. -- Survival: - - TODO -- Binary: - - TODO +### Count outcomes + +- @keene2014 is the basic proposal for Bayesian multiple imputation for negative binomial count data, covering two time periods: before and after discontinuing the trial and treatment at the same time. +- @roger2019 extends this to more than two time periods, in particular a third time period where patients are still continuing the trial, but have stopped treatment already. So this is the more general setting. + +### Survival outcomes + +- @lu2015 compare delta-adjustment and reference-based multiple imputation methods: + - The delta-adjustment method assumes a multiplicative increase of the hazard for patients who discontinue the treatment early in the experimental arm, but the same hazard as continuing control patients for control patients who discontinue. + - The reference-based method assumes that the hazard after discontinuation is in between control and experimental patients (factor $1 - \phi$ is multiplied with $\beta$ to obtain new log hazard ratio). It basically corresponds to "copy reference" approach in longitudinal data, not clear how "jump to reference" would work in survival. + - The draw model fit uses `SAS PHREG` with the `bayes` statement. An option is to use piecewise constant hazards. Therefore they use either interpolated Breslow estimate or piecewise exponential model to get the baseline hazard. + - For the imputation, they propose both a Bayesian as well as a frequentist MLE approach, and then just draw from the conditional distribution given the censoring time. Interestingly they still censor the observations at the next planned visit. + - In the analysis step they just use stanard Cox proportional hazards models, and then combine them with Rubin's rules. +- @atkinson2019 propose reference based multiple imputation: + - They argue that Rubin's rules lead to "information-anchored" inference, which gives a "level playing field" and should be ok to use + - For the draw model they propose a simple Weibull proportional hazards model, fit with maximum likelihood and then draw from the asymptotic normal distribution of the parameters + - For the imputation they distinguish the different assumptions: + - censored at random (CAR): just use the conditional distribution of the survival time given the covariates and censoring time as well as the parameters drawn from the draw step + - jump to reference (J2R): the hazard changes after the censoring time immediately to that of the control group. The authors mention that this corresponds to "copy reference" (CR) from longitudinal modeling but I don't really see that ... + - copy increment from reference (CIR): the the hazard ratio is taken from the censoring time and then multiplied with reference hazard to obtain the hazard after the censoring time. So this is additive on the log hazard scale. + - delta method: the hazard after the censoring time is multiplied with a factor $\delta$, given by the user. + - The analysis model is again the same Weibull PH model as for the draw step, but now fit to the imputed data sets, and then combined with Rubin's rules. +- @hartley2022 extend the idea from the neg bin/count imputation using on/off treatment periods from @roger2019 to survival outcomes: + - Note that they describe this as different from reference based multiple imputation + - Similar as for counts, also here allow different off treatment imputation models: + - either all have the same hazard after discontinuing treatment + - or the step change is the same for all + - or the arms have individual off treatment hazards (this will need the most observed off treatment data to be able to fit the model) + - Proposed steps are: + - They bootstrap observed data using cluster sampling + - For each bootstrapped data set they fit an Andersen-Gill model (which is the same here as a Cox PH model, right?), including the same covariates as for the analysis model + - Then they impute any missing times to event in the original dataset using the estimates from each bootstrapped data set + - Note that this is not exactly the same as in the continuous rbmi approach described [here](https://openpharma.github.io/rbmi/latest-tag/articles/stat_specs.html#bootstrapped-mi) + - Then they fit the analysis model (Cox model) to each imputed data set and pool using Rubin’s rules + - They highlight that it is problematic to use the Cox model when we have piece wise hazard functions - we no longer have the PH assumption fulfilled! + - As an alternative, they propose the restricted mean survival time (RMST), estimated here as an integral of the Kaplan-Meier curve + - SAS code available at [github.com/GSK-Biostatistics/mi_off_trt](https://github.com/GSK-Biostatistics/mi_off_trt) +- @garcia2024 propose an analytical solution for delta adjustment and reference-based imputation with time-to-event endpoints + - It has a nice table with a literature overview (but misses the @hartley2022 paper in there) + - I did not go into detail here because it is not in scope (no MI) + +### Binary + +TODO ### Outcome structure @@ -32,7 +69,7 @@ For survival outcomes, the structure is similar as for count outcomes: Ideally w For count outcomes, we focus on Bayesian multiple imputation for negative multinomial count data. -TODO survival and binary outcomes. +We see above that also bootstrap-based multiple imputation has been proposed for survival outcomes and could therefore be supported in `rbmi`. We will need to look at the details and see how it best fits in the framework. In the Bayesian multiple imputation methods, we can always use the `rbmi` workflow steps: @@ -41,7 +78,9 @@ In the Bayesian multiple imputation methods, we can always use the `rbmi` workfl - Analyse: Analyse each of the imputed datasets with a (fast) analysis model, and save relevant estimators. - Pool: Pool the estimators across the imputed datasets to get a single point estimate and confidence interval. -For `rbmi` this means that the other imputation methods, such as conditional mean imputation, are (for now) not relevant and therefore not supported. +It seems that the other imputation methods, such as conditional mean imputation, are (for now) not relevant and therefore not supported. + +TODO: integrate binary ## User interface generalization diff --git a/misc/references.bib b/misc/references.bib index a4e7f81a..858fd082 100644 --- a/misc/references.bib +++ b/misc/references.bib @@ -21,3 +21,53 @@ @article{keene2014 doi = {10.1002/pst.1624}, year = {2014} } + +@article{lu2015, +author = {Kaifeng Lu and Dayong Li and Gary G. Koch}, +title = {Comparison Between Two Controlled Multiple Imputation Methods for Sensitivity Analyses of Time-to-Event Data With Possibly Informative Censoring}, +journal = {Statistics in Biopharmaceutical Research}, +volume = {7}, +number = {3}, +pages = {199--213}, +year = {2015}, +publisher = {Taylor \& Francis}, +doi = {10.1080/19466315.2015.1053572} +} + +@article{atkinson2019, +author = {Atkinson, Andrew and Kenward, Michael G. and Clayton, Tim and Carpenter, James R.}, +title = {Reference-based sensitivity analysis for time-to-event data}, +journal = {Pharmaceutical Statistics}, +volume = {18}, +number = {6}, +pages = {645-658}, +keywords = {missing data, MNAR, multiple imputation, sensitivity analysis, time to event}, +doi = {10.1002/pst.1954}, +year = {2019} +} + +@article{hartley2022, +author = {Hartley, Benjamin and Drury, Thomas and Lettis, Sally and Mayer, Bhabita and Keene, Oliver N. and Abellan, Juan J.}, +title = {Estimation of a treatment policy estimand for time to event data using data collected post discontinuation of randomised treatment}, +journal = {Pharmaceutical Statistics}, +volume = {21}, +number = {3}, +pages = {612-624}, +keywords = {estimands, missing data, multiple imputation, time to event, treatment policy}, +doi = {10.1002/pst.2189}, +year = {2022} +} + +@article{garcia2024, +author = {García-Hernandez, Alberto and Pérez, Teresa and del Carmen Pardo, María and Rizopoulos, Dimitris}, +title = {An illness-death multistate model to implement delta adjustment and reference-based imputation with time-to-event endpoints}, +journal = {Pharmaceutical Statistics}, +volume = {23}, +number = {2}, +pages = {219-241}, +doi = {10.1002/pst.2348}, +year = {2024} +} + + + From e9a3588904a97a9eb418e3c2bb5f5a789d401fd0 Mon Sep 17 00:00:00 2001 From: Daniel Sabanes Bove Date: Thu, 4 Jun 2026 14:40:59 +0800 Subject: [PATCH 04/11] update ignores --- misc/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/misc/.gitignore b/misc/.gitignore index 5f105288..08b81c6b 100644 --- a/misc/.gitignore +++ b/misc/.gitignore @@ -1,2 +1,4 @@ *_files/ *.html +.quarto/ +*.pdf From a3d36d445dcf30291b8a820c377af528af15c43e Mon Sep 17 00:00:00 2001 From: Daniel Sabanes Bove Date: Wed, 17 Jun 2026 16:35:34 +0800 Subject: [PATCH 05/11] include comments from discussion --- misc/design_other_outcomes.qmd | 42 ++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/misc/design_other_outcomes.qmd b/misc/design_other_outcomes.qmd index a28c1097..ddc9800e 100644 --- a/misc/design_other_outcomes.qmd +++ b/misc/design_other_outcomes.qmd @@ -15,6 +15,8 @@ Here is a first high level overview of important references for the non-continuo - @keene2014 is the basic proposal for Bayesian multiple imputation for negative binomial count data, covering two time periods: before and after discontinuing the trial and treatment at the same time. - @roger2019 extends this to more than two time periods, in particular a third time period where patients are still continuing the trial, but have stopped treatment already. So this is the more general setting. +Time to recurrent events can also be analyzed with Andersen-Gill models, but we will not pursue this further here. + ### Survival outcomes - @lu2015 compare delta-adjustment and reference-based multiple imputation methods: @@ -51,13 +53,21 @@ Here is a first high level overview of important references for the non-continuo - It has a nice table with a literature overview (but misses the @hartley2022 paper in there) - I did not go into detail here because it is not in scope (no MI) +For our purposes, for survival outcomes we are going to: + +- Focus on Bayesian multiple imputation. Bootstrap could be added later if needed (it considers a different variance estimand) and is not a priority. +- Focus are reference based imputation methods (especially "jump to reference" and "copy increments from reference"), but off-treatment imputation methods can also be beneficial to have. As mentioned below in @outcome-structure, the data structure for survival outcomes is similar to that for count outcomes also in this regard. +- The delta method is needed as part of a tipping point analysis. There is also a Novartis R package for this particular approach, which could be used for comparison of results. +- Different baseline hazard models need to be supported, in particular exponential, Weibull and piecewise constant (exponential) hazards. + + ### Binary TODO -### Outcome structure +### Outcome structure {#outcome-structure} -For the current longitudinal continuous outcome, the structure is that of multiple visits (i.e. preplanned time-points) with a continuous outcome at each visit. This is the same for binary outcomes (e.g. response, relapse, etc.), which are often also measured at the same time-points as the continuous outcomes. +For the current longitudinal continuous outcome, the structure is that of multiple visits (i.e. preplanned time-points) with a continuous outcome at each visit. This is the same for binary outcomes (e.g. response, relapse, etc.), which are often also measured at the same time-points as the continuous outcomes. Off-treatment modelling for continuous and binary outcomes can be done in a simple way by including an indicator variable for being on/off treatment in the imputation model. Missing data occurs because of intercurrent events or missed visits, and the missingness is defined for each visit. For count outcomes, the structure is different: In the best case where a patient starts treatment and continues it until the end of the trial, we have a single count at the end of the trial. If we have treatment discontinuation and trial drop-out, we can have a maximum of three time periods: (1) before discontinuing the trial and treatment, (2) after discontinuing the treatment but still in the trial, and (3) after discontinuing the trial and treatment. @@ -67,11 +77,8 @@ For survival outcomes, the structure is similar as for count outcomes: Ideally w ### Available imputation methods -For count outcomes, we focus on Bayesian multiple imputation for negative multinomial count data. - -We see above that also bootstrap-based multiple imputation has been proposed for survival outcomes and could therefore be supported in `rbmi`. We will need to look at the details and see how it best fits in the framework. - -In the Bayesian multiple imputation methods, we can always use the `rbmi` workflow steps: +For all new outcomes, we initally focus on Bayesian multiple imputation methods. +We can then always use the `rbmi` workflow steps as follows: - Draw: Fit the initial imputation model via MCMC and draw parameters from the posterior distribution. - Impute: Use the drawn parameters and the assumed model to impute the missing data for each parameter draw. @@ -106,8 +113,10 @@ The `draws()` function needs to take the following inputs: - Last Mean Carried Forward: "LMCF" - `data_treatment_ice`: Only needed for count and survival outcomes, the data with treatment discontinuation time points and corresponding off-treatment imputation strategies. - TODO: We might need to be able to specify different strategies here + - TODO: Make sure that we don't have duplicate information with `data_ice` - `vars`: In addition to the existing variables, where we use `outcome` to capture counts and binary outcomes, we also need `event` and `time` for survival outcomes, and `duration` for count outcomes. - `method`: For now we will only support `method_bayes()`, but could later support additional methods via corresponding `method_*()` constructors. + - Here we need to be able to specify the survival model when used together with survival outcomes (in the similar way as now we specify the covariance model for continuous outcomes). ### Impute @@ -119,15 +128,22 @@ Similarly, the result of the `impute()` call needs to have a second class indica ### Analyse In the last step of the workflow, the user chosen analysis model is applied to each of the imputed datasets, and the relevant estimators are saved for pooling. Because we can dispatch on the outcome type, we might have slightly different arguments supported here. -For example, we will need to check whether a delta adjustment makes sense for the non-normal outcomes. -In addition, `rbmi` can provide the standard analysis functions for the different outcome types. For example, for count outcomes we can provide a `neg_bin_regression` function, for survival outcomes a `cox_regression()` function, and for binary outcomes a `logistic_regression()` function. +In addition, `rbmi` can provide the standard analysis functions for the different outcome types. For example: + +- For count outcomes we can provide a `neg_bin_regression` function, +- for survival outcomes a `cox_regression()` function, +- and for binary outcomes a `logistic_regression()` function. + +Also optional marginalized treatment effect estimators and differences can be valuable (e.g. via an `rmst()` function for restricted mean survival time analysis). We can utilize the [`RobinCar2`](https://openpharma.github.io/RobinCar2/latest-tag/) for this instead of implementing it from scratch. ### Pool Here we just want to use Rubin's rules to pool the Bayesian multiple imputation results across the imputed datasets. -We might want to add an argument `df` or so to define the calculation of the degrees of freedom, because SAS uses a different method and we might want to be able to reproduce that with `rbmi` if needed. +We initially considered to add an argument `df` or so to define the calculation of the degrees of freedom, because SAS uses a different method and we might want to be able to reproduce that with `rbmi` if needed. However we discussed and since we anyway only pool asymptotically normally distributed test statistics, we can just set the degrees of freedom to infinity and use thereby the normal distribution for the confidence interval calculation. + +Note that this also requires care about the scale at which the pooling is performed: e.g. for survival outcomes we can use the log hazard ratio scale for pooling, which is asymptotically normal, but not the hazard ratio scale itself. Similarly for count outcomes we can use the log rate ratio scale, and for binary outcomes the log odds ratio scale. ## Internal structure adaptation @@ -145,7 +161,7 @@ Also the post-processing is slightly different depending on outcome. Finally, th For the `impute()` function, we primarily need to change the `impute.random()` method, which needs to dispatch on the outcome type for the correct code path. This means changing `impute_internal()` and the workhorse `impute_data_individual()`, which currently calls `impute_outcome()` which in turn generates multivariate normal samples. In contrast, for the count outcome type e.g., we would need to generate negative binomial samples at the end. -For both the `draws()` and `impute()` steps, we will need to make sure we use the two data sets for intercurrent events and treatment discontinuation correctly for count and survival outcomes. +For both the `draws()` and `impute()` steps, we will need to make sure we use the two data sets for intercurrent events and treatment discontinuation correctly for count and survival outcomes. It might also involve having a time-varying covariate to account for the on/off treatment status in the imputation model. ### Analyse @@ -154,7 +170,7 @@ Looking at the `analyse()` function's stack [here](https://github.com/openpharma ### Pool There is not much to change here. -As mentioned above we might want to have a `df` argument to be able to optionally choose the simpler degrees of freedom calculation, along these lines (compare [here](https://documentation.sas.com/doc/en/statug/latest/statug_mianalyze_details08.htm)): +As mentioned above we initially considered to have a `df` argument to be able to optionally choose the simpler degrees of freedom calculation, along these lines (compare [here](https://documentation.sas.com/doc/en/statug/latest/statug_mianalyze_details08.htm)): ```{r} #| eval: false @@ -165,4 +181,6 @@ ci_lower_sas <- coef_hat - t_crit_sas * coef_se ci_upper_sas <- coef_hat + t_crit_sas * coef_se ``` +However, now we decided to just use `qnorm()` instead. + ## References From 6f28e7d1c26129b722ade5544e0d32dd4f231bd9 Mon Sep 17 00:00:00 2001 From: Daniel Sabanes Bove Date: Wed, 17 Jun 2026 16:41:45 +0800 Subject: [PATCH 06/11] wording --- misc/design_other_outcomes.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/design_other_outcomes.qmd b/misc/design_other_outcomes.qmd index ddc9800e..d593ad80 100644 --- a/misc/design_other_outcomes.qmd +++ b/misc/design_other_outcomes.qmd @@ -181,6 +181,6 @@ ci_lower_sas <- coef_hat - t_crit_sas * coef_se ci_upper_sas <- coef_hat + t_crit_sas * coef_se ``` -However, now we decided to just use `qnorm()` instead. +However, as mentioned above, we decided to just use `qnorm()` instead for simplicity. ## References From 7183b10d6aff4f5b084652a9e373210e72a392e1 Mon Sep 17 00:00:00 2001 From: Daniel Sabanes Bove Date: Thu, 18 Jun 2026 17:16:28 +0800 Subject: [PATCH 07/11] add binary outcome part --- misc/design_other_outcomes.qmd | 25 +++++++++++++++++++++---- misc/references.bib | 19 +++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/misc/design_other_outcomes.qmd b/misc/design_other_outcomes.qmd index d593ad80..ddd22d15 100644 --- a/misc/design_other_outcomes.qmd +++ b/misc/design_other_outcomes.qmd @@ -63,7 +63,24 @@ For our purposes, for survival outcomes we are going to: ### Binary -TODO +- @cro2025 describe two algorithms for reference-based multiple imputation for binary outcomes: + - The first uses joint modeling with the multivariate normal distribution and an adaptive rounding algorithm. This is basically using the continuous outcomes approach and then just "rounds back" post-ICE sampled outcome values to 0 and 1 by looking at the samples distribution and assuming a normal shape of it. + - The second uses joint modeling too, but with a latent multivariate normal model, that corresponds to a multivariate probit model for the binary outcomes. The computation is a bit more involved, the authors mention specialized MCMC samplers which are e.g. implemented in the [`jomo`](https://cran.r-project.org/web/packages/jomo/index.html) R package. Fortunately multivariate probit models can also be fitted with Stan, see [here](https://mc-stan.org/docs/stan-users-guide/regression.html#multivariate-probit-regression) for details. This could be a better starting point for inclusion in the `rbmi` package. + - The paper makes the assumption that all post-ICE binary outcomes are missing. + - They use a logistic regression model at a certain time point/visit as the analysis model, and then combine the results with Rubin's rules. +- @rehal2026 treat the more general case where a part of the patients is still observed after treatment discontinuation (similar as in the negative binomial and survival papers). + - A good point they make is that if the underlying outcome is truly continuous then this should be used for imputation instead - however this may be difficult if that outcome is complex! (think about response in oncology studies, where e.g. the RECIST definition is quite complex although it mainly looks at a continuous outcome, the sum of longest diameters of the target lesions) + - They use sequential, iterative imputation at each timepoint, separately within each treatment arm - i.e. at each sequence k step it can use both observed and previously imputed data from time points before k (by treating them as covariates) + - They propose different conditional regression models: + - CICS (common intercepts common slopes) + - POOLED OICS (On/Off Intercepts common slopes) - just have an intercept change based on treatment status + - OICS - same but with treatment arm specific parameter estimates (intercepts delta_zj) + - OITS - same but with additional time since discontinuation as covariate same as OICS but with additional pattern indicators (ordinal covariate) + - FULL - as reference also fitted full model on all observed data + - OICS seems most promising based on simulation study results - distinction needs to be made between the pre-and post-IE data and this should be reflected appropriately in MI models to impute the missing data + - They propose to use a pragmatic step-down process when the rate of intercurrent events and missing data are is not clear before the study, i.e. start with the most complex imputation model and only if that fails use the next less complex one etc. + - They mention perfect prediction / linear separation issue with logistic regression - I wonder if it would be relatively easy to mitigate this with regularization / prior on the regression coefficients. + ### Outcome structure {#outcome-structure} @@ -77,17 +94,17 @@ For survival outcomes, the structure is similar as for count outcomes: Ideally w ### Available imputation methods -For all new outcomes, we initally focus on Bayesian multiple imputation methods. +For all new outcomes, we initially focus on Bayesian multiple imputation methods. We can then always use the `rbmi` workflow steps as follows: -- Draw: Fit the initial imputation model via MCMC and draw parameters from the posterior distribution. +- Draw: Fit the initial imputation model via MCMC and draw parameters from the posterior distribution. - Impute: Use the drawn parameters and the assumed model to impute the missing data for each parameter draw. - Analyse: Analyse each of the imputed datasets with a (fast) analysis model, and save relevant estimators. - Pool: Pool the estimators across the imputed datasets to get a single point estimate and confidence interval. It seems that the other imputation methods, such as conditional mean imputation, are (for now) not relevant and therefore not supported. -TODO: integrate binary +Note that the above 4-step workflow assumes a joint model across all timepoints, which is first fitted to the data in the Draw step and then used to impute all missing data in the Impute step. Thus the sequential imputation approach as described in @rehal2026 for binary outcomes is not well in scope. ## User interface generalization diff --git a/misc/references.bib b/misc/references.bib index 858fd082..f64f5f2f 100644 --- a/misc/references.bib +++ b/misc/references.bib @@ -69,5 +69,24 @@ @article{garcia2024 year = {2024} } +@article{cro2025, +author = {Cro, Suzie and Quartagno, Matteo and White, Ian R. and Carpenter, James R.}, +title = {Reference-Based Multiple Imputation for Longitudinal Binary Data}, +journal = {Statistics in Medicine}, +volume = {44}, +number = {3-4}, +doi = {10.1002/sim.10301}, +year = {2025} +} + +@article{rehal2026, +author = {Rehal, Sunita and Best, Nicky and Watts, Sarah and Drury, Thomas}, +title = {Using Off-Treatment Sequential Multiple Imputation for Binary Outcomes to Address Intercurrent Events Handled by a Treatment Policy Strategy}, +journal = {Pharmaceutical Statistics}, +volume = {25}, +number = {2}, +doi = {10.1002/pst.70070}, +year = {2026} +} From c6dccb25b93520e3e1b87cd1c0aecd8b1cf58316 Mon Sep 17 00:00:00 2001 From: Daniel Sabanes Bove Date: Thu, 18 Jun 2026 17:22:29 +0800 Subject: [PATCH 08/11] fix cross references --- misc/design_other_outcomes.qmd | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/misc/design_other_outcomes.qmd b/misc/design_other_outcomes.qmd index ddd22d15..e22159b0 100644 --- a/misc/design_other_outcomes.qmd +++ b/misc/design_other_outcomes.qmd @@ -1,5 +1,6 @@ --- bibliography: references.bib +number-sections: true --- # Design doc for extending to other outcomes (count, survival, binary) @@ -56,7 +57,7 @@ Time to recurrent events can also be analyzed with Andersen-Gill models, but we For our purposes, for survival outcomes we are going to: - Focus on Bayesian multiple imputation. Bootstrap could be added later if needed (it considers a different variance estimand) and is not a priority. -- Focus are reference based imputation methods (especially "jump to reference" and "copy increments from reference"), but off-treatment imputation methods can also be beneficial to have. As mentioned below in @outcome-structure, the data structure for survival outcomes is similar to that for count outcomes also in this regard. +- Focus are reference based imputation methods (especially "jump to reference" and "copy increments from reference"), but off-treatment imputation methods can also be beneficial to have. As mentioned below in @sec-outcome-structure, the data structure for survival outcomes is similar to that for count outcomes also in this regard. - The delta method is needed as part of a tipping point analysis. There is also a Novartis R package for this particular approach, which could be used for comparison of results. - Different baseline hazard models need to be supported, in particular exponential, Weibull and piecewise constant (exponential) hazards. @@ -82,7 +83,7 @@ For our purposes, for survival outcomes we are going to: - They mention perfect prediction / linear separation issue with logistic regression - I wonder if it would be relatively easy to mitigate this with regularization / prior on the regression coefficients. -### Outcome structure {#outcome-structure} +### Outcome structure {#sec-outcome-structure} For the current longitudinal continuous outcome, the structure is that of multiple visits (i.e. preplanned time-points) with a continuous outcome at each visit. This is the same for binary outcomes (e.g. response, relapse, etc.), which are often also measured at the same time-points as the continuous outcomes. Off-treatment modelling for continuous and binary outcomes can be done in a simple way by including an indicator variable for being on/off treatment in the imputation model. Missing data occurs because of intercurrent events or missed visits, and the missingness is defined for each visit. From 6a11c952c5c1b829d58d66866dfe1bb1ebaea465 Mon Sep 17 00:00:00 2001 From: Daniel Sabanes Bove Date: Sun, 28 Jun 2026 16:09:21 +0800 Subject: [PATCH 09/11] revise data spec --- .gitignore | 2 + misc/design_other_outcomes.qmd | 111 +++++++++++++++++++++++++++++---- 2 files changed, 100 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 0f48158a..e760ac54 100644 --- a/.gitignore +++ b/.gitignore @@ -62,3 +62,5 @@ docs local/ *.rds + +cspell.json diff --git a/misc/design_other_outcomes.qmd b/misc/design_other_outcomes.qmd index e22159b0..1fe6ba96 100644 --- a/misc/design_other_outcomes.qmd +++ b/misc/design_other_outcomes.qmd @@ -85,10 +85,10 @@ For our purposes, for survival outcomes we are going to: ### Outcome structure {#sec-outcome-structure} -For the current longitudinal continuous outcome, the structure is that of multiple visits (i.e. preplanned time-points) with a continuous outcome at each visit. This is the same for binary outcomes (e.g. response, relapse, etc.), which are often also measured at the same time-points as the continuous outcomes. Off-treatment modelling for continuous and binary outcomes can be done in a simple way by including an indicator variable for being on/off treatment in the imputation model. +For the current longitudinal continuous outcome, the structure is that of multiple visits (i.e. preplanned time-points) with a continuous outcome at each visit. This is the same for binary outcomes (e.g. response, relapse, etc.), which are often also measured at the same time-points as the continuous outcomes. Off-treatment modelling for continuous and binary outcomes can be done in a simple way by including an indicator variable for being on/off treatment in the imputation model (see @rehal2026 examples mentioned above). Missing data occurs because of intercurrent events or missed visits, and the missingness is defined for each visit. -For count outcomes, the structure is different: In the best case where a patient starts treatment and continues it until the end of the trial, we have a single count at the end of the trial. If we have treatment discontinuation and trial drop-out, we can have a maximum of three time periods: (1) before discontinuing the trial and treatment, (2) after discontinuing the treatment but still in the trial, and (3) after discontinuing the trial and treatment. +For count outcomes, the structure is different: In the best case where a patient starts treatment and continues it until the end of the trial, we have a single count at the end of the trial. If we have treatment discontinuation and trial drop-out, we can have a maximum of three time periods: (1) before discontinuing the trial and treatment, (2) after discontinuing the treatment but still continuing in the trial, and (3) after discontinuing both the trial and the treatment. After discontinuing the trial, we cannot observe the outcome any longer, and therefore we have missing data for the count outcome in period (3). For survival outcomes, the structure is similar as for count outcomes: Ideally we have a single survival time at the end of the trial (either the patient had an event before, or the patient is censored at the end of the trial). If we have treatment discontinuation and trial drop-out, we can again have a maximum of three time periods as for count outcomes. At the time of trial discontinuation the patient becomes immediately censored. @@ -98,8 +98,8 @@ For survival outcomes, the structure is similar as for count outcomes: Ideally w For all new outcomes, we initially focus on Bayesian multiple imputation methods. We can then always use the `rbmi` workflow steps as follows: -- Draw: Fit the initial imputation model via MCMC and draw parameters from the posterior distribution. -- Impute: Use the drawn parameters and the assumed model to impute the missing data for each parameter draw. +- Draw: Fit the initial imputation model via MCMC and draw parameter samples from the (approximate) posterior distribution. +- Impute: Use the parameter samples and the assumed model to impute the missing data for each parameter draw. - Analyse: Analyse each of the imputed datasets with a (fast) analysis model, and save relevant estimators. - Pool: Pool the estimators across the imputed datasets to get a single point estimate and confidence interval. @@ -112,10 +112,96 @@ Note that the above 4-step workflow assumes a joint model across all timepoints, ### Data - For count and survival outcomes, the same `expand_locf()` function can be used: Instead of the visit variable, we use a "period" or "phase" variable, which indicates whether the patient is in period (1), (2) or (3) as described above. -- For count outcomes, we have then in addition a "count" variable, capturing counts for each of the three periods, as well as a "duration" variable capturing the duration of each period (e.g. in years). -- For survival outcomes, we also need in addition two variables: - - The "event" variable, which is a binary variable indicating whether the patient had an event in the time period or continued without an event (i.e. censored if next time period is not observable) - - The "time" variable, which captures either the time to event in the period where there was an event, or the duration of the period if there was no event (i.e. censored). +- For count outcomes, we capture the counts in the "outcome" variable, capturing counts for each of the three periods, as well as a "duration" variable capturing the duration of each period (e.g. in years). +- For survival outcomes, we use the same columns as for counts, but now the "outcome" variable becomes a binary variable indicating whether the patient had an event at the end of the time period or continued without an event (i.e. censored if next time period is not observable). + +Let's create some examples to make this easier to describe. + +#### Continuous example + +```{r} +library(rbmi) +library(dplyr) + +dat <- antidepressant_data + +dat_continuous <- expand_locf( + dat, + PATIENT = levels(dat$PATIENT), # expand by PATIENT and VISIT + VISIT = levels(dat$VISIT), + vars = c("BASVAL", "THERAPY"), # fill with LOCF BASVAL and THERAPY + group = c("PATIENT"), + order = c("PATIENT", "VISIT") +) +``` + +So the continuous data looks like this: + +```{r} +head(dat_continuous) +``` + +For each patient, and for each visit, we repeat any baseline covariates (here e.g. `BASVAL` and `THERAPY`) and capture time-varying outcome (here `CHANGE`) and covariates (e.g. `HAMATOTL`). + +#### Binary example + +The binary data looks basically the same, but the outcome variable is now binary (e.g. `RESPONSE`): + +```{r} +dat_binary <- dat_continuous |> + mutate(RESPONSE = ifelse(CHANGE >= 0, 1, 0)) |> + select(PATIENT, VISIT, RESPONSE, BASVAL, THERAPY, HAMATOTL) + +head(dat_binary) +``` + +#### Count example + +The count data just three "period" rows for each patient, with the count outcome (here `COUNT`)and the duration of each period: + +```{r} +dat_count <- data.frame( + PATIENT = c(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4), + PERIOD = c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3), + COUNT = c(5, NA, NA, 2, 2, NA, 4, 1, NA, 3, NA, NA), + DURATION = c(1.1, 0, 0, 0.25, 0.8, 0, 0.3, 0.3, 0.4, 0.5, 0, 0.5), + THERAPY = c("A", "A", "A", "B", "B", "B", "C", "C", "C", "D", "D", "D"), + BASVAL = c(10, 10, 10, 20, 20, 20, 15, 15, 15, 25, 25, 25) +) +dat_count +``` + +We see the different patterns here: + +- Patient 1: Never stopped treatment, completed the trial after 1.1 years. +- Patient 2: Stopped treatment after 0.25 years, but continued the trial for another 0.8 years. +- Patient 3: Stopped treatment after 0.3 years, and stopped the trial after another 0.3 years. If we assume that the total planned trial duration was 1 year, then we have 0.4 years of period 3 (i.e. no treatment and no follow up) that is not observable and therefore missing. +- Patient 4: Stopped treatment and dropped out of the trial after 0.5 years, so we have 0.5 years of period 3 that is not observable and therefore missing. + +We implicitly assume here that there are no time-varying covariates, because then we would have even more periods per patient. + +#### Survival example + +We use the same columns as for count outcomes for survival outcomes, but now the outcome variable is binary (1 = event, 0 = censored): + +```{r} +dat_survival <- data.frame( + PATIENT = c(1, 1, 1, 2, 2, 2, 3, 3, 3), + PERIOD = c(1, 2, 3, 1, 2, 3, 1, 2, 3), + EVENT = c(0, NA, NA, 0, 1, NA, 0, 0, 1), + DURATION = c(1.1, 0, 0, 0.25, 0.8, 0, 0.3, 0.3, 0.7), + THERAPY = c("A", "A", "A", "B", "B", "B", "C", "C", "C"), + BASVAL = c(10, 10, 10, 20, 20, 20, 15, 15, 15) +) +``` + +We see the different patterns here: + +- Patient 1: Never stopped treatment, completed the trial after 1.1 years without an event (censored). +- Patient 2: Stopped treatment after 0.25 years, had an event after another 0.8 years (i.e. at 1.05 years). +- Patient 3: Stopped treatment after 0.3 years, and stopped the trial after another 0.3 years (i.e. at 0.6 years). After another 0.7 years (i.e. at 1.3 years) the patient had an event. + +So it basically works similarly as for count outcomes, but the outcome variable (here `EVENT`) is binary and informs what happened at the end of each period (patient with or without event). Summing up the duration variable (here `DURATION`) gives the total follow up time for each patient, and the last period is either censored or has an event. ### Draws @@ -129,10 +215,9 @@ The `draws()` function needs to take the following inputs: - Copy Reference: "CR" - Copy Increments from Reference: "CIR" - Last Mean Carried Forward: "LMCF" -- `data_treatment_ice`: Only needed for count and survival outcomes, the data with treatment discontinuation time points and corresponding off-treatment imputation strategies. - - TODO: We might need to be able to specify different strategies here - - TODO: Make sure that we don't have duplicate information with `data_ice` -- `vars`: In addition to the existing variables, where we use `outcome` to capture counts and binary outcomes, we also need `event` and `time` for survival outcomes, and `duration` for count outcomes. +- `data_treatment_ice`: Only needed for count and survival outcomes, can be used to specify off-treatment imputation strategies. + - TODO: What are the different strategies here? +- `vars`: In addition to the existing variables, where we use `outcome` to capture counts, binary outcomes and event indicators, we need `duration` for count and survival outcomes, which captures the duration of each period (which is captured in a `period` variable). - `method`: For now we will only support `method_bayes()`, but could later support additional methods via corresponding `method_*()` constructors. - Here we need to be able to specify the survival model when used together with survival outcomes (in the similar way as now we specify the covariance model for continuous outcomes). @@ -169,7 +254,7 @@ Note that this also requires care about the scale at which the pooling is perfor The `draws()` function needs to be adapted as described above for the user interface. Internally, this means both the generic function as well as the `draws.bayes()` method need to be changed, while the other methods can almost stay as is (they should just assert that the outcome type is "continuous"). -Internally, `draws.bayes()` can then dispatch on the outcome type for the correct code path, keeping the current behavior as is for the "continuous" outcome type. In particular, the `fit_mcmc()` function need to also dispatch on the different outcome types, to fit the correct imputation model and draw parameters from the posterior distribution: Instead of calling `fit_mmrm()` for the continuous outcome type, we can call `fit_neg_multinom()` for the count outcome type e.g. However, many of the logistics around the MCMC fitting and parameter drawing can be kept the same across the different outcome types, so we can reuse a lot of code here. +Internally, `draws.bayes()` can then dispatch on the outcome type for the correct code path, keeping the current behaviour as is for the "continuous" outcome type. In particular, the `fit_mcmc()` function need to also dispatch on the different outcome types, to fit the correct imputation model and draw parameters from the posterior distribution: Instead of calling `fit_mmrm()` for the continuous outcome type, we can call `fit_neg_multinom()` for the count outcome type e.g. However, many of the logistics around the MCMC fitting and parameter drawing can be kept the same across the different outcome types, so we can reuse a lot of code here. The new fitting functions would use new Stan code from `inst/stan/` for the different outcome types, which would be added to the package. From dedd044f5a5c14001a6d3de0e8ab549cf187fc26 Mon Sep 17 00:00:00 2001 From: Daniel Sabanes Bove Date: Sun, 28 Jun 2026 16:15:03 +0800 Subject: [PATCH 10/11] polish --- misc/design_other_outcomes.qmd | 1 + 1 file changed, 1 insertion(+) diff --git a/misc/design_other_outcomes.qmd b/misc/design_other_outcomes.qmd index 1fe6ba96..4a825e72 100644 --- a/misc/design_other_outcomes.qmd +++ b/misc/design_other_outcomes.qmd @@ -120,6 +120,7 @@ Let's create some examples to make this easier to describe. #### Continuous example ```{r} +#| message: false library(rbmi) library(dplyr) From e4c9057b5c5d5f741688e751327c43b3d5caee8f Mon Sep 17 00:00:00 2001 From: Daniel Sabanes Bove Date: Sun, 28 Jun 2026 16:16:30 +0800 Subject: [PATCH 11/11] wording --- misc/design_other_outcomes.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/design_other_outcomes.qmd b/misc/design_other_outcomes.qmd index 4a825e72..124a85c1 100644 --- a/misc/design_other_outcomes.qmd +++ b/misc/design_other_outcomes.qmd @@ -112,7 +112,7 @@ Note that the above 4-step workflow assumes a joint model across all timepoints, ### Data - For count and survival outcomes, the same `expand_locf()` function can be used: Instead of the visit variable, we use a "period" or "phase" variable, which indicates whether the patient is in period (1), (2) or (3) as described above. -- For count outcomes, we capture the counts in the "outcome" variable, capturing counts for each of the three periods, as well as a "duration" variable capturing the duration of each period (e.g. in years). +- For count outcomes, we capture the counts for each of the three periods in the "outcome" variable, and use an additional "duration" variable containing the duration of each period (e.g. in years). - For survival outcomes, we use the same columns as for counts, but now the "outcome" variable becomes a binary variable indicating whether the patient had an event at the end of the time period or continued without an event (i.e. censored if next time period is not observable). Let's create some examples to make this easier to describe.