The question
Does statin use reduce all-cause mortality?
Statins are among the most widely prescribed drugs in the world, and randomized trials support a mortality benefit for many patient groups. But most real-world statin use is observational: clinicians decide who gets prescribed a statin based on perceived cardiovascular risk, not a coin flip. That is exactly the setup where confounding by indication can distort a naive comparison, in either direction.
Study variables
| Treatment | statin | reported taking a statin in the past month (yes/no) |
| Outcome | death | assumed deceased per the NCHS mortality linkage (through Dec 31, 2019) |
| Confounders | demographics + clinical measures | age, sex, race, poverty-income ratio, BMI, blood pressure, diabetes, smoking, total cholesterol |
Cohorts
- Real (NHANES analytic): 54,091 patients, 12 variables
- Synthetic (Aindo-generated): 54,091 patients, 12 variables
- NHANES 1999-2018, ten survey cycles, linked to the NCHS public-use mortality file (follow-up through Dec 31, 2019).
The data
How is the Aindo synthetic data generated?
Aindo generates synthetic patient records by learning the statistical and causal structure of a real, de-identified cohort, then sampling an entirely new synthetic cohort from what it learned: patients that never existed, with no one-to-one link back to a real person. This page loads the real NHANES analytic dataset side by side with a synthetic cohort Aindo generated from it.
1. Learn
A generative AI model is trained directly on the real, de-identified cohort. Because it learns the whole dataset jointly, not one column at a time, it captures not just each variable's own distribution, but how variables relate to one another (e.g. that statin use, age, blood pressure, and cholesterol move together). That joint structure is exactly the confounding structure a causal analysis like this one depends on.
2. Generate
Once training is done, the real data is set aside, and the model samples a brand-new synthetic cohort from what it learned: synthetic patients, not modified or resampled real ones, so no synthetic record traces back to a specific real person. This is Aindo's Synthesis mode, and it's what makes the output "void of personal information" while remaining statistically realistic, supporting GDPR-, EHDS-, and AI-Act-aligned data sharing.
3. Validate
Before a synthetic dataset ships, Aindo's platform reports a similarity score and a privacy score for the generation run, backed by univariate and bivariate analysis.
In code, the shape of it looks roughly like this (illustrative, not the actual Aindo API):
schema = {
"statin": "categorical",
"age": "numeric",
"sex": "categorical",
"total_cholesterol": "numeric",
# ... one entry per column, with its real data type
}
model = AindoSyntheticDataModel(schema)
# Learn
model.fit(real_cohort)
# Generate
synthetic_cohort = model.generate(n_samples=<number of samples requested>)Fidelity checks
Does the synthetic data look like the real data?
We perform three checks:
- Boxplot comparison for the continuous confounders, do individual distributions match?
- Prevalence comparison for the binary variables (
statin,death,sex,diabetes,smoker), same question, for variables a boxplot doesn't apply to. - Pairwise correlation agreement across every variable, including the categorical ones (
raceand the binary variables above). Do variables relate to each other the same way in both datasets? This is the one that actually matters for a causal analysis: two datasets can have identical marginals while differing completely in their confounding structure.
Continuous confounders: boxplot comparison
Similarly-shaped boxes (median, IQR, and whiskers) mean the real and synthetic distributions agree.
Age
Poverty-income ratio
BMI
Systolic BP
Diastolic BP
Total cholesterol
Binary variables: prevalence
A boxplot doesn't apply to a two-valued variable: comparing prevalence is the equivalent check.
statin 16.2% vs 16.6%, diabetes 12.2% vs 11.8%, smoker 45.3% vs 43.5%, sex (male) 48.0% vs 46.8%. death shows the largest gap, 15.8% vs 13.4%.Pairwise correlation agreement
Every pairwise correlation among treatment, outcome, and confounders (categoricals one-hot encoded), real vs. synthetic, 120 pairs in total.
Agreement
- Mean absolute difference
- 0.0105
- Worst-pair difference
- 0.0619
- Variable pairs compared
- 120
Step 1
The naive comparison
Now we proceed with the main causal question posed in the beginning: does statin use reduce all-cause mortality?
An unadjusted comparison of mortality rates between statin users and non-users.
crude difference = Pr(death | statin) − Pr(death | no statin)
Run on both datasets to compare the two directly.
Crude odds ratio
| Source | Odds ratio | 95% CI |
|---|---|---|
| Real | 2.428 | [2.300, 2.563] |
| Synthetic | 2.597 | [2.455, 2.748] |
Crude mortality rate difference
Why the naive estimate is wrong
Confounding by indication
Statins are not prescribed at random. Clinicians prescribe them to patients judged to be at higher cardiovascular risk. If statin users are systematically older and sicker, they have higher baseline mortality risk independent of the drug. The plot below shows the standardized mean difference (SMD) between statin users and non-users for each confounder, in the real data.
Dashed lines mark |SMD| = 0.1, the conventional imbalance threshold.
Step 2 · Outcome modeling
G-computation
The first technique used for dealing with these differences is G-computation. G-computation estimates an outcome model. This model learns the predictors of the outcome (death) and uses them to predict every participant's mortality risk in a counterfactual scenario where statin use is set to 1 and to 0 for everyone, then averages the difference. Here we use two different outcome models (a logistic regression and an XGBoost forest). Finally, we run the same analysis on both datasets and compare the results.
The confidence interval comes from a nonparametric bootstrap: we resample the dataset with replacement (same size as the original) 500 times, refit the outcome model from scratch on each resample, and take the 2.5th and 97.5th percentile of the resulting 500 estimates as the interval. The point estimate itself is not an average over these resamples. It is computed once, by fitting the model on the full original dataset; the bootstrap is only used to quantify the uncertainty around it.
Estimated treatment effect (risk difference)
Point estimates & 95% CI
| Model | Source | ATE | 95% CI |
|---|---|---|---|
| Logistic regression | Real | -0.0365 | [-0.0422, -0.0317] |
| Logistic regression | Synthetic | -0.0340 | [-0.0386, -0.0274] |
| XGBoost | Real | -0.0132 | [-0.0169, -0.0070] |
| XGBoost | Synthetic | -0.0148 | [-0.0187, -0.0060] |
Step 3 · Propensity weighting
Inverse Probability of Treatment Weighting
Another approach is to model the treatment: the rationale is to learn the patterns that determine treatment assignment, then weight each individual by their probability of receiving the treatment they actually got. IPTW reweights each participant by the inverse probability of the statin use they actually received, so that in the reweighted pseudo-population, statin use no longer depends on the confounders. We then compare weighted mortality means between arms. As with G-computation, the confidence interval is a nonparametric bootstrap of 500 resamples of the dataset.
Estimated treatment effect (risk difference)
Point estimates & 95% CI
| Model | Source | ATE | 95% CI |
|---|---|---|---|
| Logistic regression | Real | 0.0109 | [0.0023, 0.0197] |
| Logistic regression | Synthetic | 0.0050 | [-0.0027, 0.0151] |
| XGBoost | Real | 0.0547 | [0.0469, 0.0647] |
| XGBoost | Synthetic | 0.0497 | [0.0437, 0.0632] |
Does weighting actually balance the groups?
As a direct check (weighting should make statin users and non-users look statistically alike on the measured confounders), we redo the SMD check on the real and synthetic data, weighted by the (stabilized) IPTW weight.
Real: unweighted vs. weighted
Synthetic: unweighted vs. weighted
Step 4 · Doubly robust
Targeted Maximum Likelihood Estimation
TMLE combines G-computation and IPTW into a single doubly-robust estimate. It starts from the same two ingredients used above, an outcome model that predicts mortality risk and a propensity model that predicts treatment assignment, and adds a "targeting" step: a small, one-parameter adjustment to the outcome model's predictions, fit using the propensity scores, that nudges the plain G-computation estimate just enough to solve for the ATE directly. The result is doubly robust, meaning it is consistent if either the outcome model or the propensity model is correctly specified, so the estimate does not have to bet entirely on one nuisance model the way G-computation and IPTW each do on their own.
Unlike G-computation and IPTW, TMLE's confidence interval is not a bootstrap. The targeting step comes with a closed-form standard error derived from its efficient influence curve, computed directly from the fitted models on the full dataset, no resampling needed.
Estimated treatment effect (risk difference)
Point estimates & 95% CI
| Model | Source | ATE | 95% CI |
|---|---|---|---|
| Logistic regression | Real | -0.0271 | [-0.0373, -0.0169] |
| Logistic regression | Synthetic | -0.0306 | [-0.0393, -0.0220] |
| XGBoost | Real | -0.0187 | [-0.0255, -0.0120] |
| XGBoost | Synthetic | -0.0207 | [-0.0269, -0.0146] |
Putting it together
Naive vs. causally-adjusted estimates, real vs. synthetic
The naive/crude estimate points one direction; every causally-adjusted method points the other. The synthetic data's results match the real data's at every step.
A further use
Aindo's model as a predictor, not just a generator
Everything above used classical ML (logistic regression, XGBoost) as the outcome and propensity models. As a further demonstration, separate from the real-vs-synthetic comparison above, the same deep model architecture behind Aindo's synthetic data generation can also be trained as a plain predictive model: not to generate data, but to predict it.
Here we take a model trained by Aindo directly on the real cohort (no synthetic data involved in this section) and use it as the outcome model for a G-computation-style ATE and, paired with a logistic-regression propensity model, a TMLE estimate.
Outcome model AUC, predicting death (real data)
| Outcome model | AUC |
|---|---|
| Logistic regression | 0.8751 |
| XGBoost | 0.8890 |
| Aindo model | 0.9100 |
ATE, XGBoost vs. Aindo model as the outcome model (real data)
| Method | Outcome model | ATE | 95% CI |
|---|---|---|---|
| G-computation | XGBoost | -0.0132 | [-0.0169, -0.0070] |
| G-computation | Aindo model | -0.0118 | [-0.0120, -0.0116] |
| TMLE | XGBoost | -0.0187 | [-0.0255, -0.0120] |
| TMLE | Aindo model | -0.0124 | [-0.0184, -0.0064] |
It also outperforms both classical outcome models on plain predictive performance: at discriminating who actually died, Aindo's model reaches an AUC of 0.91, ahead of XGBoost's 0.89 and logistic regression's 0.88. Aindo's modeling technology, in other words, isn't only useful for generating a realistic synthetic cohort: the same underlying model is a stronger nuisance model for the causal estimate than the classical alternatives used elsewhere in this analysis.
Note: this section uses only the real data.
Takeaway
Aindo's synthetic cohort reproduces the same causal conclusion
Takehome message: Aindo's synthetic cohort reproduces the same causal conclusion as the real data, at every stage of a full observational RWE pipeline, not just in its summary statistics.
- Before any modeling, the synthetic data already matched the real data on individual variable distributions, binary prevalences, and the pairwise correlation structure across all confounders (the harder property to fake, and the one a causal analysis actually depends on).
- The naive comparison was confounded by indication (higher-risk patients were preferentially prescribed statins) and pointed the wrong way (on both real and synthetic data: crude mortality rate 0.14 real vs. 0.13 synthetic). A real-world-evidence analysis has to correct for this; a naive synthetic-data check would not have caught it.
- G-computation and TMLE corrected for the measured confounders and reversed that conclusion, in close agreement between the two datasets at every step (e.g. TMLE: -0.027 real vs. -0.031 synthetic for logistic regression, -0.019 vs. -0.021 for XGBoost). TMLE's doubly-robust estimate is the one we would report, and it lands in the same place whether it's computed on real patients or on Aindo's synthetic cohort. In all cases, point estimates from the synthetic data fall within the confidence intervals of the real data, and vice versa.
Put together, this is more than "the synthetic data looks similar"; it shows Aindo's synthetic data preserves the underlying causal mechanism, including the exact confounding-by-indication pattern this dataset was chosen to test. That is what makes it a credible substitute for the real patient data in this kind of analysis: an external collaborator, reviewer, or regulator could run this entire causal-inference workflow on the synthetic cohort alone, never touching an identifiable patient record, and reach the conclusion the real data supports, preserving both patient privacy and the validity of the inference.