The escalation package by Kristian Brock. Documentation is hosted at https://brockk.github.io/escalation/

Introduction

To provide dose selection decisions, the escalation package daisy-chains together objects that support a common interface, each deriving from type selector. This vignette demonstrates the entire interface supported by selector objects. For the purpose of illustratration, we use a BOIN selector but the same functions will work on every type of dose selector in escalation.

library(escalation)
#> Loading required package: magrittr
model <- get_boin(num_doses = 5, target = 0.3)
fit <- model %>% fit('1NN 2NN 3NT 2NT')

Supported Interface

Target toxicity rate:

tox_target(fit)
#> [1] 0.3

The number of patients treated:

num_patients(fit)
#> [1] 8

Cohort IDs for the treated patients:

cohort(fit)
#> [1] 1 1 2 2 3 3 4 4

The code infers from the spaces in the outcome string that a dose-decision was made after the second, fourth , and sixth patients.

Integers representing the dose-levels given:

doses_given(fit)
#> [1] 1 1 2 2 3 3 2 2

Bits representing whether toxicity event was observed:

tox(fit)
#> [1] 0 0 0 0 0 1 0 1

The total number of toxicities seen at all doses combined:

num_tox(fit)
#> [1] 2

A data-frame containing the above information:

model_frame(fit)
#> # A tibble: 8 x 4
#>   patient cohort  dose   tox
#>     <int>  <int> <int> <int>
#> 1       1      1     1     0
#> 2       2      1     1     0
#> 3       3      2     2     0
#> 4       4      2     2     0
#> 5       5      3     3     0
#> 6       6      3     3     1
#> 7       7      4     2     0
#> 8       8      4     2     1

The number of doses under investigation:

num_doses(fit)
#> [1] 5

The indices of the dose-levels under investigation:

dose_indices(fit)
#> [1] 1 2 3 4 5

The dose-level recommended for the next patient:

recommended_dose(fit)
#> [1] 2

After seeing some toxicity at doses 2 and 3, the design sensibly sticks at dose 2 for the time being.

A logical value for whether accrual should continue:

continue(fit)
#> [1] TRUE

We infer from this that no stopping condition has yet been triggered.

The number of patients treated at each dose:

n_at_dose(fit)
#> [1] 2 4 2 0 0

The number of patients treated at the recommended dose:

n_at_recommended_dose(fit)
#> [1] 4

The proportion of patients treated at each dose:

prob_administer(fit)
#>    1    2    3    4    5 
#> 0.25 0.50 0.25 0.00 0.00

The total number of toxicities seen at each dose:

tox_at_dose(fit)
#> [1] 0 1 1 0 0

The empirical toxicity rate, i.e. the number of toxicities divided by the number of patients:

empiric_tox_rate(fit)
#> [1] 0.00 0.25 0.50  NaN  NaN

The model-derived expected toxicity rate at each dose:

mean_prob_tox(fit)
#> [1] 0.02 0.26 0.50   NA   NA

The BOIN design makes no estimate for doses it has not yet administered.

The model-derived median toxicity rate at each dose:

median_prob_tox(fit)
#>    1    2    3    4    5 
#> 0.01 0.21 0.50   NA   NA

BOIN does not actually calculate posterior median estimates. Sometimes it will be necessary to return missing values if functionality is not supported by a model. Median estimates could be added to the BOIN class in due course.

The model-derived quantile of the toxicity rate at each dose:

prob_tox_quantile(fit, 0.9)
#>    1    2    3    4    5 
#> 0.05 0.54 0.89   NA   NA

BOIN does not calculate this either. It could also be added.

The posterior probability that the toxicity rate exceeds some threshold value, here 50%:

prob_tox_exceeds(fit, 0.5)
#> [1] 0.009391185 0.129051871 0.500000000          NA          NA

Once again, no estimate is made for non-administered doses. We see that the model estimates a trivial chance that the toxicity rate at the lowest dose exceeds 50%.

Learn if this model supports sampling from the posterior:

supports_sampling(fit)
#> [1] FALSE

The BOIN model does not support sampling. If it did, we could run prob_tox_samples(fit).

We can also call some standard generic functions:

print(fit)
#> Patient-level data:
#> # A tibble: 8 x 4
#>   Patient Cohort  Dose   Tox
#>     <int>  <int> <int> <int>
#> 1       1      1     1     0
#> 2       2      1     1     0
#> 3       3      2     2     0
#> 4       4      2     2     0
#> 5       5      3     3     0
#> 6       6      3     3     1
#> 7       7      4     2     0
#> 8       8      4     2     1
#> 
#> Dose-level data:
#> # A tibble: 6 x 8
#>   dose    tox     n empiric_tox_rate mean_prob_tox median_prob_tox admissible
#>   <ord> <dbl> <dbl>            <dbl>         <dbl>           <dbl> <lgl>     
#> 1 NoDo…     0     0             0             0               0    TRUE      
#> 2 1         0     2             0             0.02            0.01 TRUE      
#> 3 2         1     4             0.25          0.26            0.21 TRUE      
#> 4 3         1     2             0.5           0.5             0.5  TRUE      
#> 5 4         0     0           NaN            NA              NA    TRUE      
#> 6 5         0     0           NaN            NA              NA    TRUE      
#> # … with 1 more variable: recommended <lgl>
#> 
#> The model targets a toxicity level of 0.3.
#> The model advocates continuing at dose 2.
summary(fit)
#> # A tibble: 6 x 8
#>   dose    tox     n empiric_tox_rate mean_prob_tox median_prob_tox admissible
#>   <ord> <dbl> <dbl>            <dbl>         <dbl>           <dbl> <lgl>     
#> 1 NoDo…     0     0             0             0               0    TRUE      
#> 2 1         0     2             0             0.02            0.01 TRUE      
#> 3 2         1     4             0.25          0.26            0.21 TRUE      
#> 4 3         1     2             0.5           0.5             0.5  TRUE      
#> 5 4         0     0           NaN            NA              NA    TRUE      
#> 6 5         0     0           NaN            NA              NA    TRUE      
#> # … with 1 more variable: recommended <lgl>

and cast it to a tidyverse tibble:

library(tibble)

as_tibble(fit)
#> # A tibble: 6 x 8
#>   dose    tox     n empiric_tox_rate mean_prob_tox median_prob_tox admissible
#>   <ord> <dbl> <dbl>            <dbl>         <dbl>           <dbl> <lgl>     
#> 1 NoDo…     0     0             0             0               0    TRUE      
#> 2 1         0     2             0             0.02            0.01 TRUE      
#> 3 2         1     4             0.25          0.26            0.21 TRUE      
#> 4 3         1     2             0.5           0.5             0.5  TRUE      
#> 5 4         0     0           NaN            NA              NA    TRUE      
#> 6 5         0     0           NaN            NA              NA    TRUE      
#> # … with 1 more variable: recommended <lgl>