suppressPackageStartupMessages({
library(crmPack)
library(knitr)
library(kableExtra)
library(tidyr)
library(magrittr)
library(dplyr)
})The latest release of crmPack introduces
broom-like tidy methods for all crmPack
classes. These methods convert the underlying S4 classes to (lists of)
tibbles. This should facilitate reporting of all aspects of
CRM trials as well as making it easier to integrate crmPack
with other packages such as ggplot2.
The following is the general approach we take to tidying
crmPack classes:
tibbles or a list of tibbles.list, these rules are applied
to each element of the list in turn.tibble. This will ease downstream operations such as
row_binding.tibbles. The
list may be nested to multiple levels. (See, for example,
LogisticLogNormal.)tibble correspond to the
slot names of the parent object.
vector or list, the column name will be
singular. See, for example, CohortSizeParts below.tibble is returned.tibble, whose name is the name of
the attribute and whose value is the value of the attribute for every
row of the tibble. Vector attributes can be added, by default, as a
nested tibble. The nested tibble is 1 row x n column, with column names
defined by the name of the attribute and values given by the value of
the corresponding attribute.tbl_<className> is prepended to the class of the
(list of) tidy tibble(s).intervals slot in various
CohortSize and Increments classes, then the
naming convention described above is not followed. Instead, columns
named min and max define the extent of the
range.CohortSizeConst is a trivial example and illustrates the
default approach for all classes.
IncrementsRelative illustrate how ranges are
handled.
IncrementsRelative(
intervals = c(0, 20),
increments = c(1, 0.33)
) %>%
tidy()
#> # A tibble: 2 × 3
#> min max increment
#> <dbl> <dbl> <dbl>
#> 1 0 20 1
#> 2 20 Inf 0.33CohortSizeMax contains a slot whose value is a list.
cs_max <- maxSize(
CohortSizeConst(3),
CohortSizeDLT(intervals = 0:1, cohort_size = c(1, 3))
)
cs_max %>% tidy()
#> [[1]]
#> # A tibble: 1 × 1
#> size
#> <int>
#> 1 3
#>
#> [[2]]
#> # A tibble: 2 × 3
#> min max cohort_size
#> <dbl> <dbl> <int>
#> 1 0 1 1
#> 2 1 Inf 3
#>
#> attr(,"class")
#> [1] "tbl_CohortSizeMax" "tbl_CohortSizeMax" "list"The Samples class likely to the most useful when making
presentations not yet supported by crmPack directly.
options <- McmcOptions(
burnin = 100,
step = 1,
samples = 2000
)
emptydata <- Data(doseGrid = c(1, 3, 5, 10, 15, 20, 25, 40, 50, 80, 100))
model <- LogisticLogNormal(
mean = c(-0.85, 1),
cov =
matrix(c(1, -0.5, -0.5, 1),
nrow = 2
),
ref_dose = 56
)
samples <- mcmc(emptydata, model, options)
tidySamples <- samples %>% tidy()
tidySamples %>% head()
#> $data
#> # A tibble: 2,000 × 10
#> Iteration Chain alpha0 alpha1 nChains nParameters nIterations nBurnin nThin
#> <int> <int> <dbl> <dbl> <int> <int> <int> <int> <int>
#> 1 1 1 -1.56 3.06 1 1 2100 100 1
#> 2 2 1 -0.873 8.39 1 1 2100 100 1
#> 3 3 1 -1.44 17.2 1 1 2100 100 1
#> 4 4 1 1.59 1.49 1 1 2100 100 1
#> 5 5 1 -0.908 2.72 1 1 2100 100 1
#> 6 6 1 -0.403 0.883 1 1 2100 100 1
#> 7 7 1 -1.46 2.08 1 1 2100 100 1
#> 8 8 1 0.156 0.438 1 1 2100 100 1
#> 9 9 1 0.736 0.824 1 1 2100 100 1
#> 10 10 1 -1.98 3.57 1 1 2100 100 1
#> # ℹ 1,990 more rows
#> # ℹ 1 more variable: parallel <lgl>
#>
#> $options
#> # A tibble: 1 × 5
#> iterations burnin step rng_kind rng_seed
#> <int> <int> <int> <chr> <int>
#> 1 2100 100 1 <NA> NAcrmPack dataTidy crmPack data can be easily reported using
knitr or similar packages in the obvious way.
The cohort size for this trial is determined by the dose to be used in the current cohort according to the rules described in the table below:
CohortSizeRange(
intervals = c(0, 50, 300),
cohort_size = c(1, 3, 5)
) %>%
tidy() %>%
kable(
col.names = c("Min", "Max", "Cohort size"),
caption = "Rules for selecting the cohort size"
) %>%
add_header_above(c("Dose" = 2, " " = 1))| Min | Max | Cohort size |
|---|---|---|
| 0 | 50 | 1 |
| 50 | 300 | 3 |
| 300 | Inf | 5 |
Or presentations not directly supported by crmPack can
be easily produced. Here, we create plots of the dose-specific PDFs for
prior probabilities of toxicity after the first DLT is observed in a
fictional trial.
options <- McmcOptions(
burnin = 5000,
step = 1,
samples = 40000
)
data <- Data(
doseGrid = c(1, 3, 5, 10, 15, 20, 25, 40, 50, 80, 100),
x = c(1, 3, 5, 10, 15, 15, 15),
y = c(0, 0, 0, 0, 0, 1, 0),
ID = 1L:7L,
cohort = as.integer(c(1:4, 5, 5, 5))
)
model <- LogisticLogNormal(
mean = c(-1, 0),
cov =
matrix(c(3, -0.1, -0.1, 4),
nrow = 2
),
ref_dose = 56
)
samples <- mcmc(data, model, options)
tidySamples <- samples %>% tidy()
# The magrittr pipe is necessary here
tidySamples$data %>%
expand(
nesting(!!!.[1:10]),
Dose = data@doseGrid[2:11]
) %>%
mutate(Prob = probFunction(model, alpha0 = alpha0, alpha1 = alpha1)(Dose)) %>%
ggplot() +
geom_density(aes(x = Prob, colour = as.factor(Dose)), adjust = 1.5) +
labs(
title = "Posterior dose-specific PDFs for p(Tox)",
caption = "Dose 1 omitted as p(Tox) is essentially 0",
x = "p(Tox)"
) +
scale_colour_discrete("Dose") +
theme_light() +
theme(
axis.ticks.y = element_blank(),
axis.text.y = element_blank(),
axis.title.y = element_blank()
)sessionInfo()
#> R version 4.5.1 (2025-06-13 ucrt)
#> Platform: x86_64-w64-mingw32/x64
#> Running under: Windows 11 x64 (build 26200)
#>
#> Matrix products: default
#> LAPACK version 3.12.1
#>
#> locale:
#> [1] LC_COLLATE=C LC_CTYPE=German_Switzerland.utf8
#> [3] LC_MONETARY=German_Switzerland.utf8 LC_NUMERIC=C
#> [5] LC_TIME=German_Switzerland.utf8
#>
#> time zone: Asia/Taipei
#> tzcode source: internal
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] dplyr_1.1.4 magrittr_2.0.4 tidyr_1.3.1 kableExtra_1.4.0
#> [5] knitr_1.50 crmPack_2.0.0 ggplot2_4.0.1
#>
#> loaded via a namespace (and not attached):
#> [1] gtable_0.3.6 xfun_0.52 bslib_0.9.0
#> [4] processx_3.8.6 lattice_0.22-7 vctrs_0.6.5
#> [7] tools_4.5.1 Rdpack_2.6.4 ps_1.9.1
#> [10] generics_0.1.4 parallel_4.5.1 tibble_3.3.0
#> [13] pkgconfig_2.0.3 checkmate_2.3.3 RColorBrewer_1.1-3
#> [16] S7_0.2.0 lifecycle_1.0.4 compiler_4.5.1
#> [19] farver_2.1.2 stringr_1.6.0 textshaping_1.0.4
#> [22] htmltools_0.5.8.1 sass_0.4.10 yaml_2.3.10
#> [25] later_1.4.2 pillar_1.11.1 jquerylib_0.1.4
#> [28] cachem_1.1.0 parallelly_1.45.1 tidyselect_1.2.1
#> [31] digest_0.6.37 mvtnorm_1.3-3 stringi_1.8.7
#> [34] purrr_1.1.0 bookdown_0.44 labeling_0.4.3
#> [37] quarto_1.5.1 fastmap_1.2.0 grid_4.5.1
#> [40] cli_3.6.5 utf8_1.2.6 GenSA_1.1.14.1
#> [43] withr_3.0.2 scales_1.4.0 backports_1.5.0
#> [46] rmarkdown_2.30 lambda.r_1.2.4 gridExtra_2.3
#> [49] futile.logger_1.4.3 rjags_4-17 coda_0.19-4.1
#> [52] evaluate_1.0.5 rbibutils_2.4 viridisLite_0.4.2
#> [55] rlang_1.1.6 futile.options_1.0.1 Rcpp_1.1.0
#> [58] glue_1.8.0 formatR_1.14 xml2_1.3.8
#> [61] svglite_2.2.1 rstudioapi_0.17.1 jsonlite_2.0.0
#> [64] R6_2.6.1 systemfonts_1.3.1