This example demonstrates a simple response-adaptive randomization design with two stages.
The adaptive allocation probability is defined as:
\[ P(\text{Treatment}) = \frac{\hat p_{\text{Treatment}}} {\hat p_{\text{Treatment}}+\hat p_{\text{Control}}} \]
To avoid extreme allocation, the probability is restricted to:
\[ 0.30 \leq P(\text{Treatment}) \leq 0.70 \]
set.seed(123)
The first 100 patients are randomized equally between Treatment and Control.
Treatment coding is:
1 = Treatment0 = Controln_stage1 <- 100
trt1 <- rbinom(
n_stage1,
1,
0.50
)
For illustration, assume the true response rates are:
\[ P(\text{Response}|\text{Treatment}) = 0.70 \]
and
\[ P(\text{Response}|\text{Control}) = 0.50 \]
response1 <- rbinom(
n_stage1,
1,
prob = ifelse(
trt1 == 1,
0.70,
0.50
)
)
rate_trt <- mean(
response1[trt1 == 1]
)
rate_ctl <- mean(
response1[trt1 == 0]
)
cat(
"Observed Treatment response rate =",
round(rate_trt, 3),
"\n"
)
## Observed Treatment response rate = 0.745
cat(
"Observed Control response rate =",
round(rate_ctl, 3),
"\n"
)
## Observed Control response rate = 0.528
The Stage 2 Treatment allocation probability is calculated as:
\[ P(\text{Treatment}) = \frac{\hat p_T} {\hat p_T+\hat p_C} \]
where:
prob_trt_next <- rate_trt /
(rate_trt + rate_ctl)
To avoid extreme allocation, restrict the Treatment probability to the interval 0.30 to 0.70.
prob_trt_next <- max(
0.30,
min(
0.70,
prob_trt_next
)
)
prob_ctl_next <- 1 -
prob_trt_next
Display the Stage 2 allocation probabilities.
cat(
"Stage 2 Treatment allocation probability =",
round(prob_trt_next, 3),
"\n"
)
## Stage 2 Treatment allocation probability = 0.585
cat(
"Stage 2 Control allocation probability =",
round(prob_ctl_next, 3),
"\n"
)
## Stage 2 Control allocation probability = 0.415
n_stage2 <- 100
The next 100 patients are assigned Subject IDs from
SUBJ-101 through SUBJ-200.
subject_id <- sprintf(
"SUBJ-%03d",
101:200
)
randomization_number <- sprintf(
"R%04d",
101:200
)
For each Stage 2 patient, generate one random number from a Uniform(0,1) distribution.
\[ U_i \sim Uniform(0,1) \]
u_random <- runif(
n_stage2
)
The randomization rule is:
\[ \text{Treatment}_i = \begin{cases} \text{Treatment}, & U_i \leq P(\text{Treatment}) \ \text{Control}, & U_i > P(\text{Treatment}) \end{cases} \]
trt2 <- ifelse(
u_random <= prob_trt_next,
1,
0
)
treatment_assignment <- ifelse(
trt2 == 1,
"Treatment",
"Control"
)
For illustration:
A = TreatmentB = ControlIn a real double-blind trial, the actual mapping between blinded code and treatment would normally be restricted.
treatment_code <- ifelse(
trt2 == 1,
"A",
"B"
)
stage2_randomization <- data.frame(
Subject_ID =
subject_id,
Randomization_Number =
randomization_number,
Stage =
2,
Allocation_Probability_Treatment =
rep(
prob_trt_next,
n_stage2
),
Allocation_Probability_Control =
rep(
prob_ctl_next,
n_stage2
),
Random_Number =
round(
u_random,
6
),
Treatment_Code =
treatment_code,
Treatment_Assignment =
treatment_assignment,
stringsAsFactors = FALSE
)
head(
stage2_randomization,
10
)
## Subject_ID Randomization_Number Stage Allocation_Probability_Treatment
## 1 SUBJ-101 R0101 2 0.584989
## 2 SUBJ-102 R0102 2 0.584989
## 3 SUBJ-103 R0103 2 0.584989
## 4 SUBJ-104 R0104 2 0.584989
## 5 SUBJ-105 R0105 2 0.584989
## 6 SUBJ-106 R0106 2 0.584989
## 7 SUBJ-107 R0107 2 0.584989
## 8 SUBJ-108 R0108 2 0.584989
## 9 SUBJ-109 R0109 2 0.584989
## 10 SUBJ-110 R0110 2 0.584989
## Allocation_Probability_Control Random_Number Treatment_Code
## 1 0.415011 0.238726 A
## 2 0.415011 0.962359 B
## 3 0.415011 0.601366 B
## 4 0.415011 0.515030 A
## 5 0.415011 0.402573 A
## 6 0.415011 0.880247 B
## 7 0.415011 0.364092 A
## 8 0.415011 0.288239 A
## 9 0.415011 0.170645 A
## 10 0.415011 0.172172 A
## Treatment_Assignment
## 1 Treatment
## 2 Control
## 3 Control
## 4 Treatment
## 5 Treatment
## 6 Control
## 7 Treatment
## 8 Treatment
## 9 Treatment
## 10 Treatment
table(
stage2_randomization$
Treatment_Assignment
)
##
## Control Treatment
## 40 60
prop.table(
table(
stage2_randomization$
Treatment_Assignment
)
)
##
## Control Treatment
## 0.4 0.6
The overall adaptive randomization process is:
\[ \text{Stage 1: 1:1 Randomization} \]
\[ \downarrow \]
\[ \text{Observe Stage 1 Responses} \]
\[ \downarrow \]
\[ \text{Calculate New Allocation Probability} \]
\[ \downarrow \]
\[ \text{Stage 2 Adaptive Randomization} \]
For example, if the observed Stage 1 response rates are:
\[ \hat p_T = 0.70 \]
and
\[ \hat p_C = 0.50 \]
then:
\[ P(\text{Treatment}) = \frac{0.70}{0.70+0.50} = 0.583 \]
Therefore, approximately 58.3% of Stage 2 patients would be randomized to Treatment and 41.7% to Control.
Importantly, the exact number of patients assigned to each group will not necessarily equal these proportions because each patient is still randomized individually.
This example uses one adaptation after the first 100 patients.
Therefore, all Stage 2 patients use the same updated allocation probability.
The design is:
\[ 100\text{ patients} \rightarrow \text{Interim Analysis} \rightarrow \text{Update Allocation Probability} \rightarrow 100\text{ additional patients} \]
This is operationally simpler than updating the allocation probability after every individual patient.
In an actual clinical trial, the randomization algorithm, allocation restrictions, timing of adaptation, treatment-code mapping, and IRT/RTSM implementation should be prespecified and validated.