Dahabreh 2020 - Simulation Study of Estimators

Summary

A 36-scenario proof-of-concept simulation (100,000 runs each) with correctly specified parametric models. All adjusted estimators are near-unbiased; the trial-only estimator is biased by 0.66-0.89 under strong selection on an effect modifier; OM has the smallest variance, DR estimators are close, and IOW (especially unnormalized) is far noisier.

Overview

Purpose: examine finite-sample bias and variance of eqs. (1)-(6) for potential-outcome means and treatment effects in the target, in nested trial designs with continuous outcomes. Binary-outcome and non-nested results are in the Appendix (not in the PDF).

Main Content

Data generation (Sec. 6.1)

Factorial design: 3 trial sizes × 3 cohort sizes × 2 effect-modification magnitudes × 2 selection magnitudes = 36 scenarios.

  • Cohort ; trial size .
  • , independent.
  • Selection: , , solved numerically so that hits its target; (none/strong selection on ); .
  • Potential outcomes , ; with , . So means effect modification by on the mean-difference scale.
  • Treatment: among (marginally randomized). .
  • Estimators applied: eqs. (1)-(6) plus trial-only. All working models correctly specified: outcome models with main effects, fit separately by arm; logistic participation and treatment models with main effects.

Results (strong selection , strong effect modification, )

Table 2 - bias of target-ATE estimators

TrialIOW1IOW2OMDR1DR2DR3
20020000.76560.00180.05930.00000.00000.00030.0006
20050000.84010.00800.0710-0.00070.0002-0.00020.0000
200100000.88550.00290.0753-0.0002-0.0019-0.0015-0.0012
50020000.68920.00360.02350.00010.00160.00130.0013
50050000.7654-0.00030.0306-0.00010.00040.0002-0.0004
500100000.82330.00330.0339-0.0012-0.0023-0.0021-0.0020
100020000.6576-0.00040.00810.0000-0.0004-0.0004-0.0003
100050000.70610.00330.0157-0.0003-0.0009-0.0009-0.0005
1000100000.7653-0.00100.01600.00020.00020.00020.0002

Trial = trial-only unadjusted; OM = outcome model; IOW1/IOW2 = unnormalized/normalized inverse-odds weighting; DR1/DR2/DR3 = doubly robust (unnormalized weights / normalized weights / weighted regression).

Table 3 - variance of target-ATE estimators

TrialIOW1IOW2OMDR1DR2DR3
20020000.08434.45071.12560.07620.25620.15010.1582
20050000.09056.96501.27650.08190.33530.16690.1791
200100000.09396.12451.35390.08410.33210.17530.1921
50020000.03241.19010.52780.02680.08080.06100.0558
50050000.03361.58040.67600.02940.10590.07180.0662
500100000.03511.45930.75050.03100.11130.07830.0727
100020000.01660.45800.24560.01270.03330.02900.0258
100050000.01620.60610.35580.01370.04230.03460.0305
1000100000.01680.69640.42910.01460.05030.03990.0352
^tbl-sim-variance

Interpretation

  1. Bias. All estimators except Trial are essentially unbiased, with one exception: IOW2 shows small positive finite-sample bias (0.008 to 0.075), largest when the trial is small relative to the cohort. This is the usual ratio-estimator bias, traded against its massive variance reduction vs IOW1 (e.g., 1.13 vs 4.45 at 200/2000).
  2. Variance. OM lowest; DR2/DR3 roughly 2x the variance of OM (1.97x at 200/2000, 2.3x at 1000/2000); DR1 (unnormalized) worse; IOW1 an order of magnitude worse than OM. Variance falls with and, for the weighted estimators, grows mildly with cohort size (more extreme weights as the target grows relative to the trial).
  3. Trial-only. Biased for whenever selection depends on the effect modifier, but unbiased for . Its variance is low — precision about the wrong estimand.
  4. Normalization. With strong selection and a trial much smaller than the target, normalized weights (IOW2, DR2, DR3) beat unnormalized (IOW1, DR1). The authors “recommend avoiding weighted estimators that do not use normalized weights”.
  5. Double robustness is visible even though no model was misspecified (see special-case note in Dahabreh 2020 - Outcome Model, Inverse Odds Weighting and Doubly Robust Estimators).

Code

The paper’s Appendix provides R functions (one per estimator), a geex sandwich-variance implementation and Stata code to reproduce the study; these are not in the PDF.

Examples

Independent mini-replication (Python)

A 300-replication run of one cell (, , , , known , estimand = finite-cohort mean of among non-participants) gave bias/variance: Trial +0.764 / 0.035; OM +0.011 / 0.031; IOW1 +0.042 / 0.865; IOW2 +0.048 / 0.565; DR1 -0.005 / 0.074; DR2 -0.006 / 0.062; DR3 -0.004 / 0.062. The Trial row matches the paper’s 0.7654 for the same cell; the qualitative ordering of variances matches Table 3 (absolute values differ because of 300 vs 100,000 runs, known treatment probabilities, and a finite-sample target).

import numpy as np
from scipy.optimize import brentq
def logit_fit(X, s):
    Z = np.c_[np.ones(len(X)), X]; b = np.zeros(Z.shape[1])
    for _ in range(50):
        p = 1/(1+np.exp(-Z@b)); b += np.linalg.solve(Z.T@(Z*(p*(1-p))[:,None]), Z.T@(s-p))
    return 1/(1+np.exp(-Z@b))
def wls(Xtr, ytr, Xall, w=None):
    Z = np.c_[np.ones(len(Xtr)), Xtr]; w = np.ones(len(Xtr)) if w is None else w
    return np.c_[np.ones(len(Xall)), Xall] @ np.linalg.solve(Z.T@(Z*w[:,None]), Z.T@(w*ytr))
def one(rng, n=5000, nrct=500, b1=1.0, th11=2.0):
    X = rng.standard_normal((n,3)); Xd = np.c_[np.ones(n), X]
    b0 = brentq(lambda b: (1/(1+np.exp(-(Xd@np.r_[b,b1,1,1])))).sum()-nrct, -20, 5)
    S = rng.random(n) < 1/(1+np.exp(-(Xd@np.r_[b0,b1,1,1])))
    Y1 = Xd@np.array([1,th11,1,1]) + rng.standard_normal(n); Y0 = Xd@np.array([0,1,1,1]) + rng.standard_normal(n)
    A = rng.random(n) < .5; Y = np.where(A, Y1, Y0); truth = (Y1-Y0)[~S].mean()
    p = logit_fit(X, S.astype(float)); mu = {}
    for a in (0,1):
        sel = S & (A==a); g = wls(X[sel], Y[sel], X); w = np.where(sel, (1-p)/(p*.5), 0.)
        mu[a] = dict(OM=g[~S].mean(), IOW1=(w*Y).sum()/(~S).sum(), IOW2=(w*Y).sum()/w.sum(),
                     DR2=(w*(Y-g)).sum()/w.sum()+g[~S].mean(),
                     DR3=wls(X[sel], Y[sel], X, w[sel])[~S].mean())
    out = {k: mu[1][k]-mu[0][k]-truth for k in mu[1]}
    out["Trial"] = Y[S&A].mean()-Y[S&~A].mean()-truth
    return out
rng = np.random.default_rng(1); R = [one(rng) for _ in range(300)]
for k in R[0]: v = np.array([r[k] for r in R]); print(k, round(v.mean(),3), round(v.var(),3))

Connections

Takeaway for analysts: pick OM or a normalized DR estimator by default; keep the trial-only number for comparison; report both.

See Also