Skip to main content

scinference

A Python package for inference methods for synthetic control and related methods.

This is a Python port of the R scinference package by Victor Chernozhukov, Kaspar Wuthrich, and Yinchu Zhu.

Installation

pip install scinference

Validation Against R Package

All results in this README are generated using data from the original R package to demonstrate that Python and R produce identical results.


Example 1: Conformal Inference

Conformal inference works with a small number of post-treatment periods and provides valid p-values and confidence intervals.

Data

We use simulated data generated by the R package with set.seed(12345):

  • J = 50 control units
  • T0 = 50 pre-treatment periods
  • T1 = 5 post-treatment periods
  • True treatment effect = 2
import numpy as np
from scinference import scinference

# Load data (generated by R for exact comparison)
# Y0: control outcomes (T x J matrix)
# Y1: treated outcome (T x 1 vector)
T0, T1 = 50, 5

Testing a Null Hypothesis

We test the null hypothesis H0: theta = (4, 4, 4, 4, 4)'. Since the true effect is 2, this is a false null and we expect to reject it.

# Synthetic Control with Moving Block permutations
result_sc = scinference(Y1, Y0, T1=T1, T0=T0, theta0=4,
                        estimation_method="sc", permutation_method="mb")

# Difference-in-Differences
result_did = scinference(Y1, Y0, T1=T1, T0=T0, theta0=4,
                         estimation_method="did", permutation_method="mb")

# Constrained Lasso
result_classo = scinference(Y1, Y0, T1=T1, T0=T0, theta0=4,
                            estimation_method="classo", permutation_method="mb")

Results: P-values for H0: theta = 4 (Moving Block Permutations)

Method Python R Match
Synthetic Control 0.018182 0.018182 YES
Difference-in-Diff 0.036364 0.036364 YES
Constrained Lasso 0.036364 0.036364 YES

All three methods reject the false null at the 5% level.

Pointwise Confidence Intervals

Compute 90% pointwise confidence intervals using the synthetic control method:

result_ci = scinference(Y1, Y0, T1=T1, T0=T0,
                        estimation_method="sc",
                        ci=True,
                        ci_grid=np.arange(-2, 8.1, 0.1),
                        alpha=0.1)

print("90% Confidence Intervals:")
for t in range(T1):
    print(f"  Period {t+1}: [{result_ci['lb'][t]:.2f}, {result_ci['ub'][t]:.2f}]")

Results: 90% Pointwise Confidence Intervals

Period Python LB R LB Python UB R UB Match
1 0.80 0.80 4.10 4.10 YES
2 1.50 1.50 4.60 4.60 YES
3 0.40 0.40 4.00 4.00 YES
4 1.80 1.80 5.20 5.20 YES
5 -0.50 -0.50 2.60 2.60 YES

Confidence Intervals

The true treatment effect (2) is covered by the confidence intervals in all periods.


Example 2: T-test Based Inference

The t-test method requires a larger number of post-treatment periods and provides estimates of the Average Treatment Effect on the Treated (ATT).

Data

Data generated by R with set.seed(12345):

  • J = 30 control units
  • T0 = 30 pre-treatment periods
  • T1 = 30 post-treatment periods
  • True ATT = 2
# T-test with K=2 cross-fits
result = scinference(Y1, Y0, T1=T1, T0=T0,
                     inference_method="ttest", K=2, alpha=0.1)

print(f"ATT estimate: {result['att']:.4f}")
print(f"Standard Error: {result['se']:.4f}")
print(f"90% CI: [{result['lb']:.4f}, {result['ub']:.4f}]")

Results: T-test with Synthetic Control (K=2)

Metric Python R Match
ATT 1.488715 1.488715 YES
Standard Error 0.292220 0.292220 YES
90% CI Lower -0.356287 -0.356287 YES
90% CI Upper 3.333716 3.333716 YES

Results: T-test with Synthetic Control (K=3)

result_K3 = scinference(Y1, Y0, T1=T1, T0=T0,
                        inference_method="ttest", K=3, alpha=0.1)
Metric Python R Match
ATT 1.526818 1.526818 YES
Standard Error 0.194858 0.194858 YES
90% CI Lower 0.957835 0.957835 YES
90% CI Upper 2.095801 2.095801 YES

Results: T-test with Difference-in-Differences (K=2)

result_did = scinference(Y1, Y0, T1=T1, T0=T0,
                         inference_method="ttest",
                         estimation_method="did", K=2, alpha=0.1)
Metric Python R Match
ATT 1.624656 1.624656 YES
Standard Error 0.192063 0.192063 YES
90% CI Lower 0.412019 0.412019 YES
90% CI Upper 2.837293 2.837293 YES

T-test Comparison

All methods produce estimates close to the true ATT of 2, with the true value covered by the confidence intervals.


API Reference

Main Function

scinference(Y1, Y0, T1, T0,
            inference_method="conformal",
            alpha=0.1,
            ci=False,
            theta0=0,
            estimation_method="sc",
            permutation_method="mb",
            ci_grid=None,
            n_perm=5000,
            K=2)

Parameters

Parameter Type Default Description
Y1 array Required Outcome for treated unit (T x 1)
Y0 array Required Outcomes for control units (T x J)
T1 int Required Number of post-treatment periods
T0 int Required Number of pre-treatment periods
inference_method str "conformal" "conformal" or "ttest"
alpha float 0.1 Significance level
ci bool False Compute confidence intervals (conformal)
theta0 float/array 0 Null hypothesis value
estimation_method str "sc" "did", "sc", or "classo"
permutation_method str "mb" "mb" (moving block) or "iid"
ci_grid array None Grid for CI computation
n_perm int 5000 Permutations for IID method
K int 2 Number of cross-fits (t-test)

Returns

Conformal inference:

  • p_val: p-value for the null hypothesis
  • lb: lower bounds of pointwise CIs (if ci=True)
  • ub: upper bounds of pointwise CIs (if ci=True)

T-test:

  • att: Average Treatment Effect on the Treated
  • se: Standard error
  • lb: Lower bound of confidence interval
  • ub: Upper bound of confidence interval

Estimation Methods

Method Description
did Difference-in-differences (simple average of controls)
sc Synthetic control (Abadie et al.) - constrained weighted average
classo Constrained lasso - L1-penalized with sum-to-one constraint

References

  • Chernozhukov, V., Wuthrich, K., & Zhu, Y. (2021). "An Exact and Robust Conformal Inference Method for Counterfactual and Synthetic Controls." Journal of the American Statistical Association. arXiv:1712.09089

  • Chernozhukov, V., Wuthrich, K., & Zhu, Y. (2019). "Practical and robust t-test based inference for synthetic control and related methods." arXiv:1812.10820


License

GPL-3.0

Metadata

Release files for scinference 0.1.0

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

Source distribution (sdist)

Source distribution for scinference 0.1.0
File Size Uploaded
scinference-0.1.0.tar.gz 19.7 kB Details

Built distribution (wheel)

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

Total release size: 31.8 kB

Release files / scinference-0.1.0.tar.gz

Download URL scinference-0.1.0.tar.gz
Size 19.7 kB
Tags Source
SHA-256 checksum
How to use checksums
4b96898da2b3e10ff5f89513111045bc603184804c57900e04574058b5aca0c6
BLAKE2b-256 checksum
How to use checksums
b2c631361f75204522050e2a6ed474fd447e114314aa661b73c55657523b591a
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 Jan 21, 2026.

Transparency log

Release files / scinference-0.1.0-py3-none-any.whl

Download URL scinference-0.1.0-py3-none-any.whl
Size 12.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5ca216d3313a8e70e327d5110ff6083193b53a2c97432162842e0d34207fb301
BLAKE2b-256 checksum
How to use checksums
f1a42bce47e085d34b01860d0cd18a0f29b8a9feb6d0af2849b7e832705e3429
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 Jan 21, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

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