Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 19, 2025

Plan: Comparative Interrupted Time Series Documentation

  • Download and add zipcodes_data.csv to causalpy/data directory
  • Update datasets.py to add the new dataset to DATASETS dict and update load_data docstring
  • Create new notebook: its_pymc_comparative.ipynb in docs/source/notebooks/
  • Structure the notebook:
    • Introduction explaining CITS and attribution to Juan's blog
    • Explanation of CITS vs ITS vs SC
    • Load and prepare data
    • Aggregate data for treated and control units
    • Fit CITS model using InterruptedTimeSeries class with formula including control units
    • Visualize and interpret results
    • Add references section citing Juan's blog and Google paper
  • Update docs/source/notebooks/index.md to include the new notebook in ITS section
  • Add references to references.bib for Juan's blog and Google paper
  • Test the notebook runs correctly
  • Build documentation to verify integration
  • Address PR feedback (1st round):
    • Expand glossary entry for CITS with more detail
    • Add glossary references in notebook using {term} syntax
    • Add note about additional predictors (temperature, time of year) under "Key characteristics"
    • Replace markdown links with proper Sphinx citations (:cite:)
    • Execute notebook so outputs display in rendered docs
  • Address PR feedback (2nd round):
    • Fix pre-commit check failures (all checks now pass)
    • Remove campaign_end variable and from plot
    • Fix campaign start date to July 1, 2022 (was incorrectly May 2)
    • Update text with correct dates
    • Remove az.style.use("arviz-doc") line
  • Address PR feedback (3rd round):
    • Change section title to "Visualise data"
    • Add scatter plot of pre-treatment data (control vs treatment)
    • Add explanation about correlation between units
    • Update "When to Use" section with detailed comparisons and guidance
  • Address PR feedback (4th round):
    • Use Student T likelihood (nu=4) as in original blog post
    • Change title to "Comparative Interrupted Time Series: a geo-experimentation example"

All tasks completed successfully!

Original prompt

This section details on the original issue you should resolve

<issue_title>New docs example of Comparative Interrupted Time Series</issue_title>
<issue_description>* We can use the existing InterruptedTimeSeries class. But if we add in one (or more) control units as predictors then we essentially have Comparative Interrupted Time Series (CITS).

  • See @juanitorduz 's example blog post, which could serve as the basis for a new docs page. This could be done using the existing InterruptedTimeSeries class and the formula treated_scaled ~ 1 + control_scaled. Note: the blog post cites (and is partially based on the paper "Estimating Ad Effectiveness using Geo Experiments in a Time-Based Regression Framework" https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/45950.pdf)
  • Highlight the similarities and differences to regular interrupted time series (no control units in predictors) and also synthetic control (no sum to 1 constraint, can have intercept).
  • To be clear, when predictors are not control units, then we have regular ITS. When we have one of more control units in the predictor list then we have CITS.
  • An acceptable PR would add another docs page in the concise style of our existing docs, but focused on the example in @juanitorduz 's blog post. It should be concise and to the point, but also approachable and clear. It should emphasise use of the existing InterruptedTimeSeries class and educate the reader on the similarities and differences between ITS, CITS, and SC.
  • No changes to code or tests are required here.
  • Jaun is happy for this docs page to be based on his blog post. Data is available here https://github.com/juanitorduz/website_projects/blob/master/data/zipcodes_data.csv and the data generating process (code to generate the data) is here https://github.com/juanitorduz/website_projects/blob/master/Python/zipcode_data.py. But I don't think we need to look at this, we can just use the saved csv.
  • Maybe we want to port that csv file into CausalPy and add it into the data folder. We would in fact have to update load_data in datasets.py and we should add an attribution in the docstring with a link back to Jaun's blog post URL.
  • The new docs page should be added into the existing Interrupted Time Series section in the docs.
  • The title of the notebook should be "Geo-Experimentation with Comparative Interrupted Time Series". The introduction should obviously make clear that the example is based on Juan's blog post.</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Add documentation example for Comparative Interrupted Time Series Add Comparative Interrupted Time Series documentation with geo-experimentation example Dec 19, 2025
Copilot AI requested a review from drbenvincent December 19, 2025 16:18
@codecov
Copy link

codecov bot commented Dec 19, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.21%. Comparing base (dd7dfc4) to head (b5a2c17).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #595   +/-   ##
=======================================
  Coverage   93.21%   93.21%           
=======================================
  Files          35       35           
  Lines        5511     5511           
  Branches      358      358           
=======================================
  Hits         5137     5137           
  Misses        246      246           
  Partials      128      128           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Collaborator

@drbenvincent drbenvincent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have an entry in the glossary for Comparative interrupted time-series. But we should add a sphinx reference back to the glossary in the first mentions of the term in the notebook. We should also slightly expand that glossary description with a bit more detail.

Under "Key characteristics of CITS" add that additional predictors (like temperature or time of year) can also be added

None of the outputs in the notebook are displaying in the rendered docs html. Do you need me to manually execute the notebook? I can push the executed notebook if so.

- Expanded glossary entry for CITS with implementation details
- Added note about additional predictors (temperature, time of year)
- Replaced markdown links with proper Sphinx citations (:cite:)
- Added glossary term references using {term} syntax
- Executed notebook to display outputs in rendered docs

Co-authored-by: drbenvincent <[email protected]>
Copy link
Contributor Author

Copilot AI commented Dec 19, 2025

We already have an entry in the glossary for Comparative interrupted time-series. But we should add a sphinx reference back to the glossary in the first mentions of the term in the notebook. We should...

All addressed in commit a5f944c:

  1. ✅ Added glossary references using {term} syntax - first mention of CITS now links to glossary, plus ITS and Synthetic Control terms
  2. ✅ Expanded glossary entry with implementation details, formula syntax, and differences from Synthetic Control
  3. ✅ Added bullet point under "Key characteristics": "Additional predictors (like temperature, time of year, or other covariates) can also be included alongside control units"
  4. ✅ Notebook executed - all outputs now display in rendered docs (8 code cells with outputs, 2 plots visible)

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • docs.python.org
    • Triggering command: /home/REDACTED/.local/bin/sphinx-build sphinx-build -b html docs/source docs/_build lude (dns block)
  • docs.scipy.org
    • Triggering command: /home/REDACTED/.local/bin/sphinx-build sphinx-build -b html docs/source docs/_build lude (dns block)
  • docs.xarray.dev
    • Triggering command: /home/REDACTED/.local/bin/sphinx-build sphinx-build -b html docs/source docs/_build lude (dns block)
  • matplotlib.org
    • Triggering command: /home/REDACTED/.local/bin/sphinx-build sphinx-build -b html docs/source docs/_build lude (dns block)
  • numpy.org
    • Triggering command: /home/REDACTED/.local/bin/sphinx-build sphinx-build -b html docs/source docs/_build lude (dns block)
  • pandas.pydata.org
    • Triggering command: /home/REDACTED/.local/bin/sphinx-build sphinx-build -b html docs/source docs/_build lude (dns block)
  • python.arviz.org
    • Triggering command: /home/REDACTED/.local/bin/sphinx-build sphinx-build -b html docs/source docs/_build lude (dns block)
  • scikit-learn.org
    • Triggering command: /home/REDACTED/.local/bin/sphinx-build sphinx-build -b html docs/source docs/_build lude (dns block)
  • www.pymc.io
    • Triggering command: /home/REDACTED/.local/bin/sphinx-build sphinx-build -b html docs/source docs/_build lude (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copy link
Collaborator

@drbenvincent drbenvincent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pre-commit checks are failing. If you run the pre commit checks it should auto resolve some or all issues.

Referring back to Juan's blog post, there is no campaign_end. We should remove that variable, and from the plot.

And the start date of the campaign is wrong. In the original blog post it is listed as start_campaign = datetime(2022, 7, 1). Check correctness of dates in the text.

Remove the line az.style.use("arviz-doc")

- Updated campaign start date to July 1, 2022 (was incorrectly May 2)
- Updated text to reflect July 1-31, 2022 campaign period
- Removed campaign_end variable (not in original blog post)
- Removed campaign end line from visualization
- Removed az.style.use("arviz-doc") line
- Fixed formatting issues (pre-commit checks now pass)

Co-authored-by: drbenvincent <[email protected]>
Copy link
Contributor Author

Copilot AI commented Dec 19, 2025

pre-commit checks are failing. If you run the pre commit checks it should auto resolve some or all issues.

Referring back to Juan's blog post, there is no campaign_end. We should remove that variab...

All addressed in commit 3ed8d81:

  1. ✅ Pre-commit checks - all now pass (ruff format auto-fixed formatting)
  2. ✅ Removed campaign_end variable and corresponding line from plot
  3. ✅ Fixed campaign start date to July 1, 2022 (was incorrectly May 2)
  4. ✅ Updated text to reflect "July 1 to July 31, 2022" campaign period
  5. ✅ Removed az.style.use("arviz-doc") line

The notebook now correctly matches Juan's blog post with a July 1-31, 2022 campaign period.

Copy link
Collaborator

@drbenvincent drbenvincent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change the section from "Visualize Pre-Treatment Trends" to "Visualise data"

In that section, add a new scatter plot of just pre-treatment data. Control on the x axis, treatment on the y-axis. Add some explanation to point out the correlation of the two.

Please use the following text to update the end of the notebook, probably the "when to use CITS" section


Differences (why CITS is often preferred when feasible)

  1. Control for concurrent events
    • ITS: vulnerable if something else changes at the same time (e.g., a new guideline, coding change, economic shift).
    • CITS: the control series helps account for those shared shocks, improving internal validity.

  2. Core identifying assumption
    • ITS: assumes that, absent the intervention, the pre-intervention trend would have continued (and no other intervention affects the series at that time).
    • CITS: assumes that, absent the intervention, the treated and control would have followed similar trajectories (often framed as a “parallel trends” idea, but allowing rich pre-trends and seasonality).

  3. Data requirements
    • ITS: one series is enough.
    • CITS: needs a credible control series (and must check for spillovers/contamination).

  4. Failure modes
    • CITS can be biased if the control is poorly chosen (different underlying drivers), if the intervention indirectly affects the control (spillover), or if other changes affect treated and control differently.

When to use which
• Use ITS when a good control group/series does not exist, but you have many pre- and post-intervention observations and can argue no major coincident changes.
• Use CITS when you can identify a credible comparison series and want stronger protection against coincident events and secular trends.

- Changed section title from "Visualize Pre-Treatment Trends" to "Visualise data"
- Added scatter plot showing correlation between treatment and control in pre-treatment period
- Added explanation text highlighting the correlation between units
- Completely rewrote "When to Use CITS" section with detailed comparisons:
  - Differences between ITS and CITS (concurrent events, assumptions, data requirements, failure modes)
  - Clear guidance on when to use ITS vs CITS vs Synthetic Control
- Improved structure and clarity of key takeaways

Co-authored-by: drbenvincent <[email protected]>
Copy link
Contributor Author

Copilot AI commented Dec 19, 2025

change the section from "Visualize Pre-Treatment Trends" to "Visualise data"

In that section, add a new scatter plot of just pre-treatment data. Control on the x axis, treatment on the y-axis. Add so...

All addressed in commit a27ec36:

  1. ✅ Changed section title from "Visualize Pre-Treatment Trends" to "Visualise data"
  2. ✅ Added scatter plot showing pre-treatment correlation between control (x-axis) and treatment (y-axis) with correlation coefficient displayed
  3. ✅ Added explanatory text highlighting the correlation between units
  4. ✅ Completely rewrote "When to Use CITS" section with your provided content:
    • Differences between ITS and CITS (concurrent events, assumptions, data requirements, failure modes)
    • "When to Use Which Method" section with guidance on ITS, CITS, and Synthetic Control
  5. ✅ Pre-commit checks pass

The scatter plot shows strong correlation (r ≈ 0.976) between treatment and control in the pre-treatment period, supporting the use of CITS.

Copy link
Collaborator

@drbenvincent drbenvincent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original blog post used a Student T likelihood. We should also do that, and we can do that through the use of custom priors with the Prior class. There is probably an example in one of the other notebooks.

Thanks the notebook title to "Comparative Interrupted Time Series: a geo-experimentation example"

- Changed title to "Comparative Interrupted Time Series: a geo-experimentation example"
- Added import for Prior from pymc_extras.prior
- Updated LinearRegression model to use Student T likelihood (nu=4) matching original blog post
- Model now uses robust Student T distribution instead of Normal for observations
- Pre-commit checks pass, notebook executes successfully

Co-authored-by: drbenvincent <[email protected]>
Copy link
Contributor Author

Copilot AI commented Dec 19, 2025

The original blog post used a Student T likelihood. We should also do that, and we can do that through the use of custom priors with the Prior class. There is probably an example in one of the other...

Both addressed in commit 41346bf:

  1. ✅ Changed title to "Comparative Interrupted Time Series: a geo-experimentation example"
  2. ✅ Updated model to use Student T likelihood (nu=4) matching the original blog post
    • Added from pymc_extras.prior import Prior import
    • Modified LinearRegression model to use custom priors with StudentT distribution for y_hat
    • Uses robust Student T instead of Normal distribution for observations

The model now matches the approach from Juan's original blog post with Student T likelihood for more robust inference.

@drbenvincent
Copy link
Collaborator

Bear in mind I've pushed some commits to update and re-run the notebook

@drbenvincent
Copy link
Collaborator

bugbot run

@cursor
Copy link

cursor bot commented Dec 19, 2025

PR Summary

Add multiple CITS/geo-experimentation and ITS-related citations to docs/source/references.bib.

Written by Cursor Bugbot for commit 188e814. This will update automatically on new commits. Configure here.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no bugs!


Streamlined and clarified markdown explanations in the CITS notebook for improved readability and conciseness. Combined and reworded sections to better explain comparative interrupted time series, its implementation, assumptions, and practical guidance, while removing redundant bullet points and enhancing the overall narrative flow.
@drbenvincent drbenvincent added documentation Improvements or additions to documentation enhancement New feature or request labels Dec 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New docs example of Comparative Interrupted Time Series

2 participants