diffindiff 2.5.1__tar.gz → 2.5.3__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.
- {diffindiff-2.5.1 → diffindiff-2.5.3}/PKG-INFO +9 -7
- {diffindiff-2.5.1 → diffindiff-2.5.3}/README.md +8 -6
- {diffindiff-2.5.1 → diffindiff-2.5.3}/diffindiff/config.py +3 -3
- {diffindiff-2.5.1 → diffindiff-2.5.3}/diffindiff/didanalysis.py +53 -12
- {diffindiff-2.5.1 → diffindiff-2.5.3}/diffindiff/didanalysis_helper.py +2 -2
- {diffindiff-2.5.1 → diffindiff-2.5.3}/diffindiff/diddata.py +58 -5
- {diffindiff-2.5.1 → diffindiff-2.5.3}/diffindiff/didtools.py +4 -4
- {diffindiff-2.5.1 → diffindiff-2.5.3}/diffindiff.egg-info/PKG-INFO +9 -7
- {diffindiff-2.5.1 → diffindiff-2.5.3}/setup.py +1 -1
- {diffindiff-2.5.1 → diffindiff-2.5.3}/MANIFEST.in +0 -0
- {diffindiff-2.5.1 → diffindiff-2.5.3}/diffindiff/__init__.py +0 -0
- {diffindiff-2.5.1 → diffindiff-2.5.3}/diffindiff/tests/__init__.py +0 -0
- {diffindiff-2.5.1 → diffindiff-2.5.3}/diffindiff/tests/data/Corona_Hesse.xlsx +0 -0
- {diffindiff-2.5.1 → diffindiff-2.5.3}/diffindiff/tests/data/counties_DE.csv +0 -0
- {diffindiff-2.5.1 → diffindiff-2.5.3}/diffindiff/tests/data/curfew_DE.csv +0 -0
- {diffindiff-2.5.1 → diffindiff-2.5.3}/diffindiff/tests/tests_diffindiff.py +0 -0
- {diffindiff-2.5.1 → diffindiff-2.5.3}/diffindiff.egg-info/SOURCES.txt +0 -0
- {diffindiff-2.5.1 → diffindiff-2.5.3}/diffindiff.egg-info/dependency_links.txt +0 -0
- {diffindiff-2.5.1 → diffindiff-2.5.3}/diffindiff.egg-info/requires.txt +0 -0
- {diffindiff-2.5.1 → diffindiff-2.5.3}/diffindiff.egg-info/top_level.txt +0 -0
- {diffindiff-2.5.1 → diffindiff-2.5.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: diffindiff
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.3
|
|
4
4
|
Summary: diffindiff: Python library for convenient Difference-in-Differences analyses
|
|
5
5
|
Author: Thomas Wieland
|
|
6
6
|
Author-email: geowieland@googlemail.com
|
|
@@ -22,14 +22,14 @@ Thomas Wieland [ORCID](https://orcid.org/0000-0001-5168-9846) [EMail](mailto:geo
|
|
|
22
22
|
- 💻 GitHub Repository: [diffindiff_official](https://github.com/geowieland/diffindiff_official)
|
|
23
23
|
- 📄 DOI (Zenodo): [10.5281/zenodo.18656820](https://doi.org/10.5281/zenodo.18656820)
|
|
24
24
|
|
|
25
|
-
A
|
|
25
|
+
A case study that utilizes the diffindiff library is available on [arXiv](https://arxiv.org/abs/2605.21464).
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
## Citation
|
|
29
29
|
|
|
30
30
|
If you use this software, please cite:
|
|
31
31
|
|
|
32
|
-
Wieland, T. (2026). diffindiff: A Python library for convenient difference-in-differences analyses (Version 2.5.
|
|
32
|
+
Wieland, T. (2026). diffindiff: A Python library for convenient difference-in-differences analyses (Version 2.5.3) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.18656820
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
## Installation
|
|
@@ -53,6 +53,7 @@ pip install git+https://github.com/geowieland/diffindiff_official.git
|
|
|
53
53
|
- Define custom treatment and control groups as well as treatment periods
|
|
54
54
|
- Create ready-to-fit DiD data objects
|
|
55
55
|
- Create predictive counterfactuals
|
|
56
|
+
- Create a synthetic control unit
|
|
56
57
|
- **DiD analysis**:
|
|
57
58
|
- Perform standard DiD analysis with pre-post data
|
|
58
59
|
- Perform DiD analysis with two-way fixed effects models
|
|
@@ -66,6 +67,7 @@ pip install git+https://github.com/geowieland/diffindiff_official.git
|
|
|
66
67
|
- Including after-treatment period
|
|
67
68
|
- Perform Triple Difference (DDD) analysis
|
|
68
69
|
- Perform DiD analysis with demeaned data
|
|
70
|
+
- Perform Synthetic DiD analysis
|
|
69
71
|
- **Diagnosis tools and extensions of analyses**:
|
|
70
72
|
- Add own counterfactuals or create counterfactuals based on machine learning or OLS regression models
|
|
71
73
|
- Bonferroni correction for treatment effects
|
|
@@ -177,9 +179,9 @@ See the /tests directory for usage examples of most of the included functions.
|
|
|
177
179
|
This software was developed without the use of AI-generated code. The Continue Agent in Microsoft Visual Studio Code using the GPT-5 mini model (by OpenAI) was used solely to assist in drafting and refining docstrings for documentation. The corresponding guidelines and constraints defined by the author are documented in `AGENTS-docstrings.md` in the [public GitHub repository](https://github.com/geowieland/diffindiff_official).
|
|
178
180
|
|
|
179
181
|
|
|
180
|
-
## What's new (v2.5.
|
|
182
|
+
## What's new (v2.5.3)
|
|
181
183
|
|
|
184
|
+
- Extensions
|
|
185
|
+
- Added optional saving of plots in DiffModel plot methods
|
|
182
186
|
- Bugfixes
|
|
183
|
-
-
|
|
184
|
-
- DiffModel.plot() nows supports pre-post designs with after-treatment period
|
|
185
|
-
- Some small stabilizations
|
|
187
|
+
- Fixed typos in messages
|
|
@@ -14,14 +14,14 @@ Thomas Wieland [ORCID](https://orcid.org/0000-0001-5168-9846) [EMail](mailto:geo
|
|
|
14
14
|
- 💻 GitHub Repository: [diffindiff_official](https://github.com/geowieland/diffindiff_official)
|
|
15
15
|
- 📄 DOI (Zenodo): [10.5281/zenodo.18656820](https://doi.org/10.5281/zenodo.18656820)
|
|
16
16
|
|
|
17
|
-
A
|
|
17
|
+
A case study that utilizes the diffindiff library is available on [arXiv](https://arxiv.org/abs/2605.21464).
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
## Citation
|
|
21
21
|
|
|
22
22
|
If you use this software, please cite:
|
|
23
23
|
|
|
24
|
-
Wieland, T. (2026). diffindiff: A Python library for convenient difference-in-differences analyses (Version 2.5.
|
|
24
|
+
Wieland, T. (2026). diffindiff: A Python library for convenient difference-in-differences analyses (Version 2.5.3) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.18656820
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
## Installation
|
|
@@ -45,6 +45,7 @@ pip install git+https://github.com/geowieland/diffindiff_official.git
|
|
|
45
45
|
- Define custom treatment and control groups as well as treatment periods
|
|
46
46
|
- Create ready-to-fit DiD data objects
|
|
47
47
|
- Create predictive counterfactuals
|
|
48
|
+
- Create a synthetic control unit
|
|
48
49
|
- **DiD analysis**:
|
|
49
50
|
- Perform standard DiD analysis with pre-post data
|
|
50
51
|
- Perform DiD analysis with two-way fixed effects models
|
|
@@ -58,6 +59,7 @@ pip install git+https://github.com/geowieland/diffindiff_official.git
|
|
|
58
59
|
- Including after-treatment period
|
|
59
60
|
- Perform Triple Difference (DDD) analysis
|
|
60
61
|
- Perform DiD analysis with demeaned data
|
|
62
|
+
- Perform Synthetic DiD analysis
|
|
61
63
|
- **Diagnosis tools and extensions of analyses**:
|
|
62
64
|
- Add own counterfactuals or create counterfactuals based on machine learning or OLS regression models
|
|
63
65
|
- Bonferroni correction for treatment effects
|
|
@@ -169,9 +171,9 @@ See the /tests directory for usage examples of most of the included functions.
|
|
|
169
171
|
This software was developed without the use of AI-generated code. The Continue Agent in Microsoft Visual Studio Code using the GPT-5 mini model (by OpenAI) was used solely to assist in drafting and refining docstrings for documentation. The corresponding guidelines and constraints defined by the author are documented in `AGENTS-docstrings.md` in the [public GitHub repository](https://github.com/geowieland/diffindiff_official).
|
|
170
172
|
|
|
171
173
|
|
|
172
|
-
## What's new (v2.5.
|
|
174
|
+
## What's new (v2.5.3)
|
|
173
175
|
|
|
176
|
+
- Extensions
|
|
177
|
+
- Added optional saving of plots in DiffModel plot methods
|
|
174
178
|
- Bugfixes
|
|
175
|
-
-
|
|
176
|
-
- DiffModel.plot() nows supports pre-post designs with after-treatment period
|
|
177
|
-
- Some small stabilizations
|
|
179
|
+
- Fixed typos in messages
|
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
# Author: Thomas Wieland
|
|
5
5
|
# ORCID: 0000-0001-5168-9846
|
|
6
6
|
# mail: geowieland@googlemail.com
|
|
7
|
-
# Version: 1.0.
|
|
8
|
-
# Last update: 2026-07-
|
|
7
|
+
# Version: 1.0.24
|
|
8
|
+
# Last update: 2026-07-25 12:31
|
|
9
9
|
# Copyright (c) 2025-2026 Thomas Wieland
|
|
10
10
|
#-----------------------------------------------------------------------
|
|
11
11
|
|
|
12
12
|
# Basic config:
|
|
13
13
|
|
|
14
14
|
PACKAGE_NAME = "diffindiff"
|
|
15
|
-
PACKAGE_VERSION = "2.5.
|
|
15
|
+
PACKAGE_VERSION = "2.5.3"
|
|
16
16
|
|
|
17
17
|
VERBOSE = False
|
|
18
18
|
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
# Author: Thomas Wieland
|
|
5
5
|
# ORCID: 0000-0001-5168-9846
|
|
6
6
|
# mail: geowieland@googlemail.com
|
|
7
|
-
# Version: 2.4.
|
|
8
|
-
# Last update: 2026-07-
|
|
7
|
+
# Version: 2.4.4
|
|
8
|
+
# Last update: 2026-07-23 19:42
|
|
9
9
|
# Copyright (c) 2024-2026 Thomas Wieland
|
|
10
10
|
#-----------------------------------------------------------------------
|
|
11
11
|
|
|
@@ -782,7 +782,7 @@ class DiffModel:
|
|
|
782
782
|
|
|
783
783
|
if len(no_control_conditions) > 0:
|
|
784
784
|
if len(no_control_conditions) == 1:
|
|
785
|
-
print(f"NOTE: Treatment {no_control_conditions[0]} has no control conditions.")
|
|
785
|
+
print(f"NOTE: Treatment '{no_control_conditions[0]}' has no control conditions.")
|
|
786
786
|
else:
|
|
787
787
|
print(f"NOTE: Treatments {', '.join(no_control_conditions)} have no control conditions.")
|
|
788
788
|
|
|
@@ -829,7 +829,9 @@ class DiffModel:
|
|
|
829
829
|
plot_size: list = [7, 6],
|
|
830
830
|
scale_plot: bool = True,
|
|
831
831
|
show_central_tendency: bool = False,
|
|
832
|
-
central_tendency: str = "mean"
|
|
832
|
+
central_tendency: str = "mean",
|
|
833
|
+
save_fig: str = None,
|
|
834
|
+
save_fig_kwargs: dict = {}
|
|
833
835
|
):
|
|
834
836
|
|
|
835
837
|
"""
|
|
@@ -869,6 +871,10 @@ class DiffModel:
|
|
|
869
871
|
Show mean/median line for estimates. Default is False.
|
|
870
872
|
central_tendency : str, optional
|
|
871
873
|
'mean' or 'median' for central tendency if shown. Default is 'mean'.
|
|
874
|
+
save_fig : str, optional
|
|
875
|
+
If not none, filename of plot to be saved.
|
|
876
|
+
save_fig_kwargs : dict, optional
|
|
877
|
+
Optional arguments for plt.savefig() if save_fig is not None.
|
|
872
878
|
|
|
873
879
|
Returns
|
|
874
880
|
-------
|
|
@@ -1006,6 +1012,9 @@ class DiffModel:
|
|
|
1006
1012
|
if plot_grid:
|
|
1007
1013
|
plt.grid(True)
|
|
1008
1014
|
|
|
1015
|
+
if save_fig is not None and isinstance(save_fig, str):
|
|
1016
|
+
plt.savefig(save_fig, **save_fig_kwargs)
|
|
1017
|
+
|
|
1009
1018
|
plt.show()
|
|
1010
1019
|
|
|
1011
1020
|
return self
|
|
@@ -1422,10 +1431,15 @@ class DiffModel:
|
|
|
1422
1431
|
model_data_c[time_col] = pd.to_datetime(model_data_c[time_col])
|
|
1423
1432
|
model_data_c[unit_col] = model_data_c[unit_col].astype(str)
|
|
1424
1433
|
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1434
|
+
if control_group_N < 2:
|
|
1435
|
+
print(f"WARNING: Model includes one control unit only: '{control_group[0]}'. Placebo analysis requires size of control group >1. Original model is returned.")
|
|
1436
|
+
return self
|
|
1437
|
+
|
|
1438
|
+
else:
|
|
1439
|
+
units_random_sample = model_data_c[unit_col].sample(
|
|
1440
|
+
n = int(round(divide*control_group_N*resample, 0)),
|
|
1441
|
+
random_state = random_state
|
|
1442
|
+
).astype(str).tolist()
|
|
1429
1443
|
|
|
1430
1444
|
model_data_c[TG_col_] = 0
|
|
1431
1445
|
model_data_c.loc[(model_data_c[unit_col].isin(units_random_sample)), TG_col_] = 1
|
|
@@ -1468,7 +1482,9 @@ class DiffModel:
|
|
|
1468
1482
|
y_lim = None,
|
|
1469
1483
|
plot_title: str = "Treatment time",
|
|
1470
1484
|
plot_symbol: str = "o",
|
|
1471
|
-
treatment_group_only: bool = True
|
|
1485
|
+
treatment_group_only: bool = True,
|
|
1486
|
+
save_fig: str = None,
|
|
1487
|
+
save_fig_kwargs: dict = {}
|
|
1472
1488
|
):
|
|
1473
1489
|
|
|
1474
1490
|
"""
|
|
@@ -1492,6 +1508,10 @@ class DiffModel:
|
|
|
1492
1508
|
Symbol used for treatment timing points. Default is 'o'.
|
|
1493
1509
|
treatment_group_only : bool, optional
|
|
1494
1510
|
If True, only plot treated units.
|
|
1511
|
+
save_fig : str, optional
|
|
1512
|
+
If not none, filename of plot to be saved.
|
|
1513
|
+
save_fig_kwargs : dict, optional
|
|
1514
|
+
Optional arguments for plt.savefig() if save_fig is not None.
|
|
1495
1515
|
|
|
1496
1516
|
Returns
|
|
1497
1517
|
-------
|
|
@@ -1565,6 +1585,9 @@ class DiffModel:
|
|
|
1565
1585
|
|
|
1566
1586
|
if y_lim is not None:
|
|
1567
1587
|
ax.set_ylim(y_lim)
|
|
1588
|
+
|
|
1589
|
+
if save_fig is not None and isinstance(save_fig, str):
|
|
1590
|
+
plt.savefig(save_fig, **save_fig_kwargs)
|
|
1568
1591
|
|
|
1569
1592
|
plt.show()
|
|
1570
1593
|
|
|
@@ -1590,7 +1613,9 @@ class DiffModel:
|
|
|
1590
1613
|
pre_post_ticks: list = ["Pre", "Post"],
|
|
1591
1614
|
pre_post_barplot = False,
|
|
1592
1615
|
pre_post_bar_width = 0.5,
|
|
1593
|
-
retransform_log_outcome: bool = False
|
|
1616
|
+
retransform_log_outcome: bool = False,
|
|
1617
|
+
save_fig: str = None,
|
|
1618
|
+
save_fig_kwargs: dict = {}
|
|
1594
1619
|
):
|
|
1595
1620
|
|
|
1596
1621
|
"""
|
|
@@ -1637,6 +1662,10 @@ class DiffModel:
|
|
|
1637
1662
|
retransform_log_outcome : bool, optional
|
|
1638
1663
|
If outcome was log-transformed, retransform to original scale for plotting.
|
|
1639
1664
|
Default is False.
|
|
1665
|
+
save_fig : str, optional
|
|
1666
|
+
If not none, filename of plot to be saved.
|
|
1667
|
+
save_fig_kwargs : dict, optional
|
|
1668
|
+
Optional arguments for plt.savefig() if save_fig is not None.
|
|
1640
1669
|
|
|
1641
1670
|
Returns
|
|
1642
1671
|
-------
|
|
@@ -2039,7 +2068,10 @@ class DiffModel:
|
|
|
2039
2068
|
|
|
2040
2069
|
if y_lim is not None:
|
|
2041
2070
|
ax.set_ylim(y_lim)
|
|
2042
|
-
|
|
2071
|
+
|
|
2072
|
+
if save_fig is not None and isinstance(save_fig, str):
|
|
2073
|
+
plt.savefig(save_fig, **save_fig_kwargs)
|
|
2074
|
+
|
|
2043
2075
|
plt.show()
|
|
2044
2076
|
|
|
2045
2077
|
return model_data_TG_CG
|
|
@@ -2058,7 +2090,9 @@ class DiffModel:
|
|
|
2058
2090
|
plot_legend: bool = True,
|
|
2059
2091
|
plot_grid: bool = True,
|
|
2060
2092
|
plot_size: list = [12, 6],
|
|
2061
|
-
retransform_log_outcome: bool = False
|
|
2093
|
+
retransform_log_outcome: bool = False,
|
|
2094
|
+
save_fig: str = None,
|
|
2095
|
+
save_fig_kwargs: dict = {}
|
|
2062
2096
|
):
|
|
2063
2097
|
|
|
2064
2098
|
"""
|
|
@@ -2093,6 +2127,10 @@ class DiffModel:
|
|
|
2093
2127
|
retransform_log_outcome : bool, optional
|
|
2094
2128
|
If outcome was log-transformed, retransform to original scale for plotting.
|
|
2095
2129
|
Default is False.
|
|
2130
|
+
save_fig : str, optional
|
|
2131
|
+
If not none, filename of plot to be saved.
|
|
2132
|
+
save_fig_kwargs : dict, optional
|
|
2133
|
+
Optional arguments for plt.savefig() if save_fig is not None.
|
|
2096
2134
|
|
|
2097
2135
|
Returns
|
|
2098
2136
|
-------
|
|
@@ -2222,6 +2260,9 @@ class DiffModel:
|
|
|
2222
2260
|
|
|
2223
2261
|
if y_lim is not None:
|
|
2224
2262
|
ax.set_ylim(y_lim)
|
|
2263
|
+
|
|
2264
|
+
if save_fig is not None and isinstance(save_fig, str):
|
|
2265
|
+
plt.savefig(save_fig, **save_fig_kwargs)
|
|
2225
2266
|
|
|
2226
2267
|
plt.show()
|
|
2227
2268
|
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
# Author: Thomas Wieland
|
|
5
5
|
# ORCID: 0000-0001-5168-9846
|
|
6
6
|
# mail: geowieland@googlemail.com
|
|
7
|
-
# Version: 1.2.
|
|
8
|
-
# Last update: 2026-07-
|
|
7
|
+
# Version: 1.2.3
|
|
8
|
+
# Last update: 2026-07-14 19:44
|
|
9
9
|
# Copyright (c) 2025-2026 Thomas Wieland
|
|
10
10
|
#-----------------------------------------------------------------------
|
|
11
11
|
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
# Author: Thomas Wieland
|
|
5
5
|
# ORCID: 0000-0001-5168-9846
|
|
6
6
|
# mail: geowieland@googlemail.com
|
|
7
|
-
# Version: 2.3.
|
|
8
|
-
# Last update: 2026-07-
|
|
7
|
+
# Version: 2.3.2
|
|
8
|
+
# Last update: 2026-07-16 18:52
|
|
9
9
|
# Copyright (c) 2024-2026 Thomas Wieland
|
|
10
10
|
#-----------------------------------------------------------------------
|
|
11
11
|
|
|
@@ -815,7 +815,8 @@ class DiffData:
|
|
|
815
815
|
unit_time_col_original,
|
|
816
816
|
covariates,
|
|
817
817
|
treatment_cols,
|
|
818
|
-
timestamp
|
|
818
|
+
timestamp,
|
|
819
|
+
synthetic_control
|
|
819
820
|
):
|
|
820
821
|
|
|
821
822
|
"""
|
|
@@ -840,6 +841,8 @@ class DiffData:
|
|
|
840
841
|
Mapping of treatment columns metadata.
|
|
841
842
|
timestamp : dict
|
|
842
843
|
Timestamp metadata.
|
|
844
|
+
synthetic_control : dict
|
|
845
|
+
If included, data for a synthetic control unit, else None.
|
|
843
846
|
Returns
|
|
844
847
|
-------
|
|
845
848
|
None
|
|
@@ -855,7 +858,8 @@ class DiffData:
|
|
|
855
858
|
unit_time_col_original,
|
|
856
859
|
covariates,
|
|
857
860
|
treatment_cols,
|
|
858
|
-
timestamp
|
|
861
|
+
timestamp,
|
|
862
|
+
synthetic_control
|
|
859
863
|
]
|
|
860
864
|
|
|
861
865
|
def get_did_modeldata_df (self):
|
|
@@ -1060,6 +1064,46 @@ class DiffData:
|
|
|
1060
1064
|
"""
|
|
1061
1065
|
|
|
1062
1066
|
return self.data[7]
|
|
1067
|
+
|
|
1068
|
+
def get_synthetic_control_weightings(self):
|
|
1069
|
+
|
|
1070
|
+
"""
|
|
1071
|
+
Return weightings of the synthetic control unit (if included in the DiffData object).
|
|
1072
|
+
|
|
1073
|
+
Returns
|
|
1074
|
+
-------
|
|
1075
|
+
pandas.DataFrame
|
|
1076
|
+
Weighting by control unit.
|
|
1077
|
+
|
|
1078
|
+
Examples
|
|
1079
|
+
--------
|
|
1080
|
+
>>> my_diffdata.get_synthetic_control_weightings()
|
|
1081
|
+
"""
|
|
1082
|
+
|
|
1083
|
+
if len(self.data[8]) > 0:
|
|
1084
|
+
return self.data[8]["weights"]
|
|
1085
|
+
else:
|
|
1086
|
+
print("The DiffData object does not include a synthetic control unit.")
|
|
1087
|
+
|
|
1088
|
+
def get_synthetic_control_fitmetrics(self):
|
|
1089
|
+
|
|
1090
|
+
"""
|
|
1091
|
+
Return fit metrics of the synthetic control unit (if included in the DiffData object).
|
|
1092
|
+
|
|
1093
|
+
Returns
|
|
1094
|
+
-------
|
|
1095
|
+
list
|
|
1096
|
+
Fit metrics (dict) and data points with residuals (pandas.DataFrame).
|
|
1097
|
+
|
|
1098
|
+
Examples
|
|
1099
|
+
--------
|
|
1100
|
+
>>> my_diffdata.get_synthetic_control_fitmetrics()
|
|
1101
|
+
"""
|
|
1102
|
+
|
|
1103
|
+
if len(self.data[8]) > 0:
|
|
1104
|
+
return self.data[8]["fit_metrics"]
|
|
1105
|
+
else:
|
|
1106
|
+
print("The DiffData object does not include a synthetic control unit.")
|
|
1063
1107
|
|
|
1064
1108
|
def add_covariates(
|
|
1065
1109
|
self,
|
|
@@ -2033,6 +2077,14 @@ class DiffData:
|
|
|
2033
2077
|
verbose = False
|
|
2034
2078
|
)
|
|
2035
2079
|
|
|
2080
|
+
self.data[7] = helper.create_timestamp(function="add_synthetic")
|
|
2081
|
+
|
|
2082
|
+
self.data[8] = {
|
|
2083
|
+
"weights": weights_pd,
|
|
2084
|
+
"fit_metrics": synthetic_fit_metrics,
|
|
2085
|
+
"process_unit": process_unit
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2036
2088
|
return self
|
|
2037
2089
|
|
|
2038
2090
|
def summary(self):
|
|
@@ -2489,7 +2541,8 @@ def merge_data(
|
|
|
2489
2541
|
unit_time_col_original,
|
|
2490
2542
|
[],
|
|
2491
2543
|
treatment_cols,
|
|
2492
|
-
timestamp
|
|
2544
|
+
timestamp,
|
|
2545
|
+
{}
|
|
2493
2546
|
)
|
|
2494
2547
|
|
|
2495
2548
|
if verbose:
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
# Author: Thomas Wieland
|
|
5
5
|
# ORCID: 0000-0001-5168-9846
|
|
6
6
|
# mail: geowieland@googlemail.com
|
|
7
|
-
# Version: 2.2.
|
|
8
|
-
# Last update: 2026-
|
|
7
|
+
# Version: 2.2.5
|
|
8
|
+
# Last update: 2026-07-23 19:34
|
|
9
9
|
# Copyright (c) 2025-2026 Thomas Wieland
|
|
10
10
|
#-----------------------------------------------------------------------
|
|
11
11
|
|
|
@@ -540,10 +540,10 @@ def is_simultaneous(
|
|
|
540
540
|
print("OK")
|
|
541
541
|
|
|
542
542
|
if not simultaneous and data_isnotreatment[0]:
|
|
543
|
-
print(f"NOTE:
|
|
543
|
+
print(f"NOTE: Treatment '{treatment_col}' is not simultaneous.")
|
|
544
544
|
|
|
545
545
|
if simultaneous and not data_isnotreatment[0]:
|
|
546
|
-
print(f"WARNING:
|
|
546
|
+
print(f"WARNING: Treatment '{treatment_col}' is simultaneous and does not include a {config.NO_TREATMENT_CG_DESCRIPTION}")
|
|
547
547
|
|
|
548
548
|
return simultaneous
|
|
549
549
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: diffindiff
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.3
|
|
4
4
|
Summary: diffindiff: Python library for convenient Difference-in-Differences analyses
|
|
5
5
|
Author: Thomas Wieland
|
|
6
6
|
Author-email: geowieland@googlemail.com
|
|
@@ -22,14 +22,14 @@ Thomas Wieland [ORCID](https://orcid.org/0000-0001-5168-9846) [EMail](mailto:geo
|
|
|
22
22
|
- 💻 GitHub Repository: [diffindiff_official](https://github.com/geowieland/diffindiff_official)
|
|
23
23
|
- 📄 DOI (Zenodo): [10.5281/zenodo.18656820](https://doi.org/10.5281/zenodo.18656820)
|
|
24
24
|
|
|
25
|
-
A
|
|
25
|
+
A case study that utilizes the diffindiff library is available on [arXiv](https://arxiv.org/abs/2605.21464).
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
## Citation
|
|
29
29
|
|
|
30
30
|
If you use this software, please cite:
|
|
31
31
|
|
|
32
|
-
Wieland, T. (2026). diffindiff: A Python library for convenient difference-in-differences analyses (Version 2.5.
|
|
32
|
+
Wieland, T. (2026). diffindiff: A Python library for convenient difference-in-differences analyses (Version 2.5.3) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.18656820
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
## Installation
|
|
@@ -53,6 +53,7 @@ pip install git+https://github.com/geowieland/diffindiff_official.git
|
|
|
53
53
|
- Define custom treatment and control groups as well as treatment periods
|
|
54
54
|
- Create ready-to-fit DiD data objects
|
|
55
55
|
- Create predictive counterfactuals
|
|
56
|
+
- Create a synthetic control unit
|
|
56
57
|
- **DiD analysis**:
|
|
57
58
|
- Perform standard DiD analysis with pre-post data
|
|
58
59
|
- Perform DiD analysis with two-way fixed effects models
|
|
@@ -66,6 +67,7 @@ pip install git+https://github.com/geowieland/diffindiff_official.git
|
|
|
66
67
|
- Including after-treatment period
|
|
67
68
|
- Perform Triple Difference (DDD) analysis
|
|
68
69
|
- Perform DiD analysis with demeaned data
|
|
70
|
+
- Perform Synthetic DiD analysis
|
|
69
71
|
- **Diagnosis tools and extensions of analyses**:
|
|
70
72
|
- Add own counterfactuals or create counterfactuals based on machine learning or OLS regression models
|
|
71
73
|
- Bonferroni correction for treatment effects
|
|
@@ -177,9 +179,9 @@ See the /tests directory for usage examples of most of the included functions.
|
|
|
177
179
|
This software was developed without the use of AI-generated code. The Continue Agent in Microsoft Visual Studio Code using the GPT-5 mini model (by OpenAI) was used solely to assist in drafting and refining docstrings for documentation. The corresponding guidelines and constraints defined by the author are documented in `AGENTS-docstrings.md` in the [public GitHub repository](https://github.com/geowieland/diffindiff_official).
|
|
178
180
|
|
|
179
181
|
|
|
180
|
-
## What's new (v2.5.
|
|
182
|
+
## What's new (v2.5.3)
|
|
181
183
|
|
|
184
|
+
- Extensions
|
|
185
|
+
- Added optional saving of plots in DiffModel plot methods
|
|
182
186
|
- Bugfixes
|
|
183
|
-
-
|
|
184
|
-
- DiffModel.plot() nows supports pre-post designs with after-treatment period
|
|
185
|
-
- Some small stabilizations
|
|
187
|
+
- Fixed typos in messages
|
|
@@ -7,7 +7,7 @@ def read_README():
|
|
|
7
7
|
|
|
8
8
|
setup(
|
|
9
9
|
name='diffindiff',
|
|
10
|
-
version='2.5.
|
|
10
|
+
version='2.5.3',
|
|
11
11
|
description='diffindiff: Python library for convenient Difference-in-Differences analyses',
|
|
12
12
|
packages=find_packages(include=["diffindiff", "diffindiff.tests"]),
|
|
13
13
|
include_package_data=True,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|