# Using escalation

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
    #> Warning: package 'magrittr' was built under R version 4.0.5

    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 × 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 × 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 × 8
    #>   dose     tox     n empiric_tox_rate mean_prob_tox median_pro…¹ admis…² recom…³
    #>   <ord>  <dbl> <dbl>            <dbl>         <dbl>        <dbl> <lgl>   <lgl>
    #> 1 NoDose     0     0             0             0            0    TRUE    FALSE
    #> 2 1          0     2             0             0.02         0.01 TRUE    FALSE
    #> 3 2          1     4             0.25          0.26         0.21 TRUE    TRUE
    #> 4 3          1     2             0.5           0.5          0.5  TRUE    FALSE
    #> 5 4          0     0           NaN            NA           NA    TRUE    FALSE
    #> 6 5          0     0           NaN            NA           NA    TRUE    FALSE
    #> # … with abbreviated variable names ¹​median_prob_tox, ²​admissible, ³​recommended
    #>
    #> The model targets a toxicity level of 0.3.
    #> The model advocates continuing at dose 2.

    summary(fit)
    #> # A tibble: 6 × 8
    #>   dose     tox     n empiric_tox_rate mean_prob_tox median_pro…¹ admis…² recom…³
    #>   <ord>  <dbl> <dbl>            <dbl>         <dbl>        <dbl> <lgl>   <lgl>
    #> 1 NoDose     0     0             0             0            0    TRUE    FALSE
    #> 2 1          0     2             0             0.02         0.01 TRUE    FALSE
    #> 3 2          1     4             0.25          0.26         0.21 TRUE    TRUE
    #> 4 3          1     2             0.5           0.5          0.5  TRUE    FALSE
    #> 5 4          0     0           NaN            NA           NA    TRUE    FALSE
    #> 6 5          0     0           NaN            NA           NA    TRUE    FALSE
    #> # … with abbreviated variable names ¹​median_prob_tox, ²​admissible, ³​recommended

and cast it to a tidyverse `tibble`:

    library(tibble)

    as_tibble(fit)
    #> # A tibble: 6 × 8
    #>   dose     tox     n empiric_tox_rate mean_prob_tox median_pro…¹ admis…² recom…³
    #>   <ord>  <dbl> <dbl>            <dbl>         <dbl>        <dbl> <lgl>   <lgl>
    #> 1 NoDose     0     0             0             0            0    TRUE    FALSE
    #> 2 1          0     2             0             0.02         0.01 TRUE    FALSE
    #> 3 2          1     4             0.25          0.26         0.21 TRUE    TRUE
    #> 4 3          1     2             0.5           0.5          0.5  TRUE    FALSE
    #> 5 4          0     0           NaN            NA           NA    TRUE    FALSE
    #> 6 5          0     0           NaN            NA           NA    TRUE    FALSE
    #> # … with abbreviated variable names ¹​median_prob_tox, ²​admissible, ³​recommended