Primary analysis
This vignette demonstrates the primary analysis workflow using the EC-IPW and EC-AIPW weighting estimators proposed in Zhou et al. (2024) for incorporating external controls in randomized trials with longitudinal outcomes.
1 Load data
## x1 x2 x3 x4 x5 A S T_cross y1 y2 y3 y4
## 1 1 1 1 9 54.59836 1 1 2 3.4512377 -0.7642287 -2.4713591 3.935466
## 2 0 1 0 8 33.08006 1 1 2 0.4518106 6.3516296 4.5231869 -0.198674
## 3 1 1 1 7 48.51653 0 1 2 3.0532714 -2.0453190 5.9064870 -1.374919
## 4 1 1 1 15 31.68766 1 1 2 -9.1183948 0.2304339 4.7858172 8.490757
## 5 1 1 1 12 29.98495 0 1 2 -1.4270057 1.5878794 3.7006101 9.449632
## 6 1 1 0 7 46.08991 0 1 2 -2.6967072 -0.6130288 0.7482786 -2.413717
2 EC-IPW
2.1 No borrowing (weight = 0)
method <- ec_ipw(
ps_formula = "S ~ x1 + x2 + x3 + x4 + x5",
weight = 0
)
analysis <- setup_analysis_primary(
data = SyntheticData,
trial_status_col_name = "S",
treatment_col_name = "A",
outcome_col_name = c("y1", "y2"),
covariates_col_name = c("x1", "x2", "x3", "x4", "x5"),
method_weighting_obj = method
)
run_analysis(analysis)## $results
## point_estimates standard_deviation lower_CI_normal upper_CI_normal
## tau1 -0.02808704 0.5367987 -1.0801931 1.024019
## tau2 0.40959558 0.5625763 -0.6930338 1.512225
##
## $borrow_weight
## [1] 0
2.2 Optimal weight (data-adaptive)
method <- ec_ipw(ps_formula = "S ~ x1 + x2 + x3 + x4 + x5")
analysis <- setup_analysis_primary(
data = SyntheticData,
trial_status_col_name = "S",
treatment_col_name = "A",
outcome_col_name = c("y1", "y2"),
covariates_col_name = c("x1", "x2", "x3", "x4", "x5"),
method_weighting_obj = method
)
run_analysis(analysis)## $results
## point_estimates standard_deviation lower_CI_normal upper_CI_normal
## tau1 -0.1971969 0.5134018 -1.203446 0.809052
## tau2 0.4697209 0.5410007 -0.590621 1.530063
##
## $borrow_weight
## [1] 0.1475196
2.3 Bootstrap inference
method <- ec_ipw(
ps_formula = "S ~ x1 + x2 + x3 + x4 + x5",
bootstrap = 50,
bootstrap_ci_type = "perc"
)
analysis <- setup_analysis_primary(
data = SyntheticData,
trial_status_col_name = "S",
treatment_col_name = "A",
outcome_col_name = c("y1", "y2"),
covariates_col_name = c("x1", "x2", "x3", "x4", "x5"),
method_weighting_obj = method
)
run_analysis(analysis)## $results
## point_estimates standard_deviation lower_CI_boot upper_CI_boot
## tau1 -0.1971969 0.5989789 -1.4378865 1.296664
## tau2 0.4697209 0.5701665 -0.5582876 1.597238
##
## $borrow_weight
## [1] 0.1475196
3 EC-AIPW
EC-AIPW augments the IPW estimator with an outcome regression model, making it doubly robust: consistent if either the propensity score model or the outcome model is correctly specified.
3.1 No borrowing (weight = 0)
method <- 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
)
analysis <- setup_analysis_primary(
data = SyntheticData,
trial_status_col_name = "S",
treatment_col_name = "A",
outcome_col_name = c("y1", "y2"),
covariates_col_name = c("x1", "x2", "x3", "x4", "x5"),
method_weighting_obj = method
)
run_analysis(analysis)## $results
## point_estimates standard_deviation lower_CI_normal upper_CI_normal
## tau1 -0.4361151 0.5552065 -1.5242998 0.6520696
## tau2 0.4422248 0.5701633 -0.6752748 1.5597244
##
## $borrow_weight
## [1] 0
3.2 Optimal weight (data-adaptive)
method <- 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"
)
)
analysis <- setup_analysis_primary(
data = SyntheticData,
trial_status_col_name = "S",
treatment_col_name = "A",
outcome_col_name = c("y1", "y2"),
covariates_col_name = c("x1", "x2", "x3", "x4", "x5"),
method_weighting_obj = method
)
run_analysis(analysis)## $results
## point_estimates standard_deviation lower_CI_normal upper_CI_normal
## tau1 -0.5463256 0.5305614 -1.586207 0.4935556
## tau2 0.5401750 0.5543275 -0.546287 1.6266369
##
## $borrow_weight
## [1] 0.1475196
3.3 Bootstrap inference
method <- 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"
),
bootstrap = 50,
bootstrap_ci_type = "perc"
)
analysis <- setup_analysis_primary(
data = SyntheticData,
trial_status_col_name = "S",
treatment_col_name = "A",
outcome_col_name = c("y1", "y2"),
covariates_col_name = c("x1", "x2", "x3", "x4", "x5"),
method_weighting_obj = method
)
run_analysis(analysis)## $results
## point_estimates standard_deviation lower_CI_boot upper_CI_boot
## tau1 -0.5463256 0.6225099 -1.9966744 1.078554
## tau2 0.5401750 0.5402187 -0.4664991 1.614346
##
## $borrow_weight
## [1] 0.1475196
4 Notes
- When there are missing values in the data, preprocess the dataset (deletion, imputation, etc.) to obtain a complete dataset before applying the package.