StataFlow 0.1.0__py3-none-any.whl
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.
- stataflow-0.1.0.dist-info/METADATA +203 -0
- stataflow-0.1.0.dist-info/RECORD +31 -0
- stataflow-0.1.0.dist-info/WHEEL +5 -0
- stataflow-0.1.0.dist-info/licenses/LICENSE +21 -0
- stataflow-0.1.0.dist-info/top_level.txt +1 -0
- statapy/__init__.py +74 -0
- statapy/compat/__init__.py +1 -0
- statapy/compat/stata/__init__.py +25 -0
- statapy/compat/stata/did.py +142 -0
- statapy/compat/stata/factor_variables.py +348 -0
- statapy/compat/stata/glm.py +108 -0
- statapy/compat/stata/hdfe.py +97 -0
- statapy/compat/stata/iv.py +96 -0
- statapy/compat/stata/linear.py +115 -0
- statapy/compat/stata/rdrobust.py +114 -0
- statapy/estimators/__init__.py +14 -0
- statapy/estimators/absorbing_ols.py +628 -0
- statapy/estimators/csdid.py +376 -0
- statapy/estimators/did_imputation.py +392 -0
- statapy/estimators/eventstudyinteract.py +318 -0
- statapy/estimators/fe.py +503 -0
- statapy/estimators/glm.py +656 -0
- statapy/estimators/iv.py +983 -0
- statapy/estimators/ols.py +603 -0
- statapy/estimators/ppmlhdfe.py +518 -0
- statapy/estimators/rdrobust.py +853 -0
- statapy/postestimation.py +169 -0
- statapy/results/__init__.py +5 -0
- statapy/results/result.py +211 -0
- statapy/stata_runner/__init__.py +5 -0
- statapy/stata_runner/runner.py +234 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: StataFlow
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Stata2Python: A Python econometrics toolkit aligned with Stata 17
|
|
5
|
+
Author-email: Zhenhao Fu <zhenhaofu2001@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/ZhenHaoFu810/StataFlow
|
|
8
|
+
Project-URL: Repository, https://github.com/ZhenHaoFu810/StataFlow
|
|
9
|
+
Project-URL: Issues, https://github.com/ZhenHaoFu810/StataFlow/issues
|
|
10
|
+
Keywords: econometrics,stata,regression,fixed-effects,panel-data
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: numpy>=1.24
|
|
23
|
+
Requires-Dist: pandas>=2.0
|
|
24
|
+
Requires-Dist: scipy>=1.10
|
|
25
|
+
Requires-Dist: pyyaml>=6.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
28
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# Stata2Python
|
|
32
|
+
|
|
33
|
+
Stata2Python (`statapy`) is a Python econometrics toolkit that reproduces Stata 17 estimation results with high precision. It provides both a **Stata-compatible command layer** (for researchers migrating from Stata) and a **native Python estimator layer** (for advanced users who want direct control).
|
|
34
|
+
|
|
35
|
+
## What you can do today
|
|
36
|
+
|
|
37
|
+
- Run Stata-style commands in Python: `regress`, `reghdfe`, `ivregress 2sls`, `logit`, `ppmlhdfe`, `did_imputation`, `csdid`, `rdrobust`, and more.
|
|
38
|
+
- Obtain coefficients, standard errors, t/z-statistics, p-values, and confidence intervals that are field-level verified against Stata 17.
|
|
39
|
+
- Work with high-dimensional fixed effects (HDFE), IV/2SLS, binary/count models, and DID/event-study estimators.
|
|
40
|
+
- Use Stata-style factor-variable syntax (`i.group##c.post`, `c.x1#c.x2`, `x1##x2`) and space-separated absorb strings directly in wrapper commands. Bare variables inside `#` / `##` are treated as continuous, matching common Stata usage.
|
|
41
|
+
|
|
42
|
+
## What is not yet supported
|
|
43
|
+
|
|
44
|
+
- **Multi-way clustering** — only single-cluster robust inference is available.
|
|
45
|
+
- **Direct post-estimation on wrapper returns** — the `compat.stata` wrappers return `ResultSchema` result objects. `predict` and `margins` are available on the core estimator layer only.
|
|
46
|
+
- **Full command surfaces for community commands** — `reghdfe`, `ivreghdfe`, `ppmlhdfe`, `did_imputation`, `eventstudyinteract`, `csdid`, and `rdrobust` are implemented as **verified high-frequency subsets**, not complete Stata command reproductions. Unsupported options are explicitly rejected rather than silently ignored.
|
|
47
|
+
|
|
48
|
+
### Completeness legend
|
|
49
|
+
|
|
50
|
+
- **Stable** — synthetic + real-data dual-run verified; core API is unlikely to change.
|
|
51
|
+
- **Alpha** — high-frequency paths are implemented and verified, but the command surface is still a subset of the full Stata community command.
|
|
52
|
+
- **Alpha — Partial** — a verifiable implementation exists, but large functional areas are still missing (e.g., fuzzy RD for `rdrobust`, multi-way clustering).
|
|
53
|
+
|
|
54
|
+
See the [Command Support Matrix](./docs/command-support-matrix/README.md) for the per-command detailed status.
|
|
55
|
+
For the public Stata-vs-Python evidence book, see [Validation Overview](./docs/validation/overview.md).
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install -e .
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Requirements: Python 3.10+, NumPy, pandas, SciPy.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Quick start
|
|
70
|
+
|
|
71
|
+
### Stata-compatible command layer (recommended)
|
|
72
|
+
|
|
73
|
+
All `compat.stata` wrappers return a `ResultSchema` object with coefficients, standard errors, and fit statistics. They do **not** expose `.predict()` or `.margins()` directly—use the core estimator layer below for post-estimation.
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import pandas as pd
|
|
77
|
+
from statapy.compat.stata import regress, reghdfe, ivregress_2sls, logit
|
|
78
|
+
|
|
79
|
+
# OLS with robust standard errors
|
|
80
|
+
result = regress(df, y="wage", x=["edu", "exper"], vce="robust")
|
|
81
|
+
|
|
82
|
+
# High-dimensional fixed effects (reghdfe)
|
|
83
|
+
result = reghdfe(
|
|
84
|
+
df, y="wage", x=["edu", "exper"],
|
|
85
|
+
absorb="firm_id year_id", vce="cluster", cluster="industry"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# Factor-variable syntax in HDFE
|
|
89
|
+
result = reghdfe(
|
|
90
|
+
df, y="wage", x=["i.industry##c.post"], absorb="firm_id year_id"
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# 2SLS
|
|
94
|
+
result = ivregress_2sls(
|
|
95
|
+
df, y="lwage", x_exog=["edu"], x_endog=["exper"],
|
|
96
|
+
instruments=["age", "kidslt6"], vce="robust"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# Logit
|
|
100
|
+
result = logit(df, y="inlf", x=["nwifeinc", "educ", "exper"])
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
For runnable examples, see the [`examples/`](./examples/) directory:
|
|
104
|
+
- [`examples/demo_regress.py`](./examples/demo_regress.py)
|
|
105
|
+
- [`examples/demo_reghdfe.py`](./examples/demo_reghdfe.py)
|
|
106
|
+
- [`examples/demo_ppmlhdfe.py`](./examples/demo_ppmlhdfe.py)
|
|
107
|
+
- [`examples/demo_ivregress_2sls.py`](./examples/demo_ivregress_2sls.py)
|
|
108
|
+
|
|
109
|
+
### Native Python estimator layer (advanced)
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from statapy import OLS, FixedEffectsOLS, AbsorbingOLS, Logit, IV2SLS
|
|
113
|
+
|
|
114
|
+
model = OLS(data=df, y="wage", x=["edu", "exper"])
|
|
115
|
+
result = model.fit(vce="robust")
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Supported commands
|
|
121
|
+
|
|
122
|
+
| Command | Python entry | Core capabilities |
|
|
123
|
+
|---------|--------------|-------------------|
|
|
124
|
+
| `regress` | `statapy.compat.stata.regress` | OLS, robust, cluster, aweight |
|
|
125
|
+
| `xtreg, fe` | `statapy.compat.stata.xtreg_fe` | Fixed effects (within), cluster |
|
|
126
|
+
| `areg` | `statapy.compat.stata.areg` | Single absorb variable FE |
|
|
127
|
+
| `reghdfe` | `statapy.compat.stata.reghdfe` | 1-2 group HDFE, cluster, singleton drop |
|
|
128
|
+
| `ivregress 2sls` | `statapy.compat.stata.ivregress_2sls` | 2SLS, robust, cluster |
|
|
129
|
+
| `ivreghdfe` | `statapy.compat.stata.ivreghdfe` | IV + 1-2 group HDFE, cluster |
|
|
130
|
+
| `logit` | `statapy.compat.stata.logit` | MLE, robust, cluster |
|
|
131
|
+
| `probit` | `statapy.compat.stata.probit` | MLE, robust, cluster |
|
|
132
|
+
| `poisson` | `statapy.compat.stata.poisson` | MLE, robust, cluster |
|
|
133
|
+
| `ppmlhdfe` | `statapy.compat.stata.ppmlhdfe` | PPML + 1-2 group HDFE |
|
|
134
|
+
| `did_imputation` | `statapy.compat.stata.did_imputation` | BJS DID imputation |
|
|
135
|
+
| `eventstudyinteract` | `statapy.compat.stata.eventstudyinteract` | Sun & Abraham IW estimator |
|
|
136
|
+
| `csdid` | `statapy.compat.stata.csdid` | Callaway-Sant'Anna DID (`method="reg"` only) |
|
|
137
|
+
| `rdrobust` | `statapy.compat.stata.rdrobust` | Sharp RD local polynomial (`bwselect="mserd"`, `covs`) |
|
|
138
|
+
|
|
139
|
+
Full details: [`docs/command-support-matrix/README.md`](./docs/command-support-matrix/README.md)
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Validation philosophy
|
|
144
|
+
|
|
145
|
+
Every public command is validated with **two lines of evidence**:
|
|
146
|
+
|
|
147
|
+
1. **Synthetic / controlled cases** — formula, degrees of freedom, sample screening, edge cases.
|
|
148
|
+
2. **Real public datasets** — field-level comparison against Stata 17 on openly available economic/financial data.
|
|
149
|
+
|
|
150
|
+
A command is considered "done" only when both lines pass and the source-to-Python mapping is documented. We do not accept "statistical equivalence" without explicit mathematical or source-code justification.
|
|
151
|
+
|
|
152
|
+
Public evidence entry points:
|
|
153
|
+
|
|
154
|
+
- [Validation Overview](./docs/validation/overview.md)
|
|
155
|
+
- [Evidence Matrix](./docs/validation/evidence-matrix.md)
|
|
156
|
+
- [Dataset Registry](./docs/validation/dataset-registry.md)
|
|
157
|
+
- [Validation Policy](./docs/validation/validation-policy.md)
|
|
158
|
+
|
|
159
|
+
### Running tests
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# Unit and integration tests (fast)
|
|
163
|
+
pytest tests/ -v --ignore=tests/golden/
|
|
164
|
+
|
|
165
|
+
# Golden dual-run tests (require Stata 17)
|
|
166
|
+
pytest tests/golden/ -v
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Project structure
|
|
172
|
+
|
|
173
|
+
- **`src/statapy/estimators/`** — Core Python estimators (`OLS`, `AbsorbingOLS`, `Logit`, `PPMLHDFE`, `DIDImputation`, etc.)
|
|
174
|
+
- **`src/statapy/compat/stata/`** — Stata command wrappers (`regress()`, `reghdfe()`, `ivregress_2sls()`, etc.)
|
|
175
|
+
- **`docs/research/`** — Source-to-Python mapping documents for community commands
|
|
176
|
+
- **`docs/command-support-matrix/`** — Per-command support matrices
|
|
177
|
+
- **`tests/golden/`** — Stata-Python dual-run tests
|
|
178
|
+
- **`research/vendor/stata_community/`** — Local mirrors of open-source Stata community packages (for research only)
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Default target version
|
|
183
|
+
|
|
184
|
+
**Stata 17**
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Documentation
|
|
189
|
+
|
|
190
|
+
- [Project charter](./docs/project-charter.md)
|
|
191
|
+
- [Architecture overview](./docs/architecture/overview.md)
|
|
192
|
+
- [Public API specification](./docs/architecture/public-api.md)
|
|
193
|
+
- [Command support matrices](./docs/command-support-matrix/README.md)
|
|
194
|
+
- [Validation overview](./docs/validation/overview.md)
|
|
195
|
+
- [Validation evidence matrix](./docs/validation/evidence-matrix.md)
|
|
196
|
+
- [Open-source roadmap](./docs/next-round-open-source-plan.md)
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Governance
|
|
201
|
+
|
|
202
|
+
- **Codex** — project goals, architecture, review gates, and statistical-dispute arbitration.
|
|
203
|
+
- **Claude Code** — implementation, testing, and evidence backfill.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
stataflow-0.1.0.dist-info/licenses/LICENSE,sha256=5TXa9okNO3fzbq7a1xXt3UDr9EuyTNubGoEVe5nZhkk,1067
|
|
2
|
+
statapy/__init__.py,sha256=YIF_oMVUROS6PkRMLaLvdFg8YIMwROacjZkHaqFyCyY,1282
|
|
3
|
+
statapy/postestimation.py,sha256=HTQIoQJwvgobb1XwVO1vbij1lDY-mOQ7AyOOA9E0qZI,5053
|
|
4
|
+
statapy/compat/__init__.py,sha256=adn0FmgFGTZACXQKTBps4GQfWOks5ArrWt8_-x3Upis,62
|
|
5
|
+
statapy/compat/stata/__init__.py,sha256=c_VSYmJa9XkEeBpMtIhYKiOvk1xjKLGVcub021ODxA4,553
|
|
6
|
+
statapy/compat/stata/did.py,sha256=LZq1JQZSBiCiwndG8MrP-vI0Mw4EDyQpa8GAIqA3Tbs,3715
|
|
7
|
+
statapy/compat/stata/factor_variables.py,sha256=Q77FJHxtKA01Qi0-PnFBfpatfJ2DUshjc38Q1G2zY9M,12848
|
|
8
|
+
statapy/compat/stata/glm.py,sha256=1ISOca1ep1FM0asIZkWKaw0DYyCrNR7pgvPPC7L2C0I,2507
|
|
9
|
+
statapy/compat/stata/hdfe.py,sha256=r16hKEYqoFeq3lgyrmv198IjnWHF0oFaYydTPSvn9Wc,2460
|
|
10
|
+
statapy/compat/stata/iv.py,sha256=GgV6PLExt-JZZjOb-OeISMgywVEKyFv338b_Yx8vN2c,2632
|
|
11
|
+
statapy/compat/stata/linear.py,sha256=IF4YlksLIoIVp4gz_YZx0Yj7U0wWGcwHvLQbwQJlvvc,2665
|
|
12
|
+
statapy/compat/stata/rdrobust.py,sha256=K2CoACF11_ewBFwPvXHwDAP164g90JoHtoWgzpbOPzY,2994
|
|
13
|
+
statapy/estimators/__init__.py,sha256=wRSG4eHCPBxh2QH2KhECmMqqv8Ai-1raqT_R89SqfpQ,562
|
|
14
|
+
statapy/estimators/absorbing_ols.py,sha256=sUhjhNr1eSNctu1l92OmXPRtuuJSqLENLoUv26feyyw,22634
|
|
15
|
+
statapy/estimators/csdid.py,sha256=zJ0aQircVG49apA3VdYyfObe3YQFdG55aDqR2jy5Pzs,13073
|
|
16
|
+
statapy/estimators/did_imputation.py,sha256=reomGLMozcj9NuwMu7_acT68FR0GPZK7v8gdCbrvQaI,13443
|
|
17
|
+
statapy/estimators/eventstudyinteract.py,sha256=EycYGLohKVm2KEVZY-TjWL7CEdvKn1Vmwd5h_7Ifpr0,11391
|
|
18
|
+
statapy/estimators/fe.py,sha256=Xje_lTi6-WyVGkVT2oYS1bEI4ukL0a8GHhT9sp8E5OA,18209
|
|
19
|
+
statapy/estimators/glm.py,sha256=6eucthcwzj8S-VybDjgE-m9sO72HVZNhBAg-YYtvU64,21966
|
|
20
|
+
statapy/estimators/iv.py,sha256=fTANtgAS9UklTmgf71Z0nGErGnekJYDwQVxBn_1uAXI,35461
|
|
21
|
+
statapy/estimators/ols.py,sha256=Bp361VmzDNCbgg4pp7EbYpl0PJzFB454ZLGglvrkdbA,21082
|
|
22
|
+
statapy/estimators/ppmlhdfe.py,sha256=H_zNTa1RIy2f_FJbyfweqn7QntYx_OcUecQ9RbYjm4U,19253
|
|
23
|
+
statapy/estimators/rdrobust.py,sha256=BL640j4u-aC7RfvWLnbh1hrXwT-iGT94er724Q0KvLM,29895
|
|
24
|
+
statapy/results/__init__.py,sha256=2SscS-GXX9jaBiAOGcYBY7HW2XgxkLKTTF2tq3RIrDM,129
|
|
25
|
+
statapy/results/result.py,sha256=-5iSo9QZcY43png0U8hB1sq8T_-nGJ2_iETn-Q9PYI4,6666
|
|
26
|
+
statapy/stata_runner/__init__.py,sha256=eT9p_rD-oLJhktoxCBAfgQqmIHeRtQoQQkZxxrjN2Pg,121
|
|
27
|
+
statapy/stata_runner/runner.py,sha256=FoSnGu2t71pMTBCVluaU-C-7EoMW8HMhIeEKHWo_ios,6893
|
|
28
|
+
stataflow-0.1.0.dist-info/METADATA,sha256=sSW9UTXZYpbxkWHnBiZU-QFhQCCEIXCyB0yrFLNY9Rc,8912
|
|
29
|
+
stataflow-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
30
|
+
stataflow-0.1.0.dist-info/top_level.txt,sha256=CTAQy1sKi_620Uyq2UtGJYax126Pr4USUG369LAXglM,8
|
|
31
|
+
stataflow-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zhenhao Fu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
statapy
|
statapy/__init__.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Stata2Python (statapy) — A Python econometrics toolkit aligned with Stata 17.
|
|
3
|
+
Provides a Stata-compatible command layer and native Python estimators,
|
|
4
|
+
with field-level dual-run verification.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
__version__ = "0.1.0"
|
|
8
|
+
|
|
9
|
+
# Core estimators (Python-native API)
|
|
10
|
+
from .estimators import (
|
|
11
|
+
OLS,
|
|
12
|
+
FixedEffectsOLS,
|
|
13
|
+
AbsorbingOLS,
|
|
14
|
+
IV2SLS,
|
|
15
|
+
IVAbsorbingOLS,
|
|
16
|
+
Logit,
|
|
17
|
+
Probit,
|
|
18
|
+
Poisson,
|
|
19
|
+
PPMLHDFE,
|
|
20
|
+
DIDImputation,
|
|
21
|
+
EventStudyInteract,
|
|
22
|
+
CSDID,
|
|
23
|
+
RDRobust,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# Stata compatibility commands
|
|
27
|
+
from .compat.stata import (
|
|
28
|
+
regress,
|
|
29
|
+
xtreg_fe,
|
|
30
|
+
areg,
|
|
31
|
+
reghdfe,
|
|
32
|
+
ivregress_2sls,
|
|
33
|
+
ivreghdfe,
|
|
34
|
+
logit,
|
|
35
|
+
probit,
|
|
36
|
+
poisson,
|
|
37
|
+
ppmlhdfe,
|
|
38
|
+
did_imputation,
|
|
39
|
+
eventstudyinteract,
|
|
40
|
+
csdid,
|
|
41
|
+
rdrobust,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
__all__ = [
|
|
45
|
+
# Core estimators
|
|
46
|
+
"OLS",
|
|
47
|
+
"FixedEffectsOLS",
|
|
48
|
+
"AbsorbingOLS",
|
|
49
|
+
"IV2SLS",
|
|
50
|
+
"IVAbsorbingOLS",
|
|
51
|
+
"Logit",
|
|
52
|
+
"Probit",
|
|
53
|
+
"Poisson",
|
|
54
|
+
"PPMLHDFE",
|
|
55
|
+
"DIDImputation",
|
|
56
|
+
"EventStudyInteract",
|
|
57
|
+
"CSDID",
|
|
58
|
+
"RDRobust",
|
|
59
|
+
# Stata compatibility commands
|
|
60
|
+
"regress",
|
|
61
|
+
"xtreg_fe",
|
|
62
|
+
"areg",
|
|
63
|
+
"reghdfe",
|
|
64
|
+
"ivregress_2sls",
|
|
65
|
+
"ivreghdfe",
|
|
66
|
+
"logit",
|
|
67
|
+
"probit",
|
|
68
|
+
"poisson",
|
|
69
|
+
"ppmlhdfe",
|
|
70
|
+
"did_imputation",
|
|
71
|
+
"eventstudyinteract",
|
|
72
|
+
"csdid",
|
|
73
|
+
"rdrobust",
|
|
74
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Compatibility layers for external statistical software."""
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Stata command compatibility layer for statapy."""
|
|
2
|
+
|
|
3
|
+
from .linear import regress, xtreg_fe, areg
|
|
4
|
+
from .hdfe import reghdfe, ppmlhdfe
|
|
5
|
+
from .iv import ivregress_2sls, ivreghdfe
|
|
6
|
+
from .glm import logit, probit, poisson
|
|
7
|
+
from .did import did_imputation, eventstudyinteract, csdid
|
|
8
|
+
from .rdrobust import rdrobust
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"regress",
|
|
12
|
+
"xtreg_fe",
|
|
13
|
+
"areg",
|
|
14
|
+
"reghdfe",
|
|
15
|
+
"ivregress_2sls",
|
|
16
|
+
"ivreghdfe",
|
|
17
|
+
"logit",
|
|
18
|
+
"probit",
|
|
19
|
+
"poisson",
|
|
20
|
+
"ppmlhdfe",
|
|
21
|
+
"did_imputation",
|
|
22
|
+
"eventstudyinteract",
|
|
23
|
+
"csdid",
|
|
24
|
+
"rdrobust",
|
|
25
|
+
]
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""Stata DID command wrappers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from statapy.estimators import DIDImputation, EventStudyInteract, CSDID
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def did_imputation(
|
|
11
|
+
data,
|
|
12
|
+
y: str,
|
|
13
|
+
id: str,
|
|
14
|
+
time: str,
|
|
15
|
+
first_treat: str,
|
|
16
|
+
*,
|
|
17
|
+
cluster: Optional[str] = None,
|
|
18
|
+
allhorizons: bool = False,
|
|
19
|
+
autosample: bool = False,
|
|
20
|
+
**kwargs,
|
|
21
|
+
) -> object:
|
|
22
|
+
"""
|
|
23
|
+
Stata-compatible wrapper for ``did_imputation``.
|
|
24
|
+
|
|
25
|
+
Maps to :class:`statapy.estimators.DIDImputation`.
|
|
26
|
+
"""
|
|
27
|
+
if kwargs:
|
|
28
|
+
raise ValueError(f"Unsupported arguments: {list(kwargs.keys())}")
|
|
29
|
+
|
|
30
|
+
model = DIDImputation(
|
|
31
|
+
data=data,
|
|
32
|
+
y=y,
|
|
33
|
+
id=id,
|
|
34
|
+
time=time,
|
|
35
|
+
first_treat=first_treat,
|
|
36
|
+
)
|
|
37
|
+
return model.fit(cluster=cluster, allhorizons=allhorizons, autosample=autosample)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def eventstudyinteract(
|
|
41
|
+
data,
|
|
42
|
+
y: str,
|
|
43
|
+
*,
|
|
44
|
+
cohort: str,
|
|
45
|
+
control_cohort: str,
|
|
46
|
+
absorb: list[str],
|
|
47
|
+
event_dummies: Optional[list[str]] = None,
|
|
48
|
+
time: Optional[str] = None,
|
|
49
|
+
first_treat: Optional[str] = None,
|
|
50
|
+
horizons: Optional[list[int]] = None,
|
|
51
|
+
omit: Optional[int] = None,
|
|
52
|
+
vce: str = "ols",
|
|
53
|
+
cluster: Optional[str] = None,
|
|
54
|
+
**kwargs,
|
|
55
|
+
) -> object:
|
|
56
|
+
"""
|
|
57
|
+
Stata-compatible wrapper for ``eventstudyinteract``.
|
|
58
|
+
|
|
59
|
+
Maps to :class:`statapy.estimators.EventStudyInteract`.
|
|
60
|
+
|
|
61
|
+
Parameters
|
|
62
|
+
----------
|
|
63
|
+
event_dummies : list[str], optional
|
|
64
|
+
Pre-generated relative-time dummy variable names. If provided,
|
|
65
|
+
``time``, ``first_treat``, and ``horizons`` are ignored.
|
|
66
|
+
time, first_treat, horizons, omit
|
|
67
|
+
Alternative auto-generation mode. The wrapper creates dummy
|
|
68
|
+
variables ``Dm{h}`` (for ``h < 0``), ``D0``, or ``Dp{h}``
|
|
69
|
+
(for ``h > 0``) on a copy of ``data``. The horizon ``omit``
|
|
70
|
+
is excluded as the reference category.
|
|
71
|
+
"""
|
|
72
|
+
if kwargs:
|
|
73
|
+
raise ValueError(f"Unsupported arguments: {list(kwargs.keys())}")
|
|
74
|
+
|
|
75
|
+
df = data.copy()
|
|
76
|
+
|
|
77
|
+
if event_dummies is not None:
|
|
78
|
+
used_event_dummies = list(event_dummies)
|
|
79
|
+
else:
|
|
80
|
+
if time is None or first_treat is None or horizons is None:
|
|
81
|
+
raise ValueError(
|
|
82
|
+
"Either event_dummies or (time, first_treat, horizons) must be provided."
|
|
83
|
+
)
|
|
84
|
+
if omit is not None and omit not in horizons:
|
|
85
|
+
raise ValueError("omit must be one of the horizons.")
|
|
86
|
+
|
|
87
|
+
used_event_dummies = []
|
|
88
|
+
rel_time = df[time] - df[first_treat]
|
|
89
|
+
rel_time = rel_time.where(df[first_treat] > 0, -1000)
|
|
90
|
+
|
|
91
|
+
for h in horizons:
|
|
92
|
+
if h == omit:
|
|
93
|
+
continue
|
|
94
|
+
if h < 0:
|
|
95
|
+
col = f"Dm{abs(h)}"
|
|
96
|
+
elif h == 0:
|
|
97
|
+
col = "D0"
|
|
98
|
+
else:
|
|
99
|
+
col = f"Dp{h}"
|
|
100
|
+
df[col] = (rel_time == h).astype(float)
|
|
101
|
+
used_event_dummies.append(col)
|
|
102
|
+
|
|
103
|
+
model = EventStudyInteract(
|
|
104
|
+
data=df,
|
|
105
|
+
y=y,
|
|
106
|
+
event_dummies=used_event_dummies,
|
|
107
|
+
cohort=cohort,
|
|
108
|
+
control_cohort=control_cohort,
|
|
109
|
+
absorb=absorb,
|
|
110
|
+
)
|
|
111
|
+
return model.fit(vce=vce, cluster=cluster)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def csdid(
|
|
115
|
+
data,
|
|
116
|
+
y: str,
|
|
117
|
+
id: str,
|
|
118
|
+
time: str,
|
|
119
|
+
first_treat: str,
|
|
120
|
+
*,
|
|
121
|
+
method: str = "reg",
|
|
122
|
+
vce: Optional[str] = None,
|
|
123
|
+
cluster: Optional[str] = None,
|
|
124
|
+
**kwargs,
|
|
125
|
+
) -> object:
|
|
126
|
+
"""
|
|
127
|
+
Stata-compatible wrapper for ``csdid``.
|
|
128
|
+
|
|
129
|
+
Maps to :class:`statapy.estimators.CSDID`.
|
|
130
|
+
"""
|
|
131
|
+
if kwargs:
|
|
132
|
+
raise ValueError(f"Unsupported arguments: {list(kwargs.keys())}")
|
|
133
|
+
|
|
134
|
+
model = CSDID(
|
|
135
|
+
data=data,
|
|
136
|
+
y=y,
|
|
137
|
+
id=id,
|
|
138
|
+
time=time,
|
|
139
|
+
first_treat=first_treat,
|
|
140
|
+
)
|
|
141
|
+
model.fit(method=method, vce=vce, cluster=cluster)
|
|
142
|
+
return model.estat_event()
|