Visualize Simon's Two-Stage Phase II Design

Tingting Zhan

Introduction

This vignette of package VisualizeSimon2Stage (CRAN, Github, RPubs) documents the visualization of probabilities and operating characteristics of Simon’s two-stage Phase II design.

Note to Users

Examples in this vignette require that the search path has

library(VisualizeSimon2Stage)
library(clinfun)
library(flextable)
library(ggplot2)

Terms and Abbreviations

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; methods; 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
table Cross tabulation

Simon’s Two-Stage Phase II Design

Notations

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.

  1. Enroll n_1 subjects.
  1. Enroll an additional (n-n_1) subjects.

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

S3 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%

Probabilities

Math

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

Numbers

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%

Visualization

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 = 5L, n1 = 24L, r = 13L, n = 45L, type = 'optimal')

Simulation

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%

Operating Characteristics

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)