CausalPy 0.8.1__tar.gz → 0.9.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. {causalpy-0.8.1 → causalpy-0.9.0}/CausalPy.egg-info/PKG-INFO +119 -43
  2. {causalpy-0.8.1 → causalpy-0.9.0}/CausalPy.egg-info/SOURCES.txt +34 -9
  3. {causalpy-0.8.1 → causalpy-0.9.0}/CausalPy.egg-info/requires.txt +18 -7
  4. {causalpy-0.8.1 → causalpy-0.9.0}/PKG-INFO +119 -43
  5. causalpy-0.9.0/README.md +179 -0
  6. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/__init__.py +27 -1
  7. causalpy-0.9.0/causalpy/checks/__init__.py +54 -0
  8. causalpy-0.9.0/causalpy/checks/bandwidth.py +140 -0
  9. causalpy-0.9.0/causalpy/checks/base.py +135 -0
  10. causalpy-0.9.0/causalpy/checks/convex_hull.py +119 -0
  11. causalpy-0.9.0/causalpy/checks/leave_one_out.py +135 -0
  12. causalpy-0.9.0/causalpy/checks/mccrary.py +152 -0
  13. causalpy-0.9.0/causalpy/checks/outcome_falsification.py +387 -0
  14. causalpy-0.9.0/causalpy/checks/persistence.py +141 -0
  15. causalpy-0.9.0/causalpy/checks/placebo_in_space.py +152 -0
  16. causalpy-0.9.0/causalpy/checks/placebo_in_time.py +1048 -0
  17. causalpy-0.9.0/causalpy/checks/pre_treatment_placebo.py +124 -0
  18. causalpy-0.9.0/causalpy/checks/prior_sensitivity.py +171 -0
  19. causalpy-0.9.0/causalpy/constants.py +28 -0
  20. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/custom_exceptions.py +21 -3
  21. causalpy-0.9.0/causalpy/data/california_prop99.csv +32 -0
  22. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/data/datasets.py +62 -35
  23. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/data/simulate_data.py +157 -116
  24. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/experiments/__init__.py +5 -1
  25. causalpy-0.9.0/causalpy/experiments/base.py +545 -0
  26. causalpy-0.9.0/causalpy/experiments/diff_in_diff.py +701 -0
  27. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/experiments/instrumental_variable.py +146 -37
  28. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/experiments/interrupted_time_series.py +532 -657
  29. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/experiments/inverse_propensity_weighting.py +329 -64
  30. causalpy-0.9.0/causalpy/experiments/model_adapter.py +703 -0
  31. causalpy-0.9.0/causalpy/experiments/panel_regression.py +1026 -0
  32. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/experiments/piecewise_its.py +386 -408
  33. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/experiments/prepostnegd.py +203 -71
  34. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/experiments/regression_discontinuity.py +259 -176
  35. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/experiments/regression_kink.py +206 -73
  36. causalpy-0.9.0/causalpy/experiments/staggered_did.py +1496 -0
  37. causalpy-0.9.0/causalpy/experiments/synthetic_control.py +904 -0
  38. causalpy-0.9.0/causalpy/experiments/synthetic_difference_in_differences.py +948 -0
  39. causalpy-0.9.0/causalpy/formula_utils.py +101 -0
  40. causalpy-0.9.0/causalpy/maketables_adapters.py +433 -0
  41. causalpy-0.9.0/causalpy/pipeline.py +216 -0
  42. causalpy-0.9.0/causalpy/plot_utils.py +490 -0
  43. causalpy-0.9.0/causalpy/pymc_forecast_models.py +442 -0
  44. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/pymc_models.py +662 -116
  45. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/reporting.py +236 -181
  46. causalpy-0.9.0/causalpy/skills/__init__.py +20 -0
  47. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/skl_models.py +39 -15
  48. causalpy-0.9.0/causalpy/steps/__init__.py +25 -0
  49. causalpy-0.9.0/causalpy/steps/estimate_effect.py +131 -0
  50. causalpy-0.9.0/causalpy/steps/report.py +167 -0
  51. causalpy-0.9.0/causalpy/steps/sensitivity.py +221 -0
  52. causalpy-0.9.0/causalpy/templates/report.html +131 -0
  53. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/transforms.py +119 -24
  54. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/utils.py +62 -20
  55. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/variable_selection_priors.py +14 -8
  56. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/version.py +2 -2
  57. {causalpy-0.8.1 → causalpy-0.9.0}/pyproject.toml +93 -30
  58. causalpy-0.9.0/scripts/_ast_introspection.py +142 -0
  59. causalpy-0.9.0/scripts/check_architecture_inventory.py +224 -0
  60. causalpy-0.9.0/scripts/check_public_exports.py +164 -0
  61. causalpy-0.9.0/scripts/check_rediraffe_redirects.py +242 -0
  62. causalpy-0.9.0/scripts/generate_gallery.py +330 -0
  63. causalpy-0.9.0/scripts/generate_plots.py +327 -0
  64. {causalpy-0.8.1 → causalpy-0.9.0}/scripts/run_notebooks/runner.py +53 -10
  65. causalpy-0.9.0/scripts/validate_docstring_lists.py +129 -0
  66. causalpy-0.9.0/scripts/validate_notebooks.py +223 -0
  67. causalpy-0.8.1/README.md +0 -113
  68. causalpy-0.8.1/causalpy/data/ancova_generated.csv +0 -201
  69. causalpy-0.8.1/causalpy/data/did.csv +0 -41
  70. causalpy-0.8.1/causalpy/data/geolift1.csv +0 -209
  71. causalpy-0.8.1/causalpy/data/geolift_multi_cell.csv +0 -209
  72. causalpy-0.8.1/causalpy/data/gt_social_media_data.csv +0 -182
  73. causalpy-0.8.1/causalpy/data/its.csv +0 -121
  74. causalpy-0.8.1/causalpy/data/its_simple.csv +0 -121
  75. causalpy-0.8.1/causalpy/data/regression_discontinuity.csv +0 -101
  76. causalpy-0.8.1/causalpy/data/synthetic_control.csv +0 -101
  77. causalpy-0.8.1/causalpy/experiments/base.py +0 -197
  78. causalpy-0.8.1/causalpy/experiments/diff_in_diff.py +0 -607
  79. causalpy-0.8.1/causalpy/experiments/staggered_did.py +0 -968
  80. causalpy-0.8.1/causalpy/experiments/synthetic_control.py +0 -942
  81. causalpy-0.8.1/causalpy/plot_utils.py +0 -126
  82. causalpy-0.8.1/scripts/validate_notebooks.py +0 -126
  83. {causalpy-0.8.1 → causalpy-0.9.0}/CausalPy.egg-info/dependency_links.txt +0 -0
  84. {causalpy-0.8.1 → causalpy-0.9.0}/CausalPy.egg-info/top_level.txt +0 -0
  85. {causalpy-0.8.1 → causalpy-0.9.0}/LICENSE +0 -0
  86. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/data/AJR2001.csv +0 -0
  87. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/data/GDP_in_dollars_billions.csv +0 -0
  88. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/data/PISA18sampleScale.csv +0 -0
  89. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/data/__init__.py +0 -0
  90. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/data/banks.csv +0 -0
  91. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/data/data_nevo.csv +0 -0
  92. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/data/deaths_and_temps_england_wales.csv +0 -0
  93. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/data/drinking.csv +0 -0
  94. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/data/lalonde.csv +0 -0
  95. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/data/nets_df.csv +0 -0
  96. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/data/nhefs.csv +0 -0
  97. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/data/schoolingReturns.csv +0 -0
  98. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/data/zipcodes_data.csv +0 -0
  99. {causalpy-0.8.1 → causalpy-0.9.0}/causalpy/date_utils.py +0 -0
  100. {causalpy-0.8.1 → causalpy-0.9.0}/scripts/run_notebooks/injected.py +0 -0
  101. {causalpy-0.8.1 → causalpy-0.9.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: CausalPy
3
- Version: 0.8.1
3
+ Version: 0.9.0
4
4
  Summary: Causal inference for quasi-experiments in Python
5
5
  Author-email: Ben Vincent <ben.vincent@pymc-labs.com>
6
6
  License: Apache License
@@ -224,11 +224,12 @@ Classifier: Topic :: Scientific/Engineering :: Mathematics
224
224
  Requires-Python: >=3.11
225
225
  Description-Content-Type: text/markdown
226
226
  License-File: LICENSE
227
- Requires-Dist: arviz>=0.14.0
227
+ Requires-Dist: arviz<1.0,>=0.14.0
228
228
  Requires-Dist: graphviz
229
229
  Requires-Dist: ipython!=8.7.0
230
+ Requires-Dist: jinja2
230
231
  Requires-Dist: matplotlib>=3.5.3
231
- Requires-Dist: numpy<2.4
232
+ Requires-Dist: numpy
232
233
  Requires-Dist: pandas
233
234
  Requires-Dist: patsy
234
235
  Requires-Dist: pymc<6,>=5.15.1
@@ -239,15 +240,18 @@ Requires-Dist: seaborn>=0.11.2
239
240
  Requires-Dist: statsmodels
240
241
  Requires-Dist: xarray>=v2022.11.0
241
242
  Requires-Dist: pymc-extras>=0.3.0
243
+ Provides-Extra: forecast
244
+ Requires-Dist: pymc-forecast[extras]<0.3,>=0.2; extra == "forecast"
242
245
  Provides-Extra: dev
243
- Requires-Dist: pre-commit; extra == "dev"
246
+ Requires-Dist: prek; extra == "dev"
244
247
  Requires-Dist: twine; extra == "dev"
245
- Requires-Dist: interrogate; extra == "dev"
246
248
  Requires-Dist: codespell; extra == "dev"
247
249
  Requires-Dist: nbformat; extra == "dev"
248
250
  Requires-Dist: nbconvert; extra == "dev"
251
+ Requires-Dist: PyYAML; extra == "dev"
249
252
  Provides-Extra: docs
250
253
  Requires-Dist: ipykernel; extra == "docs"
254
+ Requires-Dist: maketables; extra == "docs"
251
255
  Requires-Dist: pymc-marketing>=0.13.1; extra == "docs"
252
256
  Requires-Dist: daft-pgm; extra == "docs"
253
257
  Requires-Dist: linkify-it-py; extra == "docs"
@@ -262,52 +266,86 @@ Requires-Dist: sphinx-copybutton; extra == "docs"
262
266
  Requires-Dist: sphinx-rtd-theme; extra == "docs"
263
267
  Requires-Dist: sphinx-sitemap; extra == "docs"
264
268
  Requires-Dist: statsmodels; extra == "docs"
265
- Requires-Dist: sphinxcontrib-bibtex; extra == "docs"
269
+ Requires-Dist: sphinxcontrib-bibtex>=2.7.0; extra == "docs"
266
270
  Requires-Dist: sphinx-notfound-page; extra == "docs"
267
271
  Requires-Dist: ipywidgets; extra == "docs"
268
272
  Requires-Dist: sphinx-design; extra == "docs"
269
273
  Requires-Dist: sphinx-togglebutton; extra == "docs"
274
+ Requires-Dist: nbformat; extra == "docs"
275
+ Requires-Dist: nbconvert; extra == "docs"
276
+ Requires-Dist: Pillow; extra == "docs"
277
+ Requires-Dist: PyYAML; extra == "docs"
278
+ Requires-Dist: sphinxext-rediraffe; extra == "docs"
270
279
  Provides-Extra: lint
271
- Requires-Dist: interrogate; extra == "lint"
272
- Requires-Dist: pre-commit; extra == "lint"
280
+ Requires-Dist: prek; extra == "lint"
273
281
  Requires-Dist: ruff; extra == "lint"
274
282
  Requires-Dist: mypy; extra == "lint"
275
283
  Provides-Extra: test
276
284
  Requires-Dist: pytest; extra == "test"
277
285
  Requires-Dist: pytest-cov; extra == "test"
286
+ Requires-Dist: diff-cover; extra == "test"
278
287
  Requires-Dist: codespell; extra == "test"
279
288
  Requires-Dist: nbformat; extra == "test"
280
289
  Requires-Dist: nbconvert; extra == "test"
281
290
  Requires-Dist: papermill; extra == "test"
291
+ Requires-Dist: pymc-forecast[extras]<0.3,>=0.2; extra == "test"
282
292
  Dynamic: license-file
283
293
 
284
294
  <div align="center">
285
- <a href="https://github.com/pymc-labs/CausalPy"><img width="60%" src="https://raw.githubusercontent.com/pymc-labs/CausalPy/main/docs/source/_static/logo.png"></a>
295
+ <a href="https://github.com/pymc-labs/CausalPy"><img width="40%" src="https://raw.githubusercontent.com/pymc-labs/CausalPy/main/docs/source/_static/logo.png"></a>
286
296
  </div>
287
297
 
288
298
  ----
289
299
 
300
+ [![PyPI version](https://badge.fury.io/py/CausalPy.svg)](https://badge.fury.io/py/CausalPy)
301
+ [![conda-forge](https://img.shields.io/conda/vn/conda-forge/causalpy.svg?color=green)](https://anaconda.org/conda-forge/causalpy)
302
+ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
303
+
290
304
  ![Build Status](https://github.com/pymc-labs/CausalPy/actions/workflows/ci.yml/badge.svg?branch=main)
291
305
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
292
- [![PyPI version](https://badge.fury.io/py/CausalPy.svg)](https://badge.fury.io/py/CausalPy)
293
- ![GitHub Repo stars](https://img.shields.io/github/stars/pymc-labs/causalpy?style=social)
306
+ [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit)
307
+ [![codecov](https://codecov.io/gh/pymc-labs/CausalPy/branch/main/graph/badge.svg?token=FDKNAY5CZ9)](https://codecov.io/gh/pymc-labs/CausalPy)
308
+
309
+ ![GitHub Repo stars](https://img.shields.io/github/stars/pymc-labs/causalpy?style=flat)
294
310
  ![Read the Docs](https://img.shields.io/readthedocs/causalpy)
311
+ [![Downloads](https://static.pepy.tech/badge/causalpy)](https://pepy.tech/project/causalpy)
295
312
  ![PyPI - Downloads](https://img.shields.io/pypi/dm/causalpy)
296
- ![Interrogate](https://raw.githubusercontent.com/pymc-labs/CausalPy/interrogate-badges/interrogate_badge.svg)
297
- [![codecov](https://codecov.io/gh/pymc-labs/CausalPy/branch/main/graph/badge.svg?token=FDKNAY5CZ9)](https://codecov.io/gh/pymc-labs/CausalPy)
298
313
 
299
- # CausalPy
314
+ <!-- docs-start -->
315
+
316
+ # Causal Inference for Quasi-Experiments
317
+
318
+ **Research-grade causal inference workflows** for quasi-experimental designs in Python.
319
+
320
+ CausalPy helps you estimate causal effects with transparent assumptions, uncertainty-aware modeling, and reproducible outputs:
321
+
322
+ - **Quasi-experimental methods:** Difference-in-differences, synthetic control, regression discontinuity, interrupted time series, instrumental variables, and more
323
+ - **Bayesian-first estimation** via [PyMC](https://www.pymc.io/) with full uncertainty quantification, plus traditional OLS via [scikit-learn](https://scikit-learn.org)
324
+ - **Decision-ready outputs:** Effect summaries with credible intervals (HDI), practical significance (ROPE), and publication-quality plots
300
325
 
301
- A Python package focussing on causal inference in quasi-experimental settings. The package allows for sophisticated Bayesian model fitting methods to be used in addition to traditional OLS.
326
+ ## 📞 [**Book a consulting call**](https://calendly.com/benjamin-vincent/causalpy)
327
+
328
+ CausalPy is built and maintained by [PyMC Labs](https://www.pymc-labs.com). If your team is exploring a consulting engagement for lift testing, complex or high-stakes causal work, you can book an introductory call. _These calls are for consulting inquiries only. For technical usage questions and free community support, please use GitHub Discussions and the documentation below._
329
+
330
+ ## Help and documentation
331
+
332
+ - Ask usage questions in [GitHub Discussions Q&A](https://github.com/pymc-labs/CausalPy/discussions/categories/q-a) so the issue tracker stays focused on bugs and enhancements.
333
+ - Report bugs and feature requests in [Issues](https://github.com/pymc-labs/CausalPy/issues)
334
+ - Browse detailed guides in the [documentation](https://causalpy.readthedocs.io)
302
335
 
303
336
  ## Installation
304
337
 
305
338
  To get the latest release:
339
+
306
340
  ```bash
307
341
  pip install CausalPy
308
342
  ```
309
343
 
310
- If you run into installation issues with PyMC (e.g. BLAS or compilation), try the conda install: `conda install -c conda-forge causalpy`.
344
+ or via conda:
345
+
346
+ ```bash
347
+ conda install causalpy -c conda-forge
348
+ ```
311
349
 
312
350
  Alternatively, if you want the very latest version of the package you can install from GitHub:
313
351
 
@@ -315,6 +353,10 @@ Alternatively, if you want the very latest version of the package you can instal
315
353
  pip install git+https://github.com/pymc-labs/CausalPy.git
316
354
  ```
317
355
 
356
+ ## AI Agent Skills
357
+
358
+ CausalPy includes agent skills that teach AI coding assistants how to use the library for causal inference. Skills are available via [Decision AI Hub](https://hub.decision.ai) and live in `causalpy/skills/` in the source tree.
359
+
318
360
  ## Quickstart
319
361
 
320
362
  ```python
@@ -326,7 +368,7 @@ df = (
326
368
  cp.load_data("drinking")
327
369
  .rename(columns={"agecell": "age"})
328
370
  .assign(treated=lambda df_: df_.age > 21)
329
- )
371
+ )
330
372
 
331
373
  # Run the analysis
332
374
  result = cp.RegressionDiscontinuity(
@@ -335,32 +377,52 @@ result = cp.RegressionDiscontinuity(
335
377
  running_variable_name="age",
336
378
  model=cp.pymc_models.LinearRegression(),
337
379
  treatment_threshold=21,
338
- )
380
+ )
339
381
 
340
- # Visualize outputs
341
- fig, ax = result.plot();
382
+ # Visualize the causal effect at the threshold
383
+ fig, ax = result.plot()
342
384
 
343
- # Get a results summary
385
+ # Get a results summary with posterior estimates
344
386
  result.summary()
345
-
346
- plt.show()
347
387
  ```
348
388
 
349
- ## Roadmap
350
-
351
- Plans for the repository can be seen in the [Issues](https://github.com/pymc-labs/CausalPy/issues).
389
+ The `result.plot()` visualizes the regression discontinuity design, showing the estimated jump at the treatment threshold. The `result.summary()` prints posterior estimates of the causal effect with uncertainty intervals.
352
390
 
353
391
  ## Videos
392
+
354
393
  Click on the thumbnail below to watch a video about CausalPy on YouTube.
394
+
355
395
  [![Youtube video thumbnail image](https://img.youtube.com/vi/gV6wzTk3o1U/maxresdefault.jpg)](https://www.youtube.com/watch?v=gV6wzTk3o1U)
356
396
 
357
- ## Features
397
+ ## When CausalPy is a good fit
398
+
399
+ - You have a plausible quasi-experimental design (threshold rule, policy change, staggered rollout, geo lift, etc.)
400
+ - You want uncertainty-aware estimates and diagnostics, not only point estimates
401
+ - You need reproducible analysis artifacts for review and communication
402
+
403
+ ## When CausalPy is not a fit
404
+
405
+ - You need causal discovery from weakly identified observational data
406
+ - You want fully automated "black box" causal answers without specifying assumptions
407
+ - You primarily need production workflow tooling (pipelines, governance, multi-user collaboration)
408
+
409
+ ## Methods and Workflows
358
410
 
359
- CausalPy has a broad range of quasi-experimental methods for causal inference:
411
+ CausalPy provides methods for common causal inference decision contexts:
360
412
 
361
- | Method | Description |
413
+ | Decision context | Methods |
414
+ |------------------|---------|
415
+ | Focussed testing on certain units (geos, products) | Synthetic control, Geographical lift |
416
+ | Evaluate before/after changes, launches, policy changes | Differences in Differences, Staggered DiD, Interrupted time series |
417
+ | Exploit cutoff rules, score-based eligibility (credit, age) | Regression discontinuity, Regression kink |
418
+ | Can't randomize, correct for selection | Instrumental variables, Inverse propensity weighting |
419
+ | Group differences, control for covariates | ANCOVA |
420
+
421
+ ### Available methods
422
+
423
+ | Method | Description |
362
424
  |-|-|
363
- | Synthetic control | Constructs a synthetic version of the treatment group from a weighted combination of control units. Used for causal inference in comparative case studies when a single unit is treated, and there are multiple control units.|
425
+ | Synthetic control | Constructs a synthetic version of the treatment group from a weighted combination of control units. Used for causal inference in comparative case studies when a single unit is treated, and there are multiple control units. |
364
426
  | Geographical lift | Measures the impact of an intervention in a specific geographic area by comparing it to similar areas without the intervention. Commonly used in marketing to assess regional campaigns. |
365
427
  | ANCOVA | Analysis of Covariance combines ANOVA and regression to control for the effects of one or more quantitative covariates. Used when comparing group means while controlling for other variables. |
366
428
  | Differences in Differences | Compares the changes in outcomes over time between a treatment group and a control group. Used in observational studies to estimate causal effects by accounting for time trends. |
@@ -371,26 +433,40 @@ CausalPy has a broad range of quasi-experimental methods for causal inference:
371
433
  | Instrumental variable regression | Addresses endogeneity by using an instrument variable that is correlated with the endogenous explanatory variable but uncorrelated with the error term. Used when explanatory variables are correlated with the error term, providing consistent estimates of causal effects. |
372
434
  | Inverse Propensity Score Weighting | Weights observations by the inverse of the probability of receiving the treatment. Used in causal inference to create a synthetic sample where the treatment assignment is independent of measured covariates, helping to adjust for confounding variables in observational studies. |
373
435
 
374
- ## License
436
+ ## Diagnostics-first by design
375
437
 
376
- [Apache License 2.0](LICENSE)
438
+ CausalPy emphasizes transparent, uncertainty-aware outputs for rigorous causal analysis:
377
439
 
378
- ---
440
+ - **Effect summaries:** Every experiment provides `effect_summary()` returning decision-ready statistics with both tabular and prose formats
441
+ - **Uncertainty quantification:** Bayesian models report HDI (Highest Density Intervals); OLS models report confidence intervals
442
+ - **Practical significance:** ROPE (Region of Practical Equivalence) analysis to assess whether effects exceed meaningful thresholds
443
+ - **Direction testing:** Tail probabilities (e.g., P(effect > 0)) for directional inference
379
444
 
380
- ## Getting Help
445
+ ## Citing CausalPy
381
446
 
382
- Have questions about using CausalPy? We're here to help!
447
+ If you use CausalPy in your research, please cite it. A Zenodo DOI for stable releases is planned. In the meantime, you can cite the repository:
383
448
 
384
- - **Questions & Help**: Visit our [GitHub Discussions Q&A](https://github.com/pymc-labs/CausalPy/discussions/categories/q-a) to ask questions and get help from the community
385
- - **Bug Reports & Feature Requests**: Open an [Issue](https://github.com/pymc-labs/CausalPy/issues) for bugs or feature requests
386
- - **Documentation**: Check out our [documentation](https://causalpy.readthedocs.io) for detailed guides and examples
449
+ ```bibtex
450
+ @software{causalpy,
451
+ author = {{PyMC Labs}},
452
+ title = {CausalPy: Causal inference for quasi-experiments in Python},
453
+ url = {https://github.com/pymc-labs/CausalPy},
454
+ year = {2026}
455
+ }
456
+ ```
387
457
 
388
- Please use GitHub Discussions for general questions rather than opening issues, so we can keep the issue tracker focused on bugs and enhancements.
458
+ ## Roadmap
459
+
460
+ Plans for the repository can be seen in the [Issues](https://github.com/pymc-labs/CausalPy/issues).
461
+
462
+ ## License
389
463
 
390
- ## Support
464
+ [Apache License 2.0](https://github.com/pymc-labs/CausalPy/blob/main/LICENSE)
391
465
 
392
- <img src="https://raw.githubusercontent.com/pymc-labs/CausalPy/main/docs/source/_static/pymc-labs-log.png" align="right" width="50%" />
466
+ ## Thanks to our contributors
393
467
 
394
- This repository is supported by [PyMC Labs](https://www.pymc-labs.com).
468
+ <a href="https://github.com/pymc-labs/CausalPy/graphs/contributors">
469
+ <img src="https://raw.githubusercontent.com/pymc-labs/CausalPy/main/docs/source/_static/contributors.svg" alt="CausalPy contributors" />
470
+ </a>
395
471
 
396
- If you are interested in seeing what PyMC Labs can do for you, then please email [ben.vincent@pymc-labs.com](mailto:ben.vincent@pymc-labs.com). We work with companies at a variety of scales and with varying levels of existing modeling capacity. We also run corporate workshop training events and can provide sessions ranging from introduction to Bayes to more advanced topics.
472
+ The contributor image is regenerated weekly by a GitHub Actions workflow (`.github/workflows/contributors.yml`) that opens a PR when the contributor list changes.
@@ -7,9 +7,14 @@ CausalPy.egg-info/dependency_links.txt
7
7
  CausalPy.egg-info/requires.txt
8
8
  CausalPy.egg-info/top_level.txt
9
9
  causalpy/__init__.py
10
+ causalpy/constants.py
10
11
  causalpy/custom_exceptions.py
11
12
  causalpy/date_utils.py
13
+ causalpy/formula_utils.py
14
+ causalpy/maketables_adapters.py
15
+ causalpy/pipeline.py
12
16
  causalpy/plot_utils.py
17
+ causalpy/pymc_forecast_models.py
13
18
  causalpy/pymc_models.py
14
19
  causalpy/reporting.py
15
20
  causalpy/skl_models.py
@@ -17,29 +22,33 @@ causalpy/transforms.py
17
22
  causalpy/utils.py
18
23
  causalpy/variable_selection_priors.py
19
24
  causalpy/version.py
25
+ causalpy/checks/__init__.py
26
+ causalpy/checks/bandwidth.py
27
+ causalpy/checks/base.py
28
+ causalpy/checks/convex_hull.py
29
+ causalpy/checks/leave_one_out.py
30
+ causalpy/checks/mccrary.py
31
+ causalpy/checks/outcome_falsification.py
32
+ causalpy/checks/persistence.py
33
+ causalpy/checks/placebo_in_space.py
34
+ causalpy/checks/placebo_in_time.py
35
+ causalpy/checks/pre_treatment_placebo.py
36
+ causalpy/checks/prior_sensitivity.py
20
37
  causalpy/data/AJR2001.csv
21
38
  causalpy/data/GDP_in_dollars_billions.csv
22
39
  causalpy/data/PISA18sampleScale.csv
23
40
  causalpy/data/__init__.py
24
- causalpy/data/ancova_generated.csv
25
41
  causalpy/data/banks.csv
42
+ causalpy/data/california_prop99.csv
26
43
  causalpy/data/data_nevo.csv
27
44
  causalpy/data/datasets.py
28
45
  causalpy/data/deaths_and_temps_england_wales.csv
29
- causalpy/data/did.csv
30
46
  causalpy/data/drinking.csv
31
- causalpy/data/geolift1.csv
32
- causalpy/data/geolift_multi_cell.csv
33
- causalpy/data/gt_social_media_data.csv
34
- causalpy/data/its.csv
35
- causalpy/data/its_simple.csv
36
47
  causalpy/data/lalonde.csv
37
48
  causalpy/data/nets_df.csv
38
49
  causalpy/data/nhefs.csv
39
- causalpy/data/regression_discontinuity.csv
40
50
  causalpy/data/schoolingReturns.csv
41
51
  causalpy/data/simulate_data.py
42
- causalpy/data/synthetic_control.csv
43
52
  causalpy/data/zipcodes_data.csv
44
53
  causalpy/experiments/__init__.py
45
54
  causalpy/experiments/base.py
@@ -47,12 +56,28 @@ causalpy/experiments/diff_in_diff.py
47
56
  causalpy/experiments/instrumental_variable.py
48
57
  causalpy/experiments/interrupted_time_series.py
49
58
  causalpy/experiments/inverse_propensity_weighting.py
59
+ causalpy/experiments/model_adapter.py
60
+ causalpy/experiments/panel_regression.py
50
61
  causalpy/experiments/piecewise_its.py
51
62
  causalpy/experiments/prepostnegd.py
52
63
  causalpy/experiments/regression_discontinuity.py
53
64
  causalpy/experiments/regression_kink.py
54
65
  causalpy/experiments/staggered_did.py
55
66
  causalpy/experiments/synthetic_control.py
67
+ causalpy/experiments/synthetic_difference_in_differences.py
68
+ causalpy/skills/__init__.py
69
+ causalpy/steps/__init__.py
70
+ causalpy/steps/estimate_effect.py
71
+ causalpy/steps/report.py
72
+ causalpy/steps/sensitivity.py
73
+ causalpy/templates/report.html
74
+ scripts/_ast_introspection.py
75
+ scripts/check_architecture_inventory.py
76
+ scripts/check_public_exports.py
77
+ scripts/check_rediraffe_redirects.py
78
+ scripts/generate_gallery.py
79
+ scripts/generate_plots.py
80
+ scripts/validate_docstring_lists.py
56
81
  scripts/validate_notebooks.py
57
82
  scripts/run_notebooks/injected.py
58
83
  scripts/run_notebooks/runner.py
@@ -1,8 +1,9 @@
1
- arviz>=0.14.0
1
+ arviz<1.0,>=0.14.0
2
2
  graphviz
3
3
  ipython!=8.7.0
4
+ jinja2
4
5
  matplotlib>=3.5.3
5
- numpy<2.4
6
+ numpy
6
7
  pandas
7
8
  patsy
8
9
  pymc<6,>=5.15.1
@@ -15,15 +16,16 @@ xarray>=v2022.11.0
15
16
  pymc-extras>=0.3.0
16
17
 
17
18
  [dev]
18
- pre-commit
19
+ prek
19
20
  twine
20
- interrogate
21
21
  codespell
22
22
  nbformat
23
23
  nbconvert
24
+ PyYAML
24
25
 
25
26
  [docs]
26
27
  ipykernel
28
+ maketables
27
29
  pymc-marketing>=0.13.1
28
30
  daft-pgm
29
31
  linkify-it-py
@@ -38,22 +40,31 @@ sphinx-copybutton
38
40
  sphinx-rtd-theme
39
41
  sphinx-sitemap
40
42
  statsmodels
41
- sphinxcontrib-bibtex
43
+ sphinxcontrib-bibtex>=2.7.0
42
44
  sphinx-notfound-page
43
45
  ipywidgets
44
46
  sphinx-design
45
47
  sphinx-togglebutton
48
+ nbformat
49
+ nbconvert
50
+ Pillow
51
+ PyYAML
52
+ sphinxext-rediraffe
53
+
54
+ [forecast]
55
+ pymc-forecast[extras]<0.3,>=0.2
46
56
 
47
57
  [lint]
48
- interrogate
49
- pre-commit
58
+ prek
50
59
  ruff
51
60
  mypy
52
61
 
53
62
  [test]
54
63
  pytest
55
64
  pytest-cov
65
+ diff-cover
56
66
  codespell
57
67
  nbformat
58
68
  nbconvert
59
69
  papermill
70
+ pymc-forecast[extras]<0.3,>=0.2