Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GeoLift

Project Status: Active License: MIT

GeoLift is a Python package for geo-level marketing incrementality measurement using Augmented Synthetic Control Methods (ASCM). It is a Python port of the R GeoLift package, covering the same end-to-end workflow with the same API surface:

  • Data ingestion — flexible date parsing, time-index creation
  • Pre-test market selection — correlation and DTW-based market ranking, power analysis
  • Post-test inference — synthetic control fitting, ATT estimation, conformal p-values and confidence intervals
  • Multi-cell experiments — multiple simultaneous treatment arms (experimental)
  • Visualization — pre- and post-test plots

Algorithmic note: Deterministic quantities (average ATT, L2 imbalance, synthetic control weights) match the R package to within numerical precision. Stochastic inference uses a different method — see Known differences below.


When to use this

  • You want to run GeoLift analyses in a Python environment without switching to R.
  • You are building a data pipeline or ML platform in Python and need programmatic access to geo-lift inference.
  • You want to reproduce or audit R GeoLift results in Python and understand where the two implementations agree and where they intentionally differ.

This package is not a drop-in replacement for R GeoLift when exact p-value or CI parity is required — the inference algorithms differ by design.


Installation

Standard install (from source)

pip install .

Developer install (editable, with test and lint tools)

pip install -e ".[dev]"

Requires Python ≥ 3.9.


Input data format

All functions expect a pandas.DataFrame with at minimum these three columns:

Column Type Description
location str Geo unit name (lowercased internally)
time int Integer time index starting at 1
Y float Outcome variable

Use geo_data_read() to convert raw data with date columns into this canonical format.


Quickstart

Post-test inference

import pandas as pd
from geolift import geo_lift

df = pd.read_csv("tests/fixtures/small_single_cell.csv")

result = geo_lift(
    data=df,
    treatment_locations=["chicago", "portland"],
    treatment_start_time=36,
    treatment_end_time=45,
    model="none",        # or "ridge" or "best"
    random_state=42,     # set for reproducible p-values / CI
)

print(result)
# GeoLift Output
# Test results for 10 treatment period(s), from time-stamp 36 to 45
# Test markets: CHICAGO, PORTLAND
# Average ATT: -50.531
# P-value: 0.65
# 90% CI: (-296.4, 195.4)
# L2 Imbalance: 595.6240
# Scaled L2 Imbalance: 0.6424

Pre-test market selection

from geolift import geo_lift_market_selection

pretest_df = pd.read_csv("tests/fixtures/small_pretest.csv")

selection = geo_lift_market_selection(
    data=pretest_df,
    treatment_periods=[5],
    N=[2],
    effect_size=[0, 0.05, 0.10, 0.15, 0.20],
    alpha=0.1,
    random_state=42,
)

print(selection)

Power analysis for a specific market

from geolift import geo_lift_power

power_df = geo_lift_power(
    data=pretest_df,
    treatment_locations=["chicago", "portland"],
    treatment_start_time=41,
    treatment_end_time=45,
    effect_size=[0, 0.05, 0.10, 0.15, 0.20],
    random_state=42,
)

print(power_df[["effect_size", "power", "scaled_l2_imbalance"]])

Supported functions

Function Description
geo_data_read() Ingest raw data, normalize dates, create time index
trim_controls() Reduce control pool via stratified sampling
geo_lift() Post-test inference — ATT, p-value, CI
geo_lift_power() Power analysis for a given market and treatment period
geo_lift_market_selection() Rank candidate markets by power and fit quality
geo_lift_multi_cell() Multi-cell post-test inference (experimental)
multi_cell_market_selection() Multi-cell market selection (experimental)
multi_cell_power() Multi-cell power analysis (experimental)

Full parameter documentation: docs/api_reference.md.


Known differences from the R implementation

On fixed small-sample fixtures, deterministic quantities match the R baseline to within numerical precision: average ATT, L2 imbalance, scaled L2 imbalance, synthetic control weights, and incremental lift.

Stochastic inference uses a different algorithm. R GeoLift uses time-shift placebo tests — it randomly selects pre-treatment windows and re-runs the full model on each to build a null distribution. Python GeoLift uses conformal inference — it fits the model once and permutes the fitted residuals. These are structurally different methods; p-values and confidence intervals will differ between the two implementations regardless of random seed. This is expected and documented behaviour, not a bug.

For a detailed comparison including per-fixture numeric tables, see docs/r_python_differences.md.

Known unimplemented features

Feature Status
model="gsyn" (Generalized Synthetic Control) Raises NotImplementedError — planned for a future release

Testing

# Run the full test suite
pytest

# Run with coverage
pytest --cov=geolift

# Run only R parity regression tests (no R installation needed)
pytest tests/test_r_parity.py

# Run only reproducibility tests
pytest tests/test_reproducibility.py

CI is configured via .github/workflows/tests.yml and runs on Python 3.10, 3.11, and 3.12.

R comparison baseline

For parity checks against an externally installed R GeoLift package:

Rscript tests/r_example_baseline.R
python tests/small_numeric_python_compare.py

Both scripts use the fixture CSVs in tests/vignette_outputs/ and write JSON outputs for comparison. Interactive versions are in examples/.


License

GeoLift is MIT licensed, as found in the LICENSE.md file.

This Python package is a port of the R GeoLift package developed by Meta Platforms, Inc. and its affiliates.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages