
Simulation Workflow for Primary Analysis
Lei Shi, Matthew Secrest
2026-05-22
Source:vignettes/primary_simulation_workflow.Rmd
primary_simulation_workflow.RmdPrimary analysis
This vignette demonstrates Monte Carlo simulation for evaluating the EC-IPW and EC-AIPW weighting estimators proposed in Zhou et al. (2024) for the primary (placebo-controlled) phase.
1 Simulate a list of datasets for primary analysis
1.1 Create basic setup
# Initialize an empty data list
set.seed(2023)
data_matrix_list_null <- list()
data_matrix_list_alt <- list()
ntrial <- 500
# Specify the significance level alpha
alpha <- 0.05
# Specify the true effect size at the end of the study
true_effect <- 0
alt_effect <- 2.0 # tune this
# Specify column names
covariates_col_name <- c("x1", "x2", "x3", "x4", "x5")
outcome_col_name <- c("y1", "y2")
treatment_col_name <- "A"
trial_status_col_name <- "S"1.2 Generate simulation data list for null hypothesis
# Sequentially adding in datasets
for (trial_iter in 1:ntrial) {
# simulate 300 sample
normal <- copula::normalCopula(param = c(0.8), dim = 4, dispstr = "ar1")
# ========== generate internal covariates =============
X_int <- simulate_X_copula(
n = 200,
p = 4,
cp = normal, # copula
margins = c("binom", "binom", "binom", "exp"), # specify marginal distributions
paramMargins = list(
list(size = 1, prob = 0.7), # specify parameters for marginals
list(size = 1, prob = 0.9),
list(size = 1, prob = 0.3),
list(rate = 1 / 10)
)
)
X_int$x4 <- round(X_int$x4) + 1
X_int$x5 <- 30 + 10 * X_int$x1 + (7) * X_int$x2 + (-6) * X_int$x3 + (-0.5) * X_int$x4 + rnorm(200, mean = 0, sd = 10)
varnames <- c("1", paste0("x", 1:5))
# ============ generate external covariates ==============
X_ext <- simulate_X_copula(
n = 100,
p = 4,
cp = normal, # copula
margins = c("binom", "binom", "binom", "exp"), # specify marginal distributions
paramMargins = list(
list(size = 1, prob = 0.7), # specify parameters for marginals
list(size = 1, prob = 0.9),
list(size = 1, prob = 0.3),
list(rate = 1 / 10)
)
)
X_ext$x4 <- round(X_ext$x4) + 1
X_ext$x5 <- 50 + 10 * X_ext$x1 + (2) * X_ext$x2 + (-1) * X_ext$x3 + (-0.3) * X_ext$x4 + rnorm(100, mean = 0, sd = 10)
varnames <- c("1", paste0("x", 1:5))
# ============ Specify outcome models ==============
model_form_x_t1 <- setNames(c(10.0, 0.05, -1.5, -1.0, -0.2, -0.1), varnames) # 1.5*A, sigma = 4.0
model_form_x_t2 <- setNames(c(6.0, 0.5, -0.5, -1.0, -0.3, -0.06), varnames) # 1.8*A, sigma = 4.0
# model_form_x_t3 = setNames(c(5.0, 1.9, 1.4, -1.3, -0.4, -0.15), varnames) # 1.6*A, sigma = 4.0
# model_form_x_t4 = setNames(c(1.2, 1.0, 2.0, -0.5, -0.4, -0.10), varnames) # 2.5*A, sigma = 5.0
outcome_model_specs <- list(
list(
effect = 0, model_form_x = model_form_x_t1, # from data: true_effect = 1.5
noise_mean = 0, noise_sd = 4
), # model form for the first time point, given by model_form1
list(
effect = true_effect, model_form_x = model_form_x_t2, # from data: true_effect = 1.8
noise_mean = 0, noise_sd = 4
) # model form for the second time point, given by model_form2
)
# =========== generate trial data ============
Data <- simulate_trial(X_int,
X_ext,
num_treated = 100,
OLE_flag = FALSE,
T_cross = 2,
outcome_model_specs
)
data_matrix_list_null[[trial_iter]] <- Data
}
head(data_matrix_list_null[[1]])
#> x1 x2 x3 x4 x5 A S y1 y2
#> 1 0 0 0 2 37.56031 1 1 3.0752036 7.4562185
#> 2 1 1 0 15 32.11467 0 1 0.3814777 1.4237345
#> 3 1 1 0 5 29.65879 1 1 -2.1309058 4.8196265
#> 4 1 1 0 14 48.56377 1 1 -0.7990459 -3.6642685
#> 5 1 1 1 21 15.37401 1 1 1.7543228 -0.5165716
#> 6 1 1 1 13 23.47198 1 1 -2.1335935 -4.05330441.3 Generate simulation data list for alternative hypothesis
# Sequentially adding in datasets
for (trial_iter in 1:ntrial) {
# simulate 300 sample
normal <- copula::normalCopula(param = c(0.8), dim = 4, dispstr = "ar1")
# ========== generate internal covariates =============
X_int <- simulate_X_copula(
n = 200,
p = 4,
cp = normal, # copula
margins = c("binom", "binom", "binom", "exp"), # specify marginal distributions
paramMargins = list(
list(size = 1, prob = 0.7), # specify parameters for marginals
list(size = 1, prob = 0.9),
list(size = 1, prob = 0.3),
list(rate = 1 / 10)
)
)
X_int$x4 <- round(X_int$x4) + 1
X_int$x5 <- 30 + 10 * X_int$x1 + (7) * X_int$x2 + (-6) * X_int$x3 + (-0.5) * X_int$x4 + rnorm(200, mean = 0, sd = 10)
varnames <- c("1", paste0("x", 1:5))
# ============ generate external covariates ==============
X_ext <- simulate_X_copula(
n = 100,
p = 4,
cp = normal, # copula
margins = c("binom", "binom", "binom", "exp"), # specify marginal distributions
paramMargins = list(
list(size = 1, prob = 0.7), # specify parameters for marginals
list(size = 1, prob = 0.9),
list(size = 1, prob = 0.3),
list(rate = 1 / 10)
)
)
X_ext$x4 <- round(X_ext$x4) + 1
X_ext$x5 <- 50 + 10 * X_ext$x1 + (2) * X_ext$x2 + (-1) * X_ext$x3 + (-0.3) * X_ext$x4 + rnorm(100, mean = 0, sd = 10)
varnames <- c("1", paste0("x", 1:5))
# ============ Specify outcome models ==============
model_form_x_t1 <- setNames(c(10.0, 0.05, -1.5, -1.0, -0.2, -0.1), varnames) # 1.5*A, sigma = 4.0
model_form_x_t2 <- setNames(c(6.0, 0.5, -0.5, -1.0, -0.3, -0.06), varnames) # 1.8*A, sigma = 4.0
# model_form_x_t3 = setNames(c(5.0, 1.9, 1.4, -1.3, -0.4, -0.15), varnames) # 1.6*A, sigma = 4.0
# model_form_x_t4 = setNames(c(1.2, 1.0, 2.0, -0.5, -0.4, -0.10), varnames) # 2.5*A, sigma = 5.0
outcome_model_specs <- list(
list(
effect = 0, model_form_x = model_form_x_t1, # from data: true_effect = 1.5
noise_mean = 0, noise_sd = 4
), # model form for the first time point, given by model_form1
list(
effect = alt_effect, model_form_x = model_form_x_t2, # from data: true_effect = 1.8
noise_mean = 0, noise_sd = 4
) # model form for the second time point, given by model_form2
)
# =========== generate trial data ============
Data <- simulate_trial(X_int,
X_ext,
num_treated = 100,
OLE_flag = FALSE,
T_cross = 2,
outcome_model_specs
)
data_matrix_list_alt[[trial_iter]] <- Data
}
data_matrix_list_alt[[1]]
#> x1 x2 x3 x4 x5 A S y1 y2
#> 1 1 1 0 9 34.261000 1 1 5.06180546 1.541673508
#> 2 1 1 0 3 38.964068 0 1 1.51775659 1.929797465
#> 3 1 1 0 9 47.732823 0 1 0.99799915 3.777971378
#> 4 1 1 0 6 45.968865 1 1 1.45481237 -9.007860159
#> 5 1 1 0 14 34.363974 0 1 5.33791999 2.835805837
#> 6 1 1 0 3 52.986543 1 1 4.58137992 3.205442321
#> 7 1 1 1 12 31.819701 0 1 5.46653981 3.086270436
#> 8 1 1 0 9 61.188139 0 1 1.36693439 -0.166789413
#> 9 0 0 0 2 20.548496 1 1 18.10356469 10.633951752
#> 10 0 1 0 2 32.048293 1 1 2.32831592 -2.414659843
#> 11 1 1 1 32 25.097566 1 1 -0.77375916 -2.575526216
#> 12 1 1 1 20 44.056397 1 1 -1.24714208 -3.308753518
#> 13 0 1 0 13 15.620922 1 1 11.57445541 -0.667855246
#> 14 1 1 0 5 54.477385 1 1 -1.50722155 4.096428997
#> 15 1 1 1 9 32.833391 1 1 -0.40946754 6.709266651
#> 16 1 1 1 52 18.491665 1 1 -7.35006511 -8.795957820
#> 17 0 1 0 3 23.490006 0 1 10.44826408 5.027272256
#> 18 0 0 0 2 27.104385 1 1 8.54100942 -1.928341671
#> 19 1 1 0 4 32.249188 0 1 1.39435462 1.733370225
#> 20 0 1 0 13 33.217198 0 1 -0.50558503 -7.733764587
#> 21 1 1 0 6 28.877335 1 1 -1.07481364 1.140907353
#> 22 1 1 1 11 34.994414 0 1 7.71059452 1.237753220
#> 23 0 1 0 4 28.176686 1 1 4.82414207 12.459162669
#> 24 1 1 1 13 20.120943 0 1 -3.92351241 2.374514797
#> 25 1 1 1 39 18.075206 1 1 -0.67654071 -12.241394541
#> 26 1 1 1 30 38.909708 0 1 -5.48033586 -9.181802486
#> 27 0 1 0 11 33.795766 1 1 0.49282976 5.502781890
#> 28 1 1 0 8 46.223652 1 1 -1.20291004 7.366232161
#> 29 0 1 0 10 19.592277 1 1 9.77139860 2.449312034
#> 30 1 1 0 10 37.718009 1 1 7.75343050 -1.309135060
#> 31 1 1 0 3 54.960156 1 1 0.53778308 3.455085928
#> 32 1 1 0 3 33.081736 1 1 4.23093593 3.349712478
#> 33 0 0 0 1 43.073230 0 1 5.81049311 5.029691317
#> 34 1 1 1 9 43.573332 1 1 -0.96238327 3.909771838
#> 35 1 1 1 23 33.956818 1 1 0.26088324 5.636234686
#> 36 1 1 0 8 44.654667 0 1 7.10885369 2.136421438
#> 37 0 1 0 5 36.037474 1 1 3.01184535 0.586590839
#> 38 1 1 1 6 22.671210 1 1 3.73279568 3.369351868
#> 39 1 1 1 21 39.707455 1 1 0.53123681 -3.214015085
#> 40 1 1 0 3 51.797471 0 1 8.02409756 5.921910384
#> 41 1 1 0 11 51.279557 0 1 1.35254812 -1.184991117
#> 42 1 1 0 7 58.722721 0 1 6.36269295 -0.711933346
#> 43 0 0 0 1 21.349785 0 1 10.30081378 3.909858405
#> 44 1 1 1 8 50.103091 0 1 4.99434483 -1.381130072
#> 45 1 1 1 45 35.908016 0 1 -3.78617246 -15.708653806
#> 46 0 0 0 14 37.430826 1 1 0.26764513 5.460564589
#> 47 0 1 0 2 34.510742 1 1 2.71808544 6.172794488
#> 48 1 1 0 13 20.362880 0 1 8.54092103 1.100186952
#> 49 0 1 0 4 34.604678 1 1 5.09621488 -7.978186803
#> 50 1 1 1 16 20.081972 0 1 -1.52997198 -0.713531902
#> 51 1 1 1 25 38.675229 1 1 -1.94120943 -4.138899169
#> 52 1 1 0 6 50.180843 0 1 7.12155031 -2.249444728
#> 53 1 1 1 41 21.540080 0 1 5.83575916 -11.506947990
#> 54 0 1 0 11 26.716486 1 1 1.47728090 -1.699294324
#> 55 0 1 0 1 55.846730 0 1 -0.42100957 3.312103975
#> 56 1 1 0 12 36.915862 0 1 1.33834949 -4.713547125
#> 57 1 1 1 39 19.160014 0 1 -1.79592454 -7.438429659
#> 58 1 1 1 28 22.617888 0 1 -0.08524851 -8.348410717
#> 59 1 1 0 3 41.007810 1 1 -4.09055248 2.855467353
#> 60 1 1 0 6 31.926114 0 1 8.80115401 7.489837626
#> 61 1 1 0 6 36.179577 1 1 4.28685987 2.633716683
#> 62 0 1 0 2 36.841007 1 1 7.46690278 7.041028272
#> 63 0 0 0 4 20.854963 1 1 2.34636105 6.064833106
#> 64 1 1 0 9 45.090981 0 1 4.60181102 0.959484988
#> 65 1 1 0 1 33.882258 0 1 4.84366655 3.040882347
#> 66 1 1 0 5 43.057545 0 1 5.25648766 3.096752727
#> 67 0 1 0 3 38.341688 1 1 7.22958077 -1.761621032
#> 68 1 1 1 12 54.647236 1 1 -3.18188305 -4.240372204
#> 69 0 1 0 7 43.303430 0 1 0.47950231 -2.682574726
#> 70 0 0 0 6 39.813863 0 1 6.40780060 -0.141333343
#> 71 0 1 0 16 41.249802 0 1 7.07882167 -0.389844743
#> 72 1 1 1 53 -9.698325 1 1 -2.37622447 -16.407757799
#> 73 0 1 1 15 31.439967 0 1 7.20220721 -12.453960076
#> 74 0 0 0 1 33.633397 0 1 4.87925787 8.117176936
#> 75 1 1 1 44 18.487587 1 1 -3.81310262 -6.437436049
#> 76 1 1 0 4 26.532584 1 1 0.24391431 5.342532708
#> 77 1 1 0 10 34.416192 0 1 9.30388253 -0.517477474
#> 78 1 1 1 6 50.824618 1 1 7.08702871 0.710544321
#> 79 1 1 0 3 47.199273 1 1 4.73192579 9.002979995
#> 80 0 1 0 5 58.521586 0 1 1.62350490 0.329636844
#> 81 1 1 1 20 27.882089 1 1 0.80366720 2.758506253
#> 82 1 1 1 11 32.269664 0 1 8.65418888 -9.111579233
#> 83 1 1 0 5 55.835802 0 1 3.17736286 5.613660918
#> 84 1 1 0 12 29.175916 0 1 4.41135042 6.392011318
#> 85 0 0 0 1 30.850301 1 1 9.47654529 5.829519314
#> 86 0 1 0 2 28.207642 1 1 -0.58985003 0.957166851
#> 87 0 0 0 1 11.365566 1 1 6.23571197 7.608760593
#> 88 1 1 0 5 26.151912 1 1 10.92690542 0.570275357
#> 89 1 1 1 17 47.322916 1 1 2.84972459 0.569154531
#> 90 0 0 0 3 32.185774 0 1 4.50891220 3.949955696
#> 91 1 1 1 17 33.815669 1 1 6.45159271 -2.576513887
#> 92 0 1 0 2 43.717022 0 1 6.40924545 -5.303522684
#> 93 1 1 0 7 39.416607 1 1 5.50240673 3.502085493
#> 94 0 0 0 1 32.262520 1 1 10.08101068 8.159180183
#> 95 1 1 0 10 53.507395 1 1 -4.38583254 2.707968847
#> 96 0 0 0 5 34.802175 1 1 8.19636972 2.250292413
#> 97 0 1 0 4 33.875578 0 1 6.36893585 -5.019955253
#> 98 1 1 0 6 68.091368 1 1 -1.99379678 7.509072379
#> 99 1 1 1 21 25.201954 0 1 -0.58082231 0.484478801
#> 100 0 1 0 7 35.988076 0 1 7.23855382 -1.121805533
#> 101 0 0 0 1 32.379853 0 1 5.08277403 1.647727310
#> 102 1 1 0 5 40.058447 0 1 7.78144164 6.121653951
#> 103 1 1 1 11 22.165128 0 1 6.49863338 0.514046732
#> 104 1 1 1 30 39.455907 1 1 1.45803203 4.095153030
#> 105 0 1 0 2 23.244401 1 1 8.16605710 -1.226874102
#> 106 0 1 0 15 35.903194 0 1 1.95862291 7.033393522
#> 107 0 0 0 4 33.883396 0 1 7.69766541 4.502584640
#> 108 1 1 0 9 28.315373 0 1 -2.27852335 -2.293822632
#> 109 1 1 1 55 22.713337 1 1 -5.52543984 -10.674658256
#> 110 0 1 0 5 33.616696 0 1 5.65422046 3.068925168
#> 111 0 1 0 18 23.484053 0 1 6.04498485 3.253013786
#> 112 0 1 0 2 26.648894 0 1 7.92478164 -6.842340698
#> 113 1 1 0 11 43.707036 1 1 7.60096249 2.018994157
#> 114 1 1 1 48 13.660804 0 1 0.83055327 -8.396852209
#> 115 0 0 0 15 23.395484 1 1 -0.50744113 1.640013614
#> 116 0 1 0 7 15.619340 0 1 8.28863744 4.932798267
#> 117 1 1 0 6 51.475198 0 1 0.11923110 -3.244792670
#> 118 1 1 0 8 45.589738 0 1 0.02282240 2.919757048
#> 119 0 0 0 10 3.468689 1 1 2.33633815 7.871816302
#> 120 1 1 0 3 54.456944 0 1 0.76221598 8.241708948
#> 121 1 1 1 31 36.263616 1 1 -3.08754374 -3.967661814
#> 122 0 1 0 5 22.200035 1 1 6.57277669 5.223948496
#> 123 1 1 1 5 16.016075 1 1 8.48342874 0.221887639
#> 124 1 1 1 23 33.412264 0 1 -1.63924448 -5.402676448
#> 125 1 1 0 17 34.681049 0 1 2.62000224 -0.927061836
#> 126 1 1 1 20 37.121992 1 1 -1.00497939 -5.098343724
#> 127 0 1 0 9 23.678611 0 1 6.02863247 -0.791317373
#> 128 1 1 0 14 46.766695 0 1 1.20276251 -2.153388580
#> 129 1 1 0 2 48.649082 0 1 -0.89239247 10.677939452
#> 130 1 1 1 13 25.486024 1 1 2.53606701 1.948935512
#> 131 1 1 1 89 -1.330384 1 1 -5.01382002 -16.277245547
#> 132 1 1 1 8 31.760365 0 1 -3.31778123 5.604140402
#> 133 0 1 0 3 44.805468 0 1 3.92228516 1.416059637
#> 134 1 1 1 41 20.939030 0 1 -7.07691797 -6.942723995
#> 135 1 1 0 4 39.554941 1 1 -2.03016072 6.452379329
#> 136 1 1 0 4 48.203243 1 1 3.31282043 -2.426520260
#> 137 0 1 0 7 36.503522 0 1 9.69937878 4.637415821
#> 138 0 0 0 3 31.350360 0 1 11.17169415 5.414481970
#> 139 1 1 0 2 40.956262 1 1 6.28070827 0.190894684
#> 140 1 1 0 8 45.728706 0 1 -3.45392987 6.616379339
#> 141 1 1 1 5 48.057887 0 1 4.36480806 -0.113285187
#> 142 0 1 0 2 25.697203 1 1 11.41173764 9.188906162
#> 143 1 1 0 5 55.229500 1 1 2.88954693 0.135702399
#> 144 1 1 1 16 16.312023 1 1 7.69837871 -0.182918190
#> 145 1 1 0 4 45.160581 0 1 2.05497849 -0.292767538
#> 146 0 0 0 5 11.314102 1 1 1.17985575 7.411340651
#> 147 1 1 0 5 64.731202 0 1 -0.77164978 5.804877524
#> 148 0 1 0 13 34.264362 0 1 -3.04065698 -4.711395748
#> 149 1 1 0 25 30.896016 1 1 1.41328880 -1.121732843
#> 150 1 1 0 12 50.197815 0 1 -2.23739198 2.465135244
#> 151 0 1 0 2 53.119146 1 1 3.82851002 9.278172461
#> 152 1 1 0 15 57.947243 0 1 4.31153779 -8.881014163
#> 153 1 1 1 13 28.760690 0 1 3.57621729 0.346728675
#> 154 0 0 0 6 25.660384 1 1 3.16066750 1.339538411
#> 155 0 0 0 5 30.050654 1 1 9.34729400 11.559720859
#> 156 1 1 0 10 60.216147 1 1 2.49848105 6.798782965
#> 157 1 1 1 18 33.953472 0 1 -0.05209902 -7.199758533
#> 158 1 1 0 2 38.040303 0 1 12.24904927 1.449869249
#> 159 1 1 0 5 51.726448 0 1 3.35505255 5.833157766
#> 160 0 0 0 4 34.674099 1 1 5.25297796 -2.678474938
#> 161 1 1 0 10 39.096550 1 1 6.31117528 -3.752485500
#> 162 1 1 1 19 22.248951 1 1 1.60846628 -7.248528988
#> 163 1 1 0 9 41.949276 0 1 14.71006547 -3.874117669
#> 164 0 0 0 5 38.381544 0 1 5.99423073 7.210022195
#> 165 0 1 0 2 26.739976 1 1 7.20254885 10.849167390
#> 166 0 1 0 2 50.927639 1 1 5.05830799 -1.766499061
#> 167 1 1 1 28 21.363050 0 1 -2.30298941 -9.523888736
#> 168 1 1 1 15 33.713043 1 1 -1.27058834 -6.255502179
#> 169 1 1 1 68 19.177456 0 1 -2.33666770 -14.521344851
#> 170 1 0 0 8 40.946052 1 1 -0.26343493 11.562329001
#> 171 0 1 1 7 21.306612 1 1 4.43486710 2.813954907
#> 172 0 1 0 5 32.012469 0 1 2.01383420 -2.523625272
#> 173 1 1 0 11 39.520997 1 1 6.78059917 -1.492304296
#> 174 0 1 0 9 45.918568 0 1 2.15359310 -5.510952838
#> 175 1 1 1 13 27.958083 1 1 0.39987864 -6.230124147
#> 176 0 0 0 1 17.785996 0 1 7.87811035 7.624261831
#> 177 1 0 0 1 39.413252 0 1 9.42232043 7.569122281
#> 178 1 1 0 6 40.695937 0 1 6.41421789 0.005232859
#> 179 0 0 0 5 41.676161 0 1 3.54369607 0.525656350
#> 180 1 1 1 10 23.961967 1 1 4.12215985 3.868381667
#> 181 1 1 0 6 48.375253 1 1 -0.43937735 3.143366471
#> 182 1 1 1 17 68.205962 1 1 -6.31037604 1.558877924
#> 183 1 1 0 19 48.849670 0 1 -2.06043346 -2.871922313
#> 184 1 1 0 9 51.073585 0 1 -1.69017769 3.760028235
#> 185 0 1 0 9 15.754358 1 1 1.71894910 6.178437648
#> 186 1 1 1 15 27.712067 1 1 6.32874980 -5.257553496
#> 187 1 1 0 9 47.239964 1 1 10.09848573 4.168258168
#> 188 1 1 0 8 48.121510 1 1 -0.69627204 3.660827289
#> 189 0 1 0 4 34.934954 1 1 2.87761180 5.968190129
#> 190 0 1 1 7 34.035652 1 1 1.49514643 3.984646866
#> 191 0 1 0 3 17.460584 0 1 9.07974908 5.352854433
#> 192 1 1 0 10 33.025631 0 1 -3.44888479 0.292946452
#> 193 1 1 0 8 51.270853 0 1 -3.02234055 6.135247458
#> 194 0 1 0 7 28.053236 0 1 0.57116254 -1.851365012
#> 195 1 1 1 19 19.504082 0 1 0.32155907 -9.952971523
#> 196 1 1 1 11 34.826771 1 1 1.73749561 9.449655893
#> 197 1 1 1 55 16.865280 0 1 -8.06483779 -8.691132100
#> 198 1 1 0 7 30.302025 1 1 3.31537497 4.297270168
#> 199 0 1 0 8 18.890965 1 1 5.16867956 -3.119319021
#> 200 1 1 0 7 43.664701 0 1 -0.77430150 7.991778187
#> 201 0 1 0 1 48.778360 0 0 5.83255643 4.031966824
#> 202 1 1 1 33 51.118988 0 0 4.71061324 -1.102463607
#> 203 1 1 1 7 64.756921 0 0 5.08420590 5.344209960
#> 204 0 1 0 2 42.372513 0 0 3.36682104 2.545740012
#> 205 1 1 1 13 47.323607 0 0 -3.86201868 0.410113093
#> 206 1 1 0 15 49.072685 0 0 2.74002557 -1.405446010
#> 207 1 1 1 17 45.954440 0 0 -0.86298263 -8.599780256
#> 208 1 1 1 22 57.288157 0 0 -9.68123306 -5.294012319
#> 209 1 1 1 3 46.252037 0 0 -3.69542116 1.967841705
#> 210 1 1 0 18 70.865445 0 0 -0.21470974 -8.920771096
#> 211 1 1 0 4 79.935834 0 0 -0.71936776 -1.863811732
#> 212 0 1 0 10 61.769259 0 0 1.14348952 -0.069269889
#> 213 1 1 1 21 58.321041 0 0 -3.33904789 -3.946552849
#> 214 1 1 0 5 80.047995 0 0 -4.32960940 -2.888750168
#> 215 0 0 0 4 58.651780 0 0 6.40618604 -3.617866298
#> 216 1 1 1 16 51.845026 0 0 0.01544653 -3.944605988
#> 217 0 1 0 7 35.192706 0 0 -3.01794828 0.699105144
#> 218 1 1 0 6 49.554526 0 0 -3.89810942 5.789909928
#> 219 1 1 0 8 77.286415 0 0 -2.93491970 -3.464115005
#> 220 0 1 0 4 38.806523 0 0 -3.14508411 -4.905008661
#> 221 1 1 0 2 52.347112 0 0 3.33809029 4.782500423
#> 222 0 1 0 8 55.092169 0 0 5.67388644 2.938206951
#> 223 1 1 1 10 50.398662 0 0 -4.63106147 8.483475669
#> 224 1 1 0 5 48.219761 0 0 -3.22763519 0.508597860
#> 225 0 1 0 12 50.457623 0 0 0.70363699 3.542262180
#> 226 1 1 1 24 50.909703 0 0 -5.20923117 -5.414028021
#> 227 1 1 0 8 46.718570 0 0 2.79419877 -5.251041940
#> 228 0 0 0 1 54.878339 0 0 4.12233767 2.977103067
#> 229 1 1 0 9 60.537557 0 0 -3.45649574 0.107607921
#> 230 1 1 0 3 61.434595 0 0 2.23484313 6.423934862
#> 231 0 1 0 3 61.406969 0 0 0.72693967 -0.540714585
#> 232 0 0 0 9 48.854201 0 0 1.75443099 -1.073544480
#> 233 1 1 0 7 37.814367 0 0 -0.07656232 0.779739769
#> 234 0 1 0 2 55.712154 0 0 4.14129700 -0.752298123
#> 235 1 1 1 13 50.196482 0 0 6.26416754 0.117345264
#> 236 1 1 1 29 25.025329 0 0 1.60068108 -11.711629439
#> 237 1 1 1 30 49.755863 0 0 -7.93331988 -7.186298658
#> 238 1 1 1 7 58.439587 0 0 -0.94739166 -1.648516746
#> 239 0 0 0 2 53.883372 0 0 5.31352104 -1.923330432
#> 240 0 0 0 2 55.188392 0 0 3.22944554 -1.020838547
#> 241 1 1 1 5 57.470998 0 0 -1.21925592 2.142456499
#> 242 1 1 0 19 57.884838 0 0 -3.63225968 -3.270769078
#> 243 1 1 0 8 62.148134 0 0 7.29799621 -3.343434604
#> 244 0 1 0 6 46.666385 0 0 -2.20189954 -3.872922973
#> 245 1 1 0 6 46.481100 0 0 -0.15311758 -2.963960031
#> 246 1 1 1 9 43.293929 0 0 1.46342133 -3.717322095
#> 247 0 0 0 8 32.414051 0 0 2.36430542 3.594977801
#> 248 1 1 1 16 75.205657 0 0 -2.69762912 1.616590147
#> 249 1 1 1 9 48.453498 0 0 4.48638302 -2.999126345
#> 250 1 1 0 5 53.215558 0 0 -8.02465785 6.142776315
#> 251 0 1 0 7 55.968257 0 0 2.60304484 -1.468344455
#> 252 1 1 0 2 65.826565 0 0 -2.23109110 -1.509220369
#> 253 1 1 1 28 47.398775 0 0 4.18573558 -0.471853175
#> 254 0 1 0 3 53.822649 0 0 1.77135997 -2.905220147
#> 255 1 1 1 13 64.829548 0 0 5.53716234 -2.203948547
#> 256 1 1 0 3 44.831534 0 0 -2.39697244 6.590857926
#> 257 1 1 0 20 69.383633 0 0 3.11730058 -2.737188187
#> 258 0 1 0 4 50.295383 0 0 4.11714058 3.442295555
#> 259 1 1 0 10 53.414722 0 0 9.72765771 -3.205491907
#> 260 1 1 0 6 66.126891 0 0 7.87894655 1.266947751
#> 261 1 1 0 10 61.326122 0 0 10.26813734 -2.620498357
#> 262 1 1 1 12 57.492598 0 0 -1.52018673 -9.277013312
#> 263 1 1 0 2 57.085470 0 0 5.15874638 -2.420023625
#> 264 0 1 0 2 46.391897 0 0 6.90942200 2.204755733
#> 265 1 1 0 1 57.547876 0 0 9.76064241 9.626349192
#> 266 1 1 1 36 33.294141 0 0 -7.30084466 -3.833871162
#> 267 1 1 1 67 34.906089 0 0 -8.37344260 -11.229012499
#> 268 0 1 0 10 29.659376 0 0 4.48539315 -5.902335315
#> 269 0 1 0 6 48.845327 0 0 12.24883909 -1.070457919
#> 270 1 1 0 4 63.725738 0 0 0.39352995 4.521134028
#> 271 0 0 0 1 61.016236 0 0 10.64856747 2.690257315
#> 272 1 1 0 9 62.737064 0 0 3.19430118 1.825158406
#> 273 1 1 1 30 57.864330 0 0 -5.62287895 -8.512973677
#> 274 1 1 1 13 53.119592 0 0 -9.11698274 -6.103780609
#> 275 1 1 0 17 58.128440 0 0 1.72018171 -0.529629274
#> 276 1 1 0 3 60.644897 0 0 -2.28851125 4.457340209
#> 277 0 1 1 14 48.846299 0 0 -0.98874631 -3.468658973
#> 278 1 1 0 15 49.731396 0 0 1.95668288 -2.911275420
#> 279 1 1 1 16 42.321243 0 0 10.27458034 3.170969335
#> 280 1 1 1 38 44.436916 0 0 3.08889257 -7.893200914
#> 281 1 1 0 6 54.990202 0 0 1.81288843 3.013739369
#> 282 1 1 0 6 57.027314 0 0 3.26659656 2.574169730
#> 283 0 0 0 2 54.939818 0 0 4.38150969 0.166007393
#> 284 0 1 0 1 39.552397 0 0 10.01318060 0.361886791
#> 285 1 1 1 27 50.071518 0 0 2.17932291 -4.792382650
#> 286 0 0 0 3 42.980502 0 0 5.27514281 2.504375999
#> 287 1 1 0 28 57.554121 0 0 -9.13442316 -5.640939202
#> 288 1 1 0 6 60.365563 0 0 0.89255716 -4.147623585
#> 289 0 1 0 2 43.346335 0 0 12.91722718 4.691051550
#> 290 1 1 0 10 69.346395 0 0 -6.36819042 -12.296156759
#> 291 1 1 1 23 61.456749 0 0 -3.47832124 -12.559770608
#> 292 1 1 1 21 61.614180 0 0 -7.29175819 -9.170123070
#> 293 1 1 1 11 62.992713 0 0 -3.60182639 -7.373173681
#> 294 1 1 1 13 74.301888 0 0 -2.86416723 -9.025064563
#> 295 0 0 0 1 52.819951 0 0 2.68280231 5.165662634
#> 296 1 1 0 2 76.042539 0 0 0.80171256 -0.906519681
#> 297 1 1 1 20 54.708114 0 0 -12.10969620 -4.238926651
#> 298 1 1 0 6 67.195896 0 0 2.07758749 -4.956690069
#> 299 1 1 1 15 57.441404 0 0 -2.18238897 -4.708805925
#> 300 1 1 1 24 62.865235 0 0 -3.02622064 -10.3442984082 Parametric inference
method_IPW_optimal_weight <- ec_ipw(
ps_formula = "S ~ x1 + x2 + x3 + x4 + x5"
)
method_AIPW_optimal_weight <- ec_aipw(
ps_formula = "S ~ x1 + x2 + x3 + x4 + x5",
outcome_formula = c(
"y1 ~ x1 + x2 + x3 + x4 + x5",
"y2 ~ x1 + x2 + x3 + x4 + x5"
)
)
method_IPW_zero_weight <- ec_ipw(
ps_formula = "S ~ x1 + x2 + x3 + x4 + x5",
weight = 0
)
method_AIPW_zero_weight <- ec_aipw(
ps_formula = "S ~ x1 + x2 + x3 + x4 + x5",
outcome_formula = c(
"y1 ~ x1 + x2 + x3 + x4 + x5",
"y2 ~ x1 + x2 + x3 + x4 + x5"
),
weight = 0
)
method_obj_list <- list(
method_IPW_optimal_weight,
method_AIPW_optimal_weight,
method_IPW_zero_weight,
method_AIPW_zero_weight
)
# create a simulation object for primary analysis
simulation_primary_obj <- setup_simulation_primary(
data_matrix_list_null = data_matrix_list_null, # two scenarios
data_matrix_list_alt = data_matrix_list_alt,
trial_status_col_name = trial_status_col_name,
treatment_col_name = treatment_col_name,
outcome_col_name = outcome_col_name,
covariates_col_name = covariates_col_name,
method_obj_list = method_obj_list,
true_effect = true_effect,
alt_effect = alt_effect,
alpha = alpha,
method_description = c(
"IPW, optimal weight",
"AIPW, optimal weight",
"IPW, zero weight",
"AIPW, zero weight"
)
)
simulation_report <- run_simulation(simulation_primary_obj, quiet = TRUE)
simulation_report # Type I error and Power
#> method_description bias variance mse coverage type_I_error
#> 1 IPW, optimal weight -0.0541718304 0.4845047 0.4874393 0.946 0.054
#> 2 AIPW, optimal weight 0.0011470217 0.3140481 0.3140494 0.946 0.054
#> 3 IPW, zero weight -0.0007803934 0.5317429 0.5317435 0.956 0.044
#> 4 AIPW, zero weight -0.0005666468 0.3353926 0.3353929 0.946 0.054
#> power
#> 1 0.784
#> 2 0.954
#> 3 0.786
#> 4 0.9443 Bootstrap inference
method_IPW_optimal_weight <- ec_ipw(
ps_formula = "S ~ x1 + x2 + x3 + x4 + x5",
bootstrap = 50,
bootstrap_ci_type = "perc"
)
method_AIPW_optimal_weight <- ec_aipw(
ps_formula = "S ~ x1 + x2 + x3 + x4 + x5",
outcome_formula = c(
"y1 ~ x1 + x2 + x3 + x4 + x5",
"y2 ~ x1 + x2 + x3 + x4 + x5 + y1"
),
bootstrap = 50,
bootstrap_ci_type = "perc"
)
method_IPW_zero_weight <- ec_ipw(
ps_formula = "S ~ x1 + x2 + x3 + x4 + x5",
weight = 0,
bootstrap = 50,
bootstrap_ci_type = "perc"
)
method_AIPW_zero_weight <- ec_aipw(
ps_formula = "S ~ x1 + x2 + x3 + x4 + x5",
outcome_formula = c(
"y1 ~ x1 + x2 + x3 + x4 + x5",
"y2 ~ x1 + x2 + x3 + x4 + x5 + y1"
),
weight = 0,
bootstrap = 50,
bootstrap_ci_type = "perc"
)
method_obj_list <- list(
method_IPW_optimal_weight,
method_AIPW_optimal_weight,
method_IPW_zero_weight,
method_AIPW_zero_weight
)
# create a simulation object for primary analysis
simulation_primary_obj <- setup_simulation_primary(
data_matrix_list_null = data_matrix_list_null,
data_matrix_list_alt = data_matrix_list_alt,
trial_status_col_name = trial_status_col_name,
treatment_col_name = treatment_col_name,
outcome_col_name = outcome_col_name,
covariates_col_name = covariates_col_name,
method_obj_list = method_obj_list,
true_effect = true_effect,
alt_effect = alt_effect,
alpha = alpha,
method_description = c(
"IPW, optimal weight, bootstrap",
"AIPW, optimal weight, bootstrap",
"IPW, zero weight, bootstrap",
"AIPW, zero weight, bootstrap"
)
)
simulation_report_bs <- run_simulation(simulation_primary_obj, quiet = TRUE)
simulation_report_bs
#> method_description bias variance mse coverage
#> 1 IPW, optimal weight, bootstrap -0.0541718304 0.4845047 0.4874393 0.944
#> 2 AIPW, optimal weight, bootstrap 0.0032679422 0.3159685 0.3159792 0.952
#> 3 IPW, zero weight, bootstrap -0.0007803934 0.5317429 0.5317435 0.954
#> 4 AIPW, zero weight, bootstrap 0.0014500246 0.3367785 0.3367806 0.944
#> type_I_error power
#> 1 0.056 0.750
#> 2 0.048 0.910
#> 3 0.046 0.722
#> 4 0.056 0.890References
- Zhou X, Zhu J, Drake C, Pang H (2024). “Causal estimators for incorporating external controls in randomized trials with longitudinal outcomes.” Journal of the Royal Statistical Society Series A: Statistics in Society. doi: 10.1093/jrsssa/qnae075.
- Shi L, Pang H, Chen C, Zhu J (2025). “rdborrow: an R package for causal inference incorporating external controls in randomized controlled trials with longitudinal outcomes.” Journal of Biopharmaceutical Statistics, 35(6), 1043-1066. doi: 10.1080/10543406.2025.2489283.