library(VisualizeSimon2Stage)
library(clinfun)
library(flextable)
library(ggplot2)This vignette of package VisualizeSimon2Stage (CRAN, Github, RPubs) documents the visualization of probabilities and operating characteristics of Simon’s two-stage Phase II design.
Examples in this vignette require that the search path has
library(VisualizeSimon2Stage)
library(clinfun)
library(flextable)
library(ggplot2)| Term / Abbreviation | Description |
|---|---|
| |> | Forward pipe operator introduced in R 4.1.0 |
$ |
Extract parts of an object |
binom |
Binomial density and distribution |
CRAN, R |
The Comprehensive R Archive Network |
class |
Object class |
flextable |
Flexible tables |
PASS |
Power Analysis & Sample Size, https://www.ncss.com/software/pass/ |
PET |
Probability of early termination |
ph2simon |
Simon’s 2-stage Phase II design |
S3, generic, methods |
S3 object oriented system, UseMethod; getS3method; https://adv-r.hadley.nz/s3.html |
S4, generic, methods |
S4 object oriented system, isS4; setClass; getMethod; https://adv-r.hadley.nz/s4.html |
search |
Search path |
seed |
Random number generation seed |
Simon’s two-stage design tests the one-sided hypothesis H_0: p\leq p_u vs. H_a: p>p_u for a binary response in the following steps.
In this vignette, p_u denotes the unacceptable response rate, and p_a denotes the acceptable response rate. The parameter nomenclature of r_1, n_1, r and n follows that of PASS and of function clinfun::ph2simon().
Types of Simon’s two-stage design include
'minimax' (default), minimum total sample size n'optimal', minimum expected total sample size \textrm{E}(n|p=p_u)'n1', minimum Stage-1 sample size n_1'maximax', to use up the user-provided maximum total sample size, i.e., parameter nmax of function clinfun::ph2simon()'all', all types listed aboveS3 class 'ph2simon'Function clinfun::ph2simon() returns an object of S3 class 'ph2simon'. The output is printed in the R console using S3 method dispatch clinfun:::print.ph2simon().
Example below provides the various Simon’s two-stage designs for hypotheses p_u=.2, p_a=.4, with Type-I error rate \alpha=5\% and Type-II error rate \beta=10\%.
(x = ph2simon(pu = .2, pa = .4, ep1 = .05, ep2 = .1))
Simon 2-stage Phase II design
Unacceptable response rate: 0.2
Desirable response rate: 0.4
Error rates: alpha = 0.05 ; beta = 0.1
r1 n1 r n EN(p0) PET(p0) qLo qHi
Minimax 5 24 13 45 31.23 0.6559 0.108 1.000
Admissible 4 20 14 49 30.74 0.6296 0.058 0.108
Optimal 4 19 15 54 30.43 0.6733 0.000 0.058
S4 class 'ph2simon4'Function ph2simon4() converts an S3 object 'ph2simon' to an S4 object 'ph2simon4'. The output is printed in the R console using S4 method dispatch getMethod(f = 'show', signature = 'ph2simon4').
x |> ph2simon4(type = 'all')
Simon's 2-Stage Design
Unacceptable Response Rate: 20.0%
Desirable Response Rate: 40.0%
Controlled Error Rates: α ≤ 5%, β ≤ 10%
Maximum Sample Size Allowed: 100
r1 n1 r n EN(pu) EN(pa) PET(pu) PET(pa) α β
minimax 5 24 13 45 31.2 44.2 65.6% 4.0% 4.8% 10.0%
optimal 4 19 15 54 30.4 51.6 67.3% 7.0% 4.8% 9.6%
n1 3 15 19 71 34.7 65.9 64.8% 9.1% 4.5% 9.8%
maximax 7 27 28 100 38.4 93.0 84.4% 9.5% 1.2% 9.9%
Given a Simon’s two-stage design (r_1,n_1,r,n) and a true response rate p, we have
The probability of early termination is
p_{\textrm{frail}} = \textrm{Pr}(X_1 \leq r_1)
The probability of failure to reject H_0 is
p_{\textrm{fail}} = \sum_{s_1 = r_1+1}^{n_1} \textrm{Pr}(X_1=s_1)\cdot\textrm{Pr}\left(X_2 \leq (r-s_1)\right)
The probability of successfully rejecting H_0 is
p_{\textrm{success}} = \sum_{s_1 = r_1+1}^{n_1} \textrm{Pr}(X_1=s_1)\cdot\textrm{Pr}(X_2 > (r-s_1))
The expected sample size is \textrm{E}(n) = p_{\textrm{frail}} \cdot n_1 + (1 - p_{\textrm{frail}}) \cdot n
The S3 generic simon_pr() calculates the probabilities of early termination, fail and success at one-or-more response rates p, either from an S3 object 'ph2simon',
x |> simon_pr(prob = c(.2, .3, .4)) |> as_flextable()
|
| Probabilities | ||
|---|---|---|---|---|
Response Rate | E(N) | Early Termination | Fail | Success |
p = 20% | 31.2 | 65.6% | 29.6% | 4.8% |
p = 30% | 40.2 | 22.9% | 30.3% | 46.8% |
p = 40% | 44.2 | 4.0% | 6.0% | 90.0% |
or from an S4 object 'ph2simon4',
x |> ph2simon4() |> simon_pr(prob = c(.2, .3, .4)) |> as_flextable()
|
| Probabilities | ||
|---|---|---|---|---|
Response Rate | E(N) | Early Termination | Fail | Success |
p = 20% | 31.2 | 65.6% | 29.6% | 4.8% |
p = 30% | 40.2 | 22.9% | 30.3% | 46.8% |
p = 40% | 44.2 | 4.0% | 6.0% | 90.0% |
or from the design parameters (r_1, n_1, r, n). In such case the user must call the S3 method dispatch simon_pr.ph2simon4() explicitly.
simon_pr.ph2simon4(prob = c(.2, .3, .4), r1 = 5L, n1 = 24L, r = 13L, n = 45L) |>
as_flextable()
|
| Probabilities | ||
|---|---|---|---|---|
Response Rate | E(N) | Early Termination | Fail | Success |
p = 20% | 31.2 | 65.6% | 29.6% | 4.8% |
p = 30% | 40.2 | 22.9% | 30.3% | 46.8% |
p = 40% | 44.2 | 4.0% | 6.0% | 90.0% |
S3 methods dispatches for the generic ggplot2::autoplot() visualize the probabilities of early termination, fail and success at p=p_u and p=p_a. The donut slices for success are colored with the highest opacity, indicating that they represent the Type-I error rate \alpha if p=p_u, and the power 1-\beta if p=p_a. The probabilities are visualized either from an S3 object 'ph2simon',
x |> autoplot(type = 'optimal')or from an S4 object 'ph2simon4'.
x |> ph2simon4(type = 'optimal') |> autoplot()or from the design parameters (r_1, n_1, r, n) and type. In such case the user must call the S3 method dispatch autoplot.ph2simon4() explicitly.
autoplot.ph2simon4(pu = .2, pa = .4, r1 = 4L, n1 = 19L, r = 15L, n = 54L, type = 'optimal')The S3 generic r_simon() simulates the number of positive responses in Simon’s two-stage design. Following examples show simulations of 1e4L trials at p=.3, either from an S3 object 'ph2simon',
set.seed(15); s = x |> r_simon(R = 1e4L, prob = .3, type = 'optimal')or from an S4 object 'ph2simon4',
set.seed(15); s1 = x |> ph2simon4(type = 'optimal') |> r_simon(R = 1e4L, prob = .3)
stopifnot(identical(s, s1))or from the design parameters (r_1, n_1, r, n). In such case the user must call the S3 method dispatch r_simon.ph2simon4() explicitly.
set.seed(15); s2 = r_simon.ph2simon4(R = 1e4L, prob = .3, r1 = 4L, n1 = 19L, r = 15L, n = 54L)
stopifnot(identical(s, s2))Obviously, at a sufficiently large simulated sample size, the Type-I error rate is controlled at \alpha<5\% when p=p_u=.2,
set.seed(31); x |> r_simon(R = 1e4L, prob = .2) |>
attr(which = 'dx', exact = TRUE) |>
as_flextable() |> set_caption(caption = 'pu = .2')Trial.Decision | Count | Percent |
|---|---|---|
[0,5]; Early Termination | 6,577 | 65.8% |
(5,13]; Fail | 2,961 | 29.6% |
(13,45]; Success | 462 | 4.6% |
Total | 10,000 | 100.0% |
and the Type-II error rate is controlled at \beta<10\%, or power (1-\beta)>90\%, when p=p_a=.4.
set.seed(24); x |> r_simon(R = 1e4L, prob = .4) |>
attr(which = 'dx', exact = TRUE) |>
as_flextable() |> set_caption(caption = 'pa = .4')Trial.Decision | Count | Percent |
|---|---|---|
[0,5]; Early Termination | 379 | 3.8% |
(5,13]; Fail | 583 | 5.8% |
(13,45]; Success | 9,038 | 90.4% |
Total | 10,000 | 100.0% |
Suppose we have three drugs A, B and C, with true response rate p^A=.3, p^B=.2 and p^C=.15, respectively.
p = c(A = .3, B = .2, C = .15)We simulated 1e4L Simon’s two-stage trials of each drug to obtain the operating characteristics, i.e., the percentage of trials in which each drug
The operating characteristics are visualized either from an S3 object 'ph2simon',
set.seed(52); x |> simon_oc(prob = p, R = 1e4L, type = 'optimal')or from an S4 object 'ph2simon4',
set.seed(52); x |> ph2simon4(type = 'optimal') |> simon_oc(prob = p, R = 1e4L)or from the design parameters (r_1, n_1, r, n). In such case the user must call the S3 method dispatch simon_oc.ph2simon4() explicitly.
set.seed(52); simon_oc.ph2simon4(prob = p, R = 1e4L, r1 = 4L, n1 = 19L, r = 15L, n = 54L)