Skip to content

Commit 6afe765

Browse files
authored
Merge pull request #49 from igerber/claude/prepare-v1.3.0-release-XmIcZ
2 parents 2afcde7 + 4a48f7e commit 6afe765

4 files changed

Lines changed: 151 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.3.0] - 2026-01-09
9+
10+
### Added
11+
- **Triple Difference (DDD) estimator** implementing Ortiz-Villavicencio & Sant'Anna (2025)
12+
- `TripleDifference` class for DDD designs where treatment requires two criteria (group AND partition)
13+
- `TripleDifferenceResults` dataclass with ATT, SEs, cell means, and diagnostics
14+
- `triple_difference()` convenience function for quick estimation
15+
- Three estimation methods: regression adjustment (`reg`), inverse probability weighting (`ipw`), and doubly robust (`dr`)
16+
- Proper covariate handling (unlike naive DDD implementations that difference two DiDs)
17+
- Propensity score trimming for IPW/DR methods
18+
- Cluster-robust standard errors support
19+
- Tutorial notebook: `docs/tutorials/08_triple_diff.ipynb`
20+
21+
**Reference**: Ortiz-Villavicencio, M., & Sant'Anna, P. H. C. (2025). "Better Understanding Triple Differences Estimators." *Working Paper*. [arXiv:2505.09942](https://arxiv.org/abs/2505.09942)
22+
823
## [1.2.1] - 2026-01-08
924

1025
### Added
@@ -248,6 +263,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
248263
- `to_dict()` and `to_dataframe()` export methods
249264
- `is_significant` and `significance_stars` properties
250265

266+
[1.3.0]: https://github.com/igerber/diff-diff/compare/v1.2.1...v1.3.0
251267
[1.2.1]: https://github.com/igerber/diff-diff/compare/v1.2.0...v1.2.1
252268
[1.2.0]: https://github.com/igerber/diff-diff/compare/v1.1.1...v1.2.0
253269
[1.1.1]: https://github.com/igerber/diff-diff/compare/v1.1.0...v1.1.1

docs/api/index.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Core estimator classes for DiD analysis:
1818
diff_diff.SyntheticDiD
1919
diff_diff.CallawaySantAnna
2020
diff_diff.SunAbraham
21+
diff_diff.TripleDifference
2122

2223
Results Classes
2324
---------------
@@ -37,6 +38,7 @@ Result containers returned by estimators:
3738
diff_diff.GroupTimeEffect
3839
diff_diff.SunAbrahamResults
3940
diff_diff.SABootstrapResults
41+
diff_diff.TripleDifferenceResults
4042

4143
Visualization
4244
-------------
@@ -177,6 +179,7 @@ Detailed documentation by module:
177179

178180
estimators
179181
staggered
182+
triple_diff
180183
results
181184
visualization
182185
diagnostics

docs/api/triple_diff.rst

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
Triple Difference (DDD)
2+
=======================
3+
4+
Triple Difference estimator for designs where treatment requires two criteria.
5+
6+
This module implements the methodology from Ortiz-Villavicencio & Sant'Anna (2025),
7+
which correctly handles covariate adjustment in DDD designs. Unlike naive implementations
8+
that difference two DiDs, this approach provides valid estimates when identification
9+
requires conditioning on covariates.
10+
11+
**When to use DDD instead of DiD:**
12+
13+
DDD allows for violations of parallel trends that are:
14+
15+
- Group-specific (e.g., economic shocks affecting treatment states)
16+
- Partition-specific (e.g., trends affecting women everywhere)
17+
18+
As long as these biases are additive, DDD differences them out. The key assumption
19+
is that the *differential* trend between eligible and ineligible units would be
20+
the same across groups.
21+
22+
**Reference:** Ortiz-Villavicencio, M., & Sant'Anna, P. H. C. (2025). Better Understanding
23+
Triple Differences Estimators. *Working Paper*. `arXiv:2505.09942 <https://arxiv.org/abs/2505.09942>`_
24+
25+
.. module:: diff_diff.triple_diff
26+
27+
TripleDifference
28+
----------------
29+
30+
Main estimator class for Triple Difference designs.
31+
32+
.. autoclass:: diff_diff.TripleDifference
33+
:members:
34+
:undoc-members:
35+
:show-inheritance:
36+
:inherited-members:
37+
38+
.. rubric:: Methods
39+
40+
.. autosummary::
41+
42+
~TripleDifference.fit
43+
~TripleDifference.get_params
44+
~TripleDifference.set_params
45+
46+
TripleDifferenceResults
47+
-----------------------
48+
49+
Results container for Triple Difference estimation.
50+
51+
.. autoclass:: diff_diff.TripleDifferenceResults
52+
:members:
53+
:undoc-members:
54+
:show-inheritance:
55+
56+
.. rubric:: Methods
57+
58+
.. autosummary::
59+
60+
~TripleDifferenceResults.summary
61+
~TripleDifferenceResults.print_summary
62+
~TripleDifferenceResults.to_dict
63+
~TripleDifferenceResults.to_dataframe
64+
65+
Convenience Function
66+
--------------------
67+
68+
.. autofunction:: diff_diff.triple_difference
69+
70+
Estimation Methods
71+
------------------
72+
73+
The estimator supports three estimation methods:
74+
75+
.. list-table::
76+
:header-rows: 1
77+
:widths: 15 35 50
78+
79+
* - Method
80+
- Description
81+
- When to use
82+
* - ``"dr"``
83+
- Doubly robust
84+
- Recommended. Consistent if either outcome or propensity model is correct
85+
* - ``"reg"``
86+
- Regression adjustment
87+
- Simple outcome regression with full interactions
88+
* - ``"ipw"``
89+
- Inverse probability weighting
90+
- When propensity score model is well-specified
91+
92+
Example Usage
93+
-------------
94+
95+
Basic usage::
96+
97+
from diff_diff import TripleDifference
98+
99+
ddd = TripleDifference(estimation_method='dr')
100+
results = ddd.fit(
101+
data,
102+
outcome='wages',
103+
group='policy_state', # 1=state enacted policy, 0=control state
104+
partition='female', # 1=women (affected by policy), 0=men
105+
time='post' # 1=post-policy, 0=pre-policy
106+
)
107+
results.print_summary()
108+
109+
With covariates::
110+
111+
results = ddd.fit(
112+
data,
113+
outcome='wages',
114+
group='policy_state',
115+
partition='female',
116+
time='post',
117+
covariates=['age', 'education', 'experience']
118+
)
119+
120+
Using the convenience function::
121+
122+
from diff_diff import triple_difference
123+
124+
results = triple_difference(
125+
data,
126+
outcome='wages',
127+
group='policy_state',
128+
partition='female',
129+
time='post',
130+
estimation_method='dr'
131+
)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "diff-diff"
7-
version = "1.2.1"
7+
version = "1.3.0"
88
description = "A library for Difference-in-Differences causal inference analysis"
99
readme = "README.md"
1010
license = "MIT"

0 commit comments

Comments
 (0)