CausalPy in 2025: a year of growing up for quasi‑experimental analysis #588
drbenvincent
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
CausalPy 2025 retrospective
2025 was a year where CausalPy quietly but decisively grew up. The library stayed true to its focus on quasi‑experimental designs, but the experience of actually using it became smoother, more flexible, and better documented.
From multiple‑treated‑unit synthetic control to a new reporting layer and custom priors, the changes this year were less about flashy new features and more about making CausalPy feel like a practical, dependable toolbox for real data and real teams.
2025 in numbers
Rather than stepping through each release in order, it is helpful to start with a quick snapshot of the year.
The rest of this review looks at what actually changed for users: by design type, by modelling flexibility, in the documentation, and under the hood.
What improved for your favourite design?
Because CausalPy is organised around quasi‑experimental designs, it makes sense to tour the year by design rather than by version number.
Synthetic control: from single unit to richer workflows
Synthetic control saw some of the most visible user‑facing changes in 2025.
The headline shift was support for multiple treated units in the synthetic control experiment class. This required some breaking API changes in 0.5.0, but in exchange it became much easier to handle more realistic settings where more than one region, store, or segment receives the intervention.
Behind that change sat a refactoring of the
SyntheticControlclass and related code. The intent was to keep the public surface as simple as possible while making the internals easier to extend and reason about. Later in the year, fixes aroundSyntheticControl.get_plot_datatightened up the plotting workflow, so that the data you get out more closely reflects the objects you have fit.Together, these changes mark a shift from “you can do synthetic control in CausalPy” to “you can do synthetic control the way it shows up in real‑world work, including multiple treated units and better plotted outputs.”
Interrupted time series and MMM calibration
Interrupted time series (ITS) stayed central to CausalPy in 2025, but the improvements were as much about explanation as about code.
The ITS documentation was expanded to give more detail on how to extract causal impact measures from fitted models, and to clarify what the different summaries mean in practice. For users, this is the difference between looking at a plot and being able to answer concrete questions like “What was the lift over the post‑intervention period?”
A particularly practical addition is an ITS lift‑testing notebook for MMM (marketing mix modelling) calibration. This acts as a bridge between experimental or quasi‑experimental effects and MMM models. It also serves as a worked example for anyone calibrating their own forecasting or optimisation pipelines using CausalPy’s ITS functionality.
Difference‑in‑differences: more flexible and better documented
Difference‑in‑differences (DID) also saw both conceptual and practical improvements.
On the practical side, the scikit‑learn‑flavoured
DifferenceInDifferencesimplementation was refactored, and it became possible to supply custom column names for thepost_treatmentindicator. That sounds small, but it removes a lot of friction when adapting CausalPy to existing data schemas and pipelines.On the conceptual side, the documentation around DID was updated to emphasise the two‑way fixed effects (TWFE) formulation. The updated docs provide a clearer connection between the models you might write down on paper, the formulas used in the literature, and the way CausalPy’s objects are parameterised.
The net effect is that difference‑in‑differences in CausalPy is both a better fit for messy, real‑world datasets and easier to reason about from first principles.
Regression discontinuity and related designs
Regression discontinuity (RD) and related pre‑test/post‑test designs did not see large, headline‑grabbing changes, but they did receive a steady stream of polish.
A bugfix improved handling of integer treatment indicators in the regression discontinuity experiment class, making the behaviour more robust when working with typical tabular datasets. The docs were also updated to make the notion of a sharp regression discontinuity design more explicit, reducing the gap between textbook definitions and actual code.
In the knowledge base, CausalPy gained more material on pre‑test/post‑test non‑equivalent group designs, along with extended discussion of how these designs relate to other quasi‑experimental approaches supported by the library. This helps situate RD and its relatives in a broader methodological landscape.
Modelling flexibility and reporting
Beyond any specific design, two cross‑cutting themes in 2025 were greater modelling flexibility and better ways of getting results out.
Custom priors and more explicit modelling
One of the most important additions of the year was support for custom priors via a
Priorclass. Instead of being restricted to a default priors, users can now express more of their own modelling preferences directly in CausalPy.The practical impact is that teams with established Bayesian workflows can align CausalPy’s models with their house style rather than treating CausalPy as a sealed black box. Example notebooks show how to override defaults and plug in custom priors in a way that remains discoverable and documented.
More broadly, the work on propensity score estimation and the discussion of joint estimation versus two‑stage approaches signal an ongoing shift toward making modelling choices explicit and inspectable.
A new reporting layer and clearer plot data
The introduction of a reporting layer in 0.6.0 is another step toward treating CausalPy as something that can be embedded in production workflows. Rather than leaving users to stitch together outputs ad hoc, the reporting layer creates a more standardised way to gather and present results.
Alongside this, several changes focused on the data that underlies plots and diagnostics. Accessors like
get_plot_datafor pre/post‑fit experiments were expanded and then refined over the year, and the definition of goodness of fit viar2_scorewas updated to focus on posterior expectations rather than posterior predictions.These changes make it easier to do two things that matter in practice: reproduce plots outside of notebooks (for example, in dashboards or slide decks), and explain how fit metrics are actually computed.
Documentation, knowledge base, and learning resources
A substantial share of 2025 work went into documentation and educational material, which is often the difference between a promising library and one that people can really adopt.
On the conceptual side, the documentation grew deeper coverage of several topics:
On the practical side, a curated list of written learning resources was added to the docs, making it easier for new users to find tutorials, blog posts, or longer‑form explanations around CausalPy and quasi‑experimental methods.
Smaller fixes also added up: updated badges and CI status on the landing page, unsquashed images in the documentation, and tidier navigation. None of these change how the models work, but they do change how approachable the library feels.
Under the hood: quality, tooling, and compatibility
A year in review would be incomplete without acknowledging the less visible work that keeps the project healthy.
Type safety and static analysis
CausalPy adopted MyPy checks and gained more type hints in key modules such as the simulation utilities. This is valuable for two reasons: it reduces the chance of subtle type‑related bugs, and it makes the library easier to integrate into codebases that already rely on static analysis.
Ruff‑based formatting of docstrings and other style improvements help to keep the codebase consistent and readable as more contributors join.
Tooling, CI, and build improvements
On the maintenance side, 2025 saw a raft of quality‑of‑life changes:
environment.ymlandpyproject.tomlso that dependencies are defined consistently.These changes are minor individually, but together they make CausalPy more pleasant to work on, which is essential for a growing open‑source project.
Keeping pace with Python
Finally, CausalPy adjusted its Python support, dropping Python 3.10 and adding support for Python 3.13. This keeps the project aligned with the modern Python ecosystem and reduces the maintenance burden of supporting older versions indefinitely.
Community and contributors
One of the quiet successes of 2025 was the steady growth of the contributor community.
Each release included a “New Contributors” section, and across the year 16 human contributors appeared in the release notes, including 12 people making their first contribution to the project. On top of that, a GitHub Actions bot helped to automate some of the project’s housekeeping. Contributions covered everything from bugfixes and CI improvements to documentation, new features, and examples.
The core maintainers continued to drive most of the big changes, but the presence of new names on each release is a healthy sign: CausalPy is no longer a one‑or‑two‑person project, but a small and gradually diversifying community.
If you are reading this as a user rather than a contributor, this matters because it increases the odds that bugs will be noticed, docs will be improved, and new quasi‑experimental patterns will be added over time.
Looking ahead
Taken together, the 2025 releases did not radically redefine what CausalPy is. Instead, they made it more usable, more flexible, and more maintainable.
Synthetic control is better equipped for realistic scenarios with multiple treated units. Interrupted time series is better documented and more tightly integrated with tasks like MMM calibration. Difference‑in‑differences is easier to plug into existing datasets and easier to relate to the fixed‑effects models familiar from the literature. Regression discontinuity and related designs have been polished at the edges.
Underneath all of this, the addition of custom priors, a reporting layer, and stronger tooling pushes CausalPy toward being something that can live comfortably in production workflows, not just in exploratory notebooks.
If 2024 was about establishing CausalPy as a useful repository of quasi‑experimental designs, 2025 looks like the year it began to feel like a mature, evolving toolbox. The most encouraging part is that this progress came from a mix of core maintainers and new contributors. That combination bodes well for whatever designs, examples, and integrations emerge in 2026.
Beta Was this translation helpful? Give feedback.
All reactions