Calculate dose-transition pathways for an EffTox study.
The function efftox_dtps_to_dataframe
performs a similar
function, but is much less-flexible.
efftox_dtps( cohort_sizes, previous_outcomes = "", next_dose = NULL, user_dose_func = NULL, verbose = FALSE, i_am_patient = FALSE, ... )
cohort_sizes | vector of future cohort sizes, i.e. positive integers.
E.g. To calculate paths for the the next cohort of two followed by another
cohort of three, use |
---|---|
previous_outcomes | Outcomes observed hitherto in the syntax required
by |
next_dose | the dose-level to be given to the immediately next cohort. |
user_dose_func | optional delegate for deciding dose. A function that
takes a |
verbose | logical, TRUE to get progress messages. |
i_am_patient | logical, TRUE to show your tolerance for waiting for over 100 models to fit. Set to FALSE by default. |
... | extra params passed to |
dose pathways in a data.frame
.
Yap C, Billingham LJ, Cheung YK, Craddock C, O’Quigley J. Dose transition pathways: The missing link between complex dose-finding designs and simple decision-making. Clinical Cancer Research. 2017;23(24):7440-7447. doi:10.1158/1078-0432.CCR-17-0582
Brock K, Billingham L, Copland M, Siddique S, Sirovica M, Yap C. Implementing the EffTox dose-finding design in the Matchpoint trial. BMC Medical Research Methodology. 2017;17(1):112. doi:10.1186/s12874-017-0381-x
if (FALSE) { # Calculate paths for the first cohort of 3 in Thall et al 2014 example paths1 <- efftox_dtps(cohort_sizes = c(3), next_dose = 1, real_doses = c(1.0, 2.0, 4.0, 6.6, 10.0), efficacy_hurdle = 0.5, toxicity_hurdle = 0.3, p_e = 0.1, p_t = 0.1, eff0 = 0.5, tox1 = 0.65, eff_star = 0.7, tox_star = 0.25, alpha_mean = -7.9593, alpha_sd = 3.5487, beta_mean = 1.5482, beta_sd = 3.5018, gamma_mean = 0.7367, gamma_sd = 2.5423, zeta_mean = 3.4181, zeta_sd = 2.4406, eta_mean = 0, eta_sd = 0.2, psi_mean = 0, psi_sd = 1, seed = 123) # Calculate paths for the next two cohorts of 2, in an in-progress trial # Warning: this create 100 paths. It will run for a minute or two. paths2 <- efftox_dtps(cohort_sizes = c(2, 2), previous_outcomes = '1NN 2EE', next_dose = 1, real_doses = c(1.0, 2.0, 4.0, 6.6, 10.0), efficacy_hurdle = 0.5, toxicity_hurdle = 0.3, p_e = 0.1, p_t = 0.1, eff0 = 0.5, tox1 = 0.65, eff_star = 0.7, tox_star = 0.25, alpha_mean = -7.9593, alpha_sd = 3.5487, beta_mean = 1.5482, beta_sd = 3.5018, gamma_mean = 0.7367, gamma_sd = 2.5423, zeta_mean = 3.4181, zeta_sd = 2.4406, eta_mean = 0, eta_sd = 0.2, psi_mean = 0, psi_sd = 1, seed = 123, i_am_patient = TRUE) # Paths can be converted to a tibble library(tibble) library(dplyr) df <- as_tibble(paths2) df %>% print(n = 200) # And shaped in a wide format spread_paths(df %>% select(-fit, -parent_fit, -dose_index)) %>% print(n = 100) # Incredibly, there are 100 ways these two cohorts of two can end up. # An example with a custom dose selection function. # Define a function to select the maximal utility dose, no matter what. # Note: this diverges from the original authors' intentions; we provide this # for illustration only! max_utility_dose <- function(efftox_fit) { return(which.max(efftox_fit$utility)) } # Fit the paths, providing the user_dose_func parameter # Warning: this create 100 paths. It will run for a minute or two. paths3 <- efftox_dtps(cohort_sizes = c(2, 2), previous_outcomes = '1NN 2EE', next_dose = 1, real_doses = c(1.0, 2.0, 4.0, 6.6, 10.0), efficacy_hurdle = 0.5, toxicity_hurdle = 0.3, p_e = 0.1, p_t = 0.1, eff0 = 0.5, tox1 = 0.65, eff_star = 0.7, tox_star = 0.25, alpha_mean = -7.9593, alpha_sd = 3.5487, beta_mean = 1.5482, beta_sd = 3.5018, gamma_mean = 0.7367, gamma_sd = 2.5423, zeta_mean = 3.4181, zeta_sd = 2.4406, eta_mean = 0, eta_sd = 0.2, psi_mean = 0, psi_sd = 1, user_dose_func = max_utility_dose, seed = 123, i_am_patient = TRUE) # We can see where the dose-selections differ at the second future cohort # by joining these paths to those calculated in the previous example: left_join( as_tibble(paths2)%>% select(.node, .parent, .depth, outcomes, model_dose = next_dose), as_tibble(paths3) %>% select(.node, user_dose = next_dose), by = '.node' ) %>% spread_paths() %>% filter(model_dose2 != user_dose2) # They differ in many places. The user defined functions sometimes selects # higher doses; sometimes lower. }