Causal Inference Library for Lift Measurement
Project description
RealLift
Causal Inference Framework for Geo Experiments & Marketing Science
RealLift is a Python library for measuring the true incremental impact of marketing interventions through Synthetic Control, Convex Optimization, and robust significance testing — designed for markets where individual-level tracking is unavailable.
Framework Pillars
Four layers of defense against noise and spurious correlations:
- Data Quality (
clean) — Missing value imputation, zero-rate filtering, and geo-level quality scoring. - Auditable Planning (
design) — Algorithmically selects optimal treatment/control clusters and projects statistical power (MDE) before any spend. - Causal Inference (
run) — Builds counterfactuals via Convex Optimization with Intercept Adjustment, ensuring behavioral alignment across differing baseline levels. - Confidence Validation — Moving Block Bootstrap (MBB) + Placebo/Permutation tests with visual and statistical evidence.
Installation
pip install reallift
Quick Start
The API is object-oriented. Instantiate a GeoExperiment via the RealLift namespace — it holds the data in memory across all pipeline steps.
1. Initialize
from reallift import RealLift
# Accepts a CSV path or a pandas DataFrame
rl = RealLift.GeoExperiment(
"geo_daily_sales.csv",
date_col="date",
start_date="2025-01-01", # optional: window the analysis period
end_date="2025-04-30",
)
2. Clean
df_clean = rl.clean(
imputation_method="constant", # "constant" or "interpolation"
max_zero_rate=0.0, # drop geos with any zero-revenue days
keep_top_quantiles=1, # keep only top revenue quantile
quantile_bins=40,
save_pdf=True,
pdf_name="DataQualityReport.pdf",
)
3. Design (Pre-Test Phase)
doe = rl.design(
pct_treatment=[0.05, 0.10, 0.15], # treatment pool sizes to evaluate
experiment_days=[21, 28, 35], # durations to evaluate
check_ghost_lift=True, # OOS backtest for spurious effects
save_pdf=True,
pdf_name="DoEReport.pdf",
)
# Visual diagnostics
doe.plot_cluster_fits(scenario=0) # pre-period synthetic control fit per cluster
doe.plot_consolidated_fit(scenario=0) # aggregated control group fit
doe.plot_power_analysis() # MDE curves vs. experiment duration
4. Run (Post-Test Phase)
Option A — Backtest on historical data (validate the design before the campaign):
results = rl.run(
perform_backtesting={"lift": 0.0, "days": 28}, # placebo: inject 0% lift
doe=doe,
scenario=0,
)
Option B — Real campaign analysis (after the campaign ends, load data that includes the treatment period):
rl_post = RealLift.GeoExperiment("geo_daily_sales_with_campaign.csv", date_col="date")
rl_post.clean()
results = rl_post.run(
treatment_start_date="2025-04-01",
treatment_end_date="2025-04-28",
doe=doe,
scenario=0,
)
5. Visualize Results
results.plot_cluster_effects(post_only=False) # treatment vs. synthetic per cluster
results.plot_consolidated_effect(post_only=False) # aggregated causal impact
results.plot_lift_distributions(show_null=True) # bootstrap CI + hypothesis test
Hands-on example:
examples/GeoExperiment/GeoExperiment-Quickstart.ipynb— full pipeline with synthetic data, no setup required.
Key Algorithms
| Algorithm | Role |
|---|---|
| Convex Intercept | Absorbs baseline shift between treated and synthetic while preserving Σw = 1 |
| Synchronization Error Ratio (SER) | Pre-experiment geo ranking and volatility scoring |
| ElasticNet Pool Purification | Removes weak/spurious controls before convex optimization |
| Moving Block Bootstrap (MBB) | Respects temporal autocorrelation (~7-day blocks) for conservative CIs |
| OOS Ghost Lift Detection | Weekly-aligned backtest that flags spurious effects in the experiment design |
| Placebo / MSPE Ratio | Permutation-based empirical p-values robust to noisy markets |
Dependencies
- Optimization:
cvxpy,scipy,numpy - Data:
pandas,scikit-learn - Visualization:
matplotlib
Developed by Roberto Junior.
Citation
If you use RealLift in your research or applied work, please cite:
@misc{junior2026reallift,
author = {Junior, Roberto},
title = {RealLift: Robust Design and Inference for Geo-Experimentation},
year = {2026},
doi = {10.5281/zenodo.20329451},
url = {https://doi.org/10.5281/zenodo.20329451},
note = {Preprint}
}
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file reallift-0.7.1.tar.gz.
File metadata
- Download URL: reallift-0.7.1.tar.gz
- Upload date:
- Size: 1.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
83e73fb48c5069e6a9746974efeaeb9cefe48f12fd2a65011f2022c4085bd8de
|
|
| MD5 |
70021286eaee2bb03fbb346544bda454
|
|
| BLAKE2b-256 |
065e85f2ee0cb094872bbd64d4343a59f8d20200e30633f9a5e3e455a8d4f007
|
Provenance
The following attestation bundles were made for reallift-0.7.1.tar.gz:
Publisher:
publish.yml on RobertoJuniorWXYZ/RealLift
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
reallift-0.7.1.tar.gz -
Subject digest:
83e73fb48c5069e6a9746974efeaeb9cefe48f12fd2a65011f2022c4085bd8de - Sigstore transparency entry: 1593083151
- Sigstore integration time:
-
Permalink:
RobertoJuniorWXYZ/RealLift@1f3785dcf6934d739fb7fa85a413371e6ef18595 -
Branch / Tag:
refs/tags/v0.7.1 - Owner: https://github.com/RobertoJuniorWXYZ
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1f3785dcf6934d739fb7fa85a413371e6ef18595 -
Trigger Event:
push
-
Statement type:
File details
Details for the file reallift-0.7.1-py3-none-any.whl.
File metadata
- Download URL: reallift-0.7.1-py3-none-any.whl
- Upload date:
- Size: 84.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96d075570a353ec85adf88f8d11e6b979625a24dafcf5134337717b7a2914930
|
|
| MD5 |
43d4efa703ee046d64e98a32260f32ae
|
|
| BLAKE2b-256 |
4d410fbf9554c216f4aa3c7a1c65aa0991dc03077a63824f875ffe74fb329132
|
Provenance
The following attestation bundles were made for reallift-0.7.1-py3-none-any.whl:
Publisher:
publish.yml on RobertoJuniorWXYZ/RealLift
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
reallift-0.7.1-py3-none-any.whl -
Subject digest:
96d075570a353ec85adf88f8d11e6b979625a24dafcf5134337717b7a2914930 - Sigstore transparency entry: 1593083245
- Sigstore integration time:
-
Permalink:
RobertoJuniorWXYZ/RealLift@1f3785dcf6934d739fb7fa85a413371e6ef18595 -
Branch / Tag:
refs/tags/v0.7.1 - Owner: https://github.com/RobertoJuniorWXYZ
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1f3785dcf6934d739fb7fa85a413371e6ef18595 -
Trigger Event:
push
-
Statement type: