Comparison with Other Packages
Where pathmc fits in the Python causal inference ecosystem
The Python ecosystem has several excellent packages for causal inference, each built around different design philosophies and targeting different workflows. This page maps out where pathmc sits relative to five widely used alternatives, so you can pick the right tool for the job.
Philosophy
pathmc occupies a specific niche: structural causal models with Bayesian estimation and interventional simulation via a concise DSL. It combines three things that are usually separate:
- A lavaan-style formula language for specifying systems of equations
- Full Bayesian inference via PyMC
- A built-in do() operator that uses PyMC-native graph surgery (
pm.do()) to propagate posterior uncertainty through the DAG
Other packages emphasize different parts of the causal workflow — discovery, identification, estimation of treatment effects, or quasi-experimental designs. The right choice depends on what stage of the analysis you’re in and what assumptions you’re willing to encode.
While pathmc is built on Pearl’s SCM framework (DAGs, structural equations, the do-operator), the quantities it computes — ATE, CATE, and interventional distributions — are the same estimands targeted by potential outcomes methods. See Pearl ↔︎ Potential Outcomes for a detailed term mapping and equivalence guide.
Feature comparison
The table below compares pathmc against five packages that Python practitioners commonly reach for when doing causal inference.
| Feature | pathmc | DoWhy | CausalPy | semopy | EconML | Bambi |
|---|---|---|---|---|---|---|
| Bayesian inference | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ |
| Formula DSL | ✅ ~ ~~ := X:Z |
❌ | ❌ | ✅ lavaan-style | ❌ | ✅ R-style |
| Multi-equation systems | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
Residual covariance (~~) |
✅ LKJ + MvNormal | ❌ | ❌ | ✅ | ❌ | ❌ |
| do() operator | ✅ pm.do() graph surgery |
✅ estimation-based | ❌ | ❌ | ❌ | ❌ |
| Time-forward simulation | ✅ panel do() | ❌ | ❌ | ❌ | ❌ | ❌ |
| Transforms with estimable params | ✅ adstock, saturation | ❌ | ❌ | ❌ | ❌ | ❌ |
| Smooth and periodic basis terms | ✅ hsgp(), bs()/ns()/ps() (1-D); fourier() for periodic effects |
❌ | ❌ | ❌ | ❌ | ✅ hsgp() |
| Panel / longitudinal data | ✅ random intercepts + slopes | ❌ | ✅ time series focus | ❌ | ❌ | ✅ via groups |
| Causal identification checks | ✅ backdoor, front-door, colliders | ✅ comprehensive | ❌ | ❌ | ❌ | ❌ |
| Backdoor regression adjustment | ✅ adjustment_model() | ✅ many estimators | ❌ | ❌ | ❌ | ✅ formula + interpret |
| Implied independence tests | ✅ test_implications() | ❌ | ❌ | ❌ | ❌ | ❌ |
| Sensitivity analysis | ✅ sensitivity() | ✅ refutation tests | ❌ | ❌ | ❌ | ❌ |
| Heterogeneous treatment effects | ✅ cate() | ❌ | ❌ | ❌ | ✅ core strength | ✅ via interactions |
| Quasi-experimental designs | ✅ DiD via panel do() | ✅ DiD, IV | ✅ DiD, SC, RDD | ❌ | ✅ DML, IV | ❌ |
| Latent variables | ✅ deterministic mediators | ❌ | ❌ | ✅ CFA/SEM | ❌ | ❌ |
| Causal discovery | ✅ TBFPC (experimental) | ✅ via plugins | ❌ | ❌ | ❌ | ❌ |
| Posterior predictive checks | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ |
| Standardized effects (stdyx) | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
| Path-specific effects | ✅ effect("X→M→Y") |
❌ | ❌ | ✅ indirect effects | ❌ | ❌ |
| Probabilistic queries | ✅ prob("Y>0") |
❌ | ❌ | ❌ | ❌ | ❌ |
| Data simulation from model | ✅ simulate() | ❌ | ❌ | ❌ | ❌ | ❌ |
Package-by-package comparison
DoWhy
DoWhy is the most comprehensive causal inference framework in Python. It follows a four-step workflow — model, identify, estimate, refute — that cleanly separates the causal reasoning from the statistical estimation. DoWhy’s identification engine is more complete than pathmc’s: it implements the full do-calculus, instrumental variables, and more. pathmc covers backdoor and front-door identification, but DoWhy goes further.
Choose DoWhy when you need rigorous identification beyond the backdoor criterion, want access to many estimators (IPW, matching, IV, etc.), or need refutation tests to stress-test your estimates.
Choose pathmc when you want to specify a full system of structural equations (not just one treatment-outcome pair), need Bayesian uncertainty quantification throughout, or want to simulate counterfactual scenarios by propagating posterior draws through the DAG. DoWhy estimates a single treatment effect; pathmc models the entire system and lets you query any variable under any intervention.
CausalPy
CausalPy is PyMC Labs’ package for quasi-experimental causal inference. It provides Bayesian implementations of difference-in-differences, synthetic control, regression discontinuity, and interrupted time series designs. CausalPy is excellent when you have a natural experiment and want to estimate its effect with full posterior uncertainty.
Choose CausalPy when your identification strategy is a quasi-experimental design (a policy change, a natural experiment, a geographic discontinuity) and you want a purpose-built tool for that specific estimand.
Choose pathmc when you want to model the causal mechanism itself — the system of equations connecting variables — rather than estimating a single treatment effect from a quasi-experiment. pathmc’s do() operator answers “what would happen if I intervened?” by simulating through the structural model, while CausalPy answers “what was the effect of this past intervention?” using pre/post comparisons.
semopy
semopy is the closest methodological relative to pathmc — it implements structural equation modeling in Python with a lavaan-inspired syntax. If you’re coming from R’s lavaan, semopy will feel immediately familiar. It supports latent variables (CFA), full SEM, and fit indices (CFI, RMSEA, SRMR) that pathmc does not.
Choose semopy when you need latent variable models (factor analysis, measurement models), frequentist estimation with ML or DWLS, or classical SEM fit indices.
Choose pathmc when you want Bayesian inference (full posteriors, priors, posterior predictive checks), a do() operator for interventional queries, panel data with hierarchical structure, transforms with estimable parameters, or latent deterministic mediators. semopy gives you the full SEM toolkit with measurement models; pathmc gives you Bayesian path analysis with a causal simulation engine and PyMC-native interventions.
EconML
EconML (Microsoft) specializes in heterogeneous treatment effect estimation using machine learning. Its core strength is estimating how treatment effects vary across subpopulations — CATE estimation via methods like double machine learning, causal forests, and orthogonal random forests. EconML scales to high-dimensional settings where traditional regression would struggle.
Choose EconML when you have high-dimensional covariates, want nonparametric CATE estimates, or need treatment effect estimation that is robust to model misspecification via double/debiased ML.
Choose pathmc when you want to model the causal mechanism structurally (not just estimate a single treatment effect), need Bayesian uncertainty quantification, or want to simulate counterfactual scenarios through a system of equations. EconML is agnostic about mechanism — it estimates effects without specifying how the treatment operates. pathmc requires you to specify the mechanism but rewards you with richer queries.
Bambi
Bambi is a high-level Bayesian regression interface built on PyMC. It shares pathmc’s Bayesian foundation and formula-based model specification, and it is excellent for building individual regression models with complex random-effects structures. Using Bambi’s interpret module, you can compute predictions, comparisons, and slopes that approximate causal quantities when identification assumptions hold.
Choose Bambi when you need full GAMs (multi-dimensional or grouped smooths beyond pathmc’s 1-D hsgp() and spline terms), distributional models, or sophisticated crossed or nested random-effects structures that pathmc does not provide, and you are willing to specify the adjustment formula by hand.
Choose pathmc when you need to model a system of equations simultaneously, want residual covariance across equations, need a do() operator that propagates through the full causal graph, want built-in identification checks, or want DAG-derived backdoor adjustment via adjustment_model() without leaving the pathmc API. Bambi excels at rich single-equation regression; pathmc models the whole DAG and can reduce it to a single identified outcome equation when that is all you need.
When to use what
| Scenario | Recommended tool |
|---|---|
| You have a DAG and want to estimate all paths simultaneously | pathmc |
| You need to simulate counterfactual interventions through a system | pathmc |
| You want to assess robustness to unmeasured confounding | pathmc or DoWhy |
| You need rigorous identification beyond the backdoor criterion | DoWhy |
| You have a natural experiment (DiD, RDD, synthetic control) | CausalPy |
| You need latent variable SEM with fit indices | semopy |
| You have high-dimensional data and want nonparametric CATE | EconML |
| You need a smooth nonlinear effect of one predictor inside a structural model | pathmc (hsgp() or bs()/ns()/ps(); fourier() for periodic effects) |
| You do not know the DAG and want candidate structure around one outcome | pathmc (TBFPC, experimental) or causal-learn |
| You need backdoor regression adjustment from a DAG | pathmc (adjustment_model()) |
| You need a flexible single-equation Bayesian model (multi-dimensional GAMs, rich multilevel) | Bambi |
| You want an MMM with adstock/saturation and counterfactual simulation | pathmc |
| You want to combine multiple tools in a workflow | Use DoWhy for identification, then pathmc (structural or adjustment_model()) or Bambi for estimation |
What pathmc does not do
Being clear about limitations is as important as highlighting strengths:
- No latent factor models. pathmc supports latent deterministic mediators (unobserved variables fully determined by their parents), but not measurement models, factor analysis, or CFA/SEM latent factors. For those, use semopy or lavaan (R).
- Causal discovery is experimental and target-oriented. TBFPC learns a CPDAG around a single outcome from a list of candidate drivers, using a linear-Gaussian Bayes-factor test for conditional independence, and same_markov_equivalence_class() lets you check a hand-drawn DAG against the result. It is one PC-style algorithm, not a discovery library: there is no score-based search, no FCI-style handling of latent confounders, and no time-series discovery. For a broader toolkit, see causal-learn or DoWhy’s discovery plugins; see Causal Discovery for what pathmc does provide.
- Nonparametric effects are limited to one-dimensional smooths. The
hsgp(),bs(),ns(), andps()basis terms each smooth a single exogenous predictor inside a structural equation — the input cannot be a mediator, observed or latent.hsgp()is a kernel approximation with a hard support boundary; the splines are a fixed B-spline or natural-spline basis, withps()adding a random-walk penalty, and they extrapolate (polynomial forbs/ps, linear forns) rather than stopping at a boundary. The companionfourier()term is a parametric periodic basis (a fixed number of harmonics at a given period) that can also take a mediator as input. All of these are cross-sectional only (not yet available in panel models), one-dimensional, and cannot be nested inside a transform or used in an equation whose outcome participates in a~~residual-covariance block. For high-dimensional or multi-predictor nonparametric CATE estimation, use EconML or BART-based approaches. - No instrumental variables. Identification supports the backdoor criterion and front-door criterion (frontdoor_identifiable()), but not IV estimation.
- Structural equations are additive in their terms. Each equation’s right-hand side is a sum of terms — linear coefficients, interactions (
X:Z), transforms with estimable parameters (adstock, saturation), and basis-term smooths — forming a linear predictor on the link scale (identity for Gaussian and StudentT, logit for Bernoulli, log for Poisson and NegBinomial). For an observed outcome, the response mean is the inverse link of that sum; a deterministic latent mediator simply equals the sum. This covers a lot of nonlinearity, but an outcome that is an arbitrary non-additive function of its parents (for example, a product of two smooths) still requires custom PyMC code.
Complementary workflows
These packages are not mutually exclusive. A mature causal analysis might combine several:
- Specify the DAG from domain knowledge, optionally seeded by TBFPC discovery when the structure is only partly known
- Check identification with DoWhy’s do-calculus or pathmc’s adjustment_sets()
- Estimate with pathmc (full structural model, native adjustment_model(), or Bambi for multi-dimensional GAMs and rich multilevel formulas)
- Validate with quasi-experiments using CausalPy when natural experiments are available
- Explore heterogeneity with EconML for subgroup-level treatment effects
pathmc’s sweet spot is step 3 — fitting and querying a complete structural causal model with full Bayesian uncertainty — especially when you want to ask “what if?” questions via do().