Randomized Controlled Trials — Design and Analysis
Statistics
The Gold Standard for Establishing Causation
RCTs eliminate confounding through random assignment, ensuring treatment groups are comparable in expectation. Proper design — blinding, power analysis, intention-to-treat — maximizes the credibility of causal conclusions.
-
Drug Development — Establish pharmaceutical efficacy for regulatory approval
-
Technology — Test feature impact through A/B testing on user populations
-
Education — Evaluate curriculum changes with randomized classroom assignments
Randomization is the great equalizer — it balances known and unknown confounders simultaneously.
A randomized controlled trial (RCT) is the gold standard for establishing causal relationships because randomization ensures that treatment and control groups are comparable in expectation.
Key Components of an RCT
| Component | Description |
|-----------|------------|
| Randomization | Random assignment to treatment/control |
| Control group | Receives placebo or standard treatment |
| Blinding | Participants/researchers unaware of assignment |
| Sample size | Determined by power analysis |
| Pre-registration | Specify analysis plan before data collection |
Why Randomization Works
Treatment Effects in RCTs
With randomization, the naive comparison identifies the ATE.
Sample Size and Power
Types of Analysis
Intention-to-Treat (ITT)
| Advantage | Disadvantage |
|-----------|-------------|
| Preserves randomization | May underestimate effect |
| Handles non-compliance | Diluted by non-adherence |
| Clinically relevant | |
Per-Protocol Analysis
Analyze only participants who fully complied with the protocol. May introduce bias if non-compliance is related to outcomes.
Blinding
| Type | Who is blinded | Purpose |
|------|---------------|---------|
| Single-blind | Participants | Reduces placebo effect |
| Double-blind | Participants + researchers | Reduces observer bias |
| Triple-blind | Participants + researchers + analysts | Reduces analysis bias |
Common Pitfalls
CONSORT Flow
A well-reported RCT follows the CONSORT guidelines:
-
Enrollment: How many were assessed and randomized?
-
Allocation: How many assigned to each group?
-
Follow-up: How many lost to follow-up?
-
Analysis: How many included in final analysis?
Python Implementation
import numpy as np
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt
np.random.seed(42)
# Simulate RCT
n = 500
X1 = np.random.randn(n) # Age
X2 = np.random.binomial(1, 0.5, n) # Gender
# Randomization
T = np.random.binomial(1, 0.5, n)
# Outcome (true ATE = 3.0)
Y0 = 50 + 0.5*X1 + 2*X2 + np.random.randn(n)*10
Y1 = Y0 + 3.0
Y = T * Y1 + (1 - T) * Y0
df = pd.DataFrame({'Y': Y, 'T': T, 'age': X1, 'gender': X2})
# Check balance (should be balanced due to randomization)
treat = df[df['T']==1]
control = df[df['T']==0]
print("Balance check:")
print(f"Age: treat={treat['age'].mean():.2f}, control={control['age'].mean():.2f}")
print(f"Gender: treat={treat['gender'].mean():.2f}, control={control['gender'].mean():.2f}")
# Two-sample t-test
t_stat, p_val = stats.ttest_ind(treat['Y'], control['Y'])
print(f"\nTreatment effect: {treat['Y'].mean() - control['Y'].mean():.2f}")
print(f"95% CI: [{treat['Y'].mean()-control['Y'].mean()-1.96*10*np.sqrt(2/n):.2f}, "
f"{treat['Y'].mean()-control['Y'].mean()+1.96*10*np.sqrt(2/n):.2f}]")
print(f"p-value: {p_val:.4f}")
# Power analysis
from statsmodels.stats.power import TTestIndPower
power_analysis = TTestIndPower()
power = power_analysis.power(effect_size=3.0/10, nobs1=250, ratio=1.0, alpha=0.05)
print(f"\nPower: {power:.3f}")
Worked Example
Key Takeaways
Related Topics
-
See Causal Inference for the potential outcomes framework
-
See Propensity Score Matching for when randomization is not possible
-
See Hypothesis Testing for p-values and significance