pymc-labs / pymc-labs/pathmc

Feature: Controlled Direct Effect (CDE) helper

Open
#116 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
128
Forks
12
Avg merge
16d 17h
Merged PRs (30d)
1

Description

Summary

When a model has a mediator (X → M → Y with X → Y), users often want to decompose the total effect into direct and indirect components. For linear Gaussian models, `indirect := a*b` is exact. For non-linear models (Bernoulli, Poisson), the product of coefficients is only approximate — the correct approach is the controlled direct effect: fix the mediator at a value (e.g., its mean) while varying the treatment, then compare to the total effect.

Currently, computing the CDE requires two manual `do()` calls — one setting both the treatment and the mediator, another setting only the treatment — and taking the difference. A convenience method would make this a single call.

Proposed API

# CDE: fix mediator at its mean, vary treatment
model.cde("Y", treatment="X", mediator="M")

# CDE: fix mediator at a specific value
model.cde("Y", treatment="X", mediator="M", mediator_value=0.5)

# Proportion mediated (requires CDE)
model.proportion_mediated("Y", treatment="X", mediator="M")
# → posterior distribution of (total - CDE) / total

Motivation

This pattern appears naturally in applied work:

  • SaaS funnels: engagement → activation → conversion (all Bernoulli). What fraction of the engagement effect on conversion is mediated through activation?
  • Marketing: spend → brand awareness → sales. How much of the spend effect goes through the brand channel vs. directly?
  • Vaccine surrogates: treatment → biomarker → outcome. Is the biomarker a valid surrogate endpoint?

The `saas_funnel.qmd` and `vaccine_surrogates.qmd` examples already demonstrate this workflow manually. A built-in helper would make it ergonomic.

This is identified in the PRD (`prd_v1.md`, §12) as a planned post-v1 convenience feature. It would also be useful in the PyMC Labs causal inference workshop (currently in planning), where Session 7 covers heterogeneous treatment effects and mediation decomposition.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with prd_v1.md §12 to understand the planned post-v1 scope, then read saas_funnel.qmd and vaccine_surrogates.qmd for the existing manual do() workflow. Define completion around replacing those repeated calls with the proposed cde() helper and adding proportion_mediated() with the stated posterior calculation.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.