Skip to main content

Causalis

PyPI version PyPI Downloads Python License: MIT Code quality Docs

Causalis logo

Robust causal inference for experiments and observational studies in Python, organized around scenarios (e.g., Classic RCT, CUPED, Unconfoundedness) with a consistent fit() → estimate() workflow.

Why Causalis?

Causalis focuses on:

  • Scenario-first workflows (you pick the study design; Causalis provides best-practice defaults).
  • Extensive robustness tests that reveal issues in the study design or model specification
  • Pydantic data contracts
  • An advanced DGP (Data Generating Process) with heterogeneous treatment effects, latent variables, and correlated confounders
  • A website with notebooks based on real-world cases

Installation

Recommended

pip install causalis

Quickstart: Classic RCT (difference in means + inference)

from causalis.dgp import generate_classic_rct_26
from causalis.scenarios.classic_rct import DiffInMeans, check_srm

# Synthetic RCT data as a validated CausalData object
data = generate_classic_rct_26(seed=42, return_causal_data=True)

# Optional: Sample Ratio Mismatch check
srm = check_srm(data, target_allocation={0: 0.5, 1: 0.5}, alpha=1e-3)
print("SRM detected?", srm.is_srm, "p=", srm.p_value, "chi2=", srm.chi2)

# Estimate treatment effect with t-test inference (or bootstrap / conversion_ztest)
result = DiffInMeans().fit(data).estimate(method="ttest", alpha=0.05)
result.summary()

Quickstart: Observational study (Unconfoundedness / DML IRM)

from causalis.scenarios.unconfoundedness.dgp import generate_obs_hte_26
from causalis.scenarios.unconfoundedness import IRM
from causalis.data_contracts import CausalData

causaldata = generate_obs_hte_26(return_causal_data=True, include_oracle=False)

from causalis.scenarios.unconfoundedness import IRM

model = IRM().fit(causaldata)
result = model.estimate(score='ATTE')
result.summary()

Binary sensitivity protocol for observational DML/IRM

Pre-specify a practically meaningful effect boundary and one or more domain-justified groups of observed pre-treatment confounders. The primary decision uses element-based long/short gain statistics for the benchmark group. Its r2_y, r2_d, and rho are calibrated jointly from the outcome variance, Riesz-representer variance, and actual effect shift. The 2× strength and forced rho=1 scenarios are reported as secondary stress tests.

from causalis.scenarios.unconfoundedness.refutation import run_sensitivity_protocol

# Example only: replace with a domain-justified, pre-specified group.
primary_group = list(causaldata.confounders[:2])

protocol = run_sensitivity_protocol(
    model,
    causaldata,
    benchmark_groups={"primary_domain_benchmark": primary_group},
    decision_threshold=0.0,  # replace with the minimum practical effect
    direction="auto",  # default: infer direction relative to the threshold
    preconditions_passed=True,  # causal set, overlap, nuisance quality, stability
)

print(protocol["status"])
print(protocol["summary"])
protocol["primary"]
protocol["stress"]
protocol["adversarial"]

PASS means every primary benchmark's bias-aware confidence interval remains strictly beyond decision_threshold in the requested direction. RV and RVa are reported as robustness diagnostics, not compared with universal cutoffs. An empty benchmark set, failed external preconditions, unavailable sensitivity elements, or strengths outside the finite sensitivity domain produce FAIL.

By default, direction="auto" selects positive when the original estimate is at or above decision_threshold, and negative otherwise. It uses this same direction for every scenario and returns it in protocol["direction"], with an inference warning in protocol["warnings"]. For a negative estimate at a zero threshold, every primary CI must have ci_upper < 0; touching or crossing zero still fails. Thresholds retain their supplied sign, and an estimate equal to the threshold does not pass. Use explicit direction="positive" or direction="negative" for a pre-specified directional claim; these choices are never overridden. Significance before sensitivity analysis alone does not guarantee a pass.

Benchmark boundary handling matches DoubleML: raw cf_y and cf_d are clipped to [0, 1]. If either long/short gain is not strictly positive, primary and stress use rho=sign(theta_short-theta_long); the adversarial scenario still forces rho=1. protocol["benchmarks"] retains raw gains, clipping/fallback flags, long/short elements, and warnings for auditability. In particular, a negative cf_d_raw becomes a numerical cf_d=0 boundary benchmark rather than a missing scenario.

Pick your scenario

Scenario Estimator Assumptions
Classic RCT Difference in means (ttest, ztest, welch_permutation_t_test) Random assignment, no sample ratio mismatch, SUTVA
CUPED CUPED-adjusted difference in means with Lin specification Random assignment, no sample ratio mismatch, SUTVA, valid pre-period metrics
Unconfoundedness DML IRM Unconfoundedness, Overlap, SUTVA, No leakage, Score stability
GATE DML IRM (GATE and GATET) Same assumptions as unconfoundedness, plus meaningful pre-specified or validated subgroup definitions.
Multi Unconfoundedness Multi DML IRM Unconfoundedness, Multi class Overlap, SUTVA, No leakage, Score stability
Synthetic Control ASCM No interference / spillovers, No anticipation, The treated unit’s untreated outcome path is well approximated by the donor pool
Difference in Difference CallawaySantAnnaDID Parallel trends, no anticipation, stable group composition, no spillovers between treated and control groups.
IV DML IV First-stage strength, Reduced form, Instrument balance by Z, Instrument propensity / predictability
Uplift / CATE scoring DML IRM (CATE) Identified treatment effects from randomized or unconfounded data, overlap, calibrated individual-level predictions.

Introduction to Causal Inference: guide

See scenario notebooks: https://causalis.causalcraft.com/explore-scenarios

Contributing guidelines

Maintainers

Ioann Martynov

References

https://github.com/DoubleML/doubleml-for-py

Search terms / supported methods

Causalis covers methods often searched as:

  • causal inference Python
  • causal machine learning Python
  • treatment effect estimation
  • A/B testing Python
  • randomized controlled trial analysis
  • CUPED Python
  • Double Machine Learning Python
  • DML / IRM
  • CATE estimation
  • uplift modeling
  • propensity score diagnostics
  • synthetic control Python
  • difference-in-differences Python

Release files for causalis 1.0.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for causalis 1.0.7
File Size Uploaded
causalis-1.0.7.tar.gz 30.2 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for causalis 1.0.7
File Interpreter ABI Platform
causalis-1.0.7-py3-none-any.whl Python 3 none any Details

Total release size: 30.6 MB

Release files / causalis-1.0.7.tar.gz

Download URL causalis-1.0.7.tar.gz
Size 30.2 MB
Tags Source
SHA-256 checksum
How to use checksums
e04eb0c194ff6d517fa624061255c7436e0132c9ac5a71ae28affa48ce229a3e
BLAKE2b-256 checksum
How to use checksums
56cca9b2711e3105852440d7b875b41d3f15feacbc5e8b650de1d97f47c1f0aa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.

Transparency log

Release files / causalis-1.0.7-py3-none-any.whl

Download URL causalis-1.0.7-py3-none-any.whl
Size 455.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
349ee500a76f698b67ff473a40668085d06d7e35ceaebf0d48c61644f6921255
BLAKE2b-256 checksum
How to use checksums
0b3d9bc70e6bd1f75e465ce3ba94bd57656c5f1c659762de158adf2c05d4e929
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page