-
Notifications
You must be signed in to change notification settings - Fork 0
/
README.Rmd
184 lines (136 loc) · 7.9 KB
/
README.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
---
output: github_document
bibliography: "mtdesign.bib"
---
<!-- README.md is generated from README.Rmd. Please edit that file -->
```{r, include = FALSE}
# /usr/local/lib/R/site-library/BH/include/boost
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```
# mtdesign
<!-- badges: start -->
[![CRAN status](https://www.r-pkg.org/badges/version/mtdesign)](https://CRAN.R-project.org/package=mtdesign)
[![Test Coverage](https://raw.githubusercontent.com/openpharma/mtdesign/_xml_coverage_reports/data/main/badge.svg)](https://github.com/openpharma/mtdesign/blob/_xml_coverage_reports/data/main/coverage.xml)
<!-- badges: end -->
## Introduction
The package `mtdesign` provides implementations of both Simon [-@SIMON] and Mander & Thompson [-@MANDER]. Other implementations of Simon's methods are available - for example, the `ph2simon` function in the `clinfun` package [@CLINFUN], but these do not provide easy access to non-optimal solutions in the way that `mtdesign` does. I am not aware of any other R-based implementations of Mander & Thompson's extension to Simon.
## Installation
Once available on CRAN, you can install `mtdesign` in the usual way:
`install.packages("mtdesign")`
You can install the development version of `mtdesign` from [GitHub](https://github.com/openpharma/mtdesign) with:
`devtools::install_github("openpharma/mtdesign")`
## Set up vignette environment
```{r}
# By policy, on CRAN, use only two cores, no matter how many are available.
if (requireNamespace("parallel", quietly = TRUE)) {
maxCores <- parallel::detectCores()
maxCores <- ifelse(identical(Sys.getenv("NOT_CRAN"), "true"), maxCores, min(maxCores, 2))
} else {
maxCores <- 1
}
```
## Example
Suppose that treatments with a response rate of less than 5% are of no interest but those with a response rate of at least 25% are worthy of further development. A Simon's 2-stage design to seek an efficacy signal with a significance level of 5% and a power of 80% is required.
```{r example}
library(mtdesign)
library(knitr)
library(dplyr)
simonDesign <- obtainDesign(p0 = 0.05, p1 = 0.25, alpha = 0.05, beta = 0.2, mander = FALSE, parallel = FALSE)
simonDesign %>%
select(-Alpha, -Beta, -p0, -p1, -PETAlt, -AveSizeAlt) %>%
kable(digits = c(0, 0, 0, 0, 3, 3, 2, 1, NA))
```
The table shows that the optimal design for these requirements is 0/9 2/17. The expected sample size is 12.0 and the probability of early termination is 63%. The significance level actually achieved is 4.7% and the power level achieved is 100% - 18.8% = 81.2%.
The power curves for both designs are easily plotted.
```{r}
powerPlot(simonDesign)
```
Obtaining the equivalent Mander & Thompson designs requires only a small change to the calls.
```{r}
manderDesign <- obtainDesign(
p0 = 0.05,
p1 = 0.25,
alpha = 0.05,
beta = 0.2,
cores = maxCores
)
manderDesign %>%
select(-Alpha, -Beta, -p0, -p1) %>%
kable(digits = c(0, 0, 0, 0, 3, 3, 2, 2, 2, 1, NA))
powerPlot(manderDesign)
```
### Constrained designs
Suppose a trial, for whatever reason, is restricted to using 8 participants in each stage. As shown above, the optimal Simon's two stage design is 0/9 2/17. That's close to n~1~ = 8, n = 16. Is there a (slightly) sub-optimal design that has n~1~ = 8, n = 16?
```{r}
x <- createGrid(p0 = 0.05, p1 = 0.25, alpha = 0.05, beta = 0.2, mander = FALSE)
y <- x %>% filter(nStage1 == 8, nTotal == 16)
z <- y %>% obtainDesign(cores = maxCores)
if (nrow(z) == 0) {
print("No acceptable designs were found.")
} else {
select(-Alpha, -Beta, -p0, -p1, -PETAlt, -AveSizeAlt) %>%
z() %>%
select(-Alpha, -Beta, -p0, -p1, -PETAlt, -AveSizeAlt) %>%
kable(digits = c(0, 0, 0, 0, 3, 3, 2, 1, NA))
}
```
No, there isn't. How close can we get?
```{r}
z1 <- y %>% augmentGrid()
bestSize <- z1 %>%
filter(Type1 < Alpha) %>%
slice_min(Type2)
bestSize %>%
select(-Alpha, -Beta, -p0, -p1, -PETAlt, -AveSizeAlt) %>%
kable(
caption = "Best sub-optimal design with required significance level",
digits = c(0, 0, 0, 0, 3, 3, 2, 1, NA)
)
bestPower <- z1 %>%
filter(Type2 < Beta) %>%
slice_min(Type1)
bestPower %>%
select(-Alpha, -Beta, -p0, -p1, -PETAlt, -AveSizeAlt) %>%
kable(
caption = "Best sub-optimal design with required power",
digits = c(0, 0, 0, 0, 3, 3, 2, 1, NA)
)
```
So the choice lies between a design which achieves the required significance level but has a power of only 77.1% or one which has the required power but which has a significance level of 15.1%. Both designs accept the null hypothesis when no responders are seen in the first group of eight participants. They differ in the critical value at the end of stage 2: 1 to maintain the power, 2 to maintain the significance level.
The power curve for each of these designs can be compared with that for the globally optimal design.
```{r}
plotData1 <- simonDesign %>%
filter(Criterion == "optimal") %>%
bind_rows(list(bestSize, bestPower))
powerPlot(plotData1)
```
## Package structure
The `mtdesign` package consists of three main functions:
* `createGrid` creates the grid (of nStage1, rFutility, nTotal and rTotal for Simon's design or nStage1, rFutility, rSuccess, nTotal and rTotal for a Mander & Thompson design) over which the brute force search for the required design(s) is conducted
* `augmentGrid`takes a grid created by `createGrid` and adds columns for probability of early termination, Type 1 error, Type 2 error and expected sample size to it.
* `obtainDesign` takes an augmented grid and identifies the optimal and minimax designs
## Error and warning messages and logging
The `mtdesign` package supports logging via the `futile.logger` package [@LOGGER]. Most functions simply report Entry and Exit at the `DEBUG` level.
The `augmentGrid` function reports steps of the parallelisation process at the `TRACE` level.
## Parallelisation
There is no known closed form solution to obtaining solutions to either Simon's original equations nor Mander & Thompson's extensions. The `mtdesign` package uses a brute force approach to evaluate the operating characteristics of all reasonable potential designs. The grids can be quickly become large, particularly for Mander & Thompson designs. For example, `createGrid(0.2, 0.4, alpha=0.1, beta=0.1)` creates a grid of almost 11 million candidate designs. `mtdesign` uses paralellisation to attempt to speed up the evaluation of candidate designs.
The `augmentGrid` function allows users some control over the parallelisation process:
* The `parallel` parameter defaults to `TRUE` and defines whether or not paralellisation is to be used.
* The `cores` parameter specifies how many cores are to be used. The default value, `NA` tells `mtdesign` to use all available (as defined by `parallel::detectCores()`), cores.
* The `minChunkSize` determines the smallest grid of candidate designs that will trigger paralellisation. The default value is `100000`.
The `parallel` package is required for parallelisation. If parallelisation is both needed (ie the grid size exceeds `minChunkSize`) and requested but the `parallel` package has not been installed, an error message is thrown and augmentation of the grid stops. If paralellisation is not requested and the grid contains one million or more rows, a warning is produced.
## Troubleshooting
If, when installing or using the `mtdesign` package, you get an error regarding a syntax error in an`.hpp` file, similar to the following
```R
.../BH/include/boost/math/tools/fraction.hpp:84:48: error: ‘long double’ is not a class, struct, or union type using value_type = typename T::value_type;
```
the issue is most likely a mismatch between the g++ compiler being used and the headers supplied by the `BH` package. There are only two solutions that I know of:
* Upgrade g++
* Downgrade the version of the `BH` package you are using. The appropriate package version depends on the version of the g++ compiler you are using.
## References
<div id="refs"></div>