scspill 0.1.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.
- scspill-0.1.0/LICENSE +21 -0
- scspill-0.1.0/PKG-INFO +151 -0
- scspill-0.1.0/README.md +116 -0
- scspill-0.1.0/pyproject.toml +136 -0
- scspill-0.1.0/scspill/__init__.py +82 -0
- scspill-0.1.0/scspill/config_models.py +589 -0
- scspill-0.1.0/scspill/data/__init__.py +286 -0
- scspill-0.1.0/scspill/data/files/california_W_matrix.csv +39 -0
- scspill-0.1.0/scspill/data/files/california_panel.csv +1210 -0
- scspill-0.1.0/scspill/data/files/california_w_vector.csv +39 -0
- scspill-0.1.0/scspill/data/files/sudan_W_matrix.csv +34 -0
- scspill-0.1.0/scspill/data/files/sudan_panel.csv +545 -0
- scspill-0.1.0/scspill/data/files/sudan_w_vector.csv +34 -0
- scspill-0.1.0/scspill/estimators/__init__.py +1 -0
- scspill-0.1.0/scspill/estimators/scspill.py +222 -0
- scspill-0.1.0/scspill/exceptions.py +25 -0
- scspill-0.1.0/scspill/py.typed +0 -0
- scspill-0.1.0/scspill/simulate/__init__.py +33 -0
- scspill-0.1.0/scspill/simulate/dgp.py +302 -0
- scspill-0.1.0/scspill/simulate/runner.py +309 -0
- scspill-0.1.0/scspill/simulate/summary.py +198 -0
- scspill-0.1.0/scspill/utils/__init__.py +1 -0
- scspill-0.1.0/scspill/utils/datautils.py +55 -0
- scspill-0.1.0/scspill/utils/effectutils.py +58 -0
- scspill-0.1.0/scspill/utils/fitutils.py +44 -0
- scspill-0.1.0/scspill/utils/plotting.py +410 -0
- scspill-0.1.0/scspill/utils/results_helpers.py +256 -0
- scspill-0.1.0/scspill/utils/scspill_helpers/__init__.py +6 -0
- scspill-0.1.0/scspill/utils/scspill_helpers/_kernels.py +514 -0
- scspill-0.1.0/scspill/utils/scspill_helpers/config.py +177 -0
- scspill-0.1.0/scspill/utils/scspill_helpers/diagnostics.py +196 -0
- scspill-0.1.0/scspill/utils/scspill_helpers/effects.py +385 -0
- scspill-0.1.0/scspill/utils/scspill_helpers/inference.py +64 -0
- scspill-0.1.0/scspill/utils/scspill_helpers/numba_kernels.py +81 -0
- scspill-0.1.0/scspill/utils/scspill_helpers/pipeline.py +140 -0
- scspill-0.1.0/scspill/utils/scspill_helpers/plotter.py +258 -0
- scspill-0.1.0/scspill/utils/scspill_helpers/sampler_alpha.py +125 -0
- scspill-0.1.0/scspill/utils/scspill_helpers/sampler_sar.py +565 -0
- scspill-0.1.0/scspill/utils/scspill_helpers/scm_baseline.py +131 -0
- scspill-0.1.0/scspill/utils/scspill_helpers/setup.py +280 -0
- scspill-0.1.0/scspill/utils/scspill_helpers/structures.py +452 -0
- scspill-0.1.0/scspill/validation/__init__.py +52 -0
- scspill-0.1.0/scspill/validation/geweke.py +374 -0
- scspill-0.1.0/scspill/validation/kernels.py +440 -0
- scspill-0.1.0/scspill/validation/plotter.py +102 -0
- scspill-0.1.0/scspill/validation/robustness.py +467 -0
- scspill-0.1.0/scspill/validation/structures.py +108 -0
- scspill-0.1.0/scspill.egg-info/PKG-INFO +151 -0
- scspill-0.1.0/scspill.egg-info/SOURCES.txt +51 -0
- scspill-0.1.0/scspill.egg-info/dependency_links.txt +1 -0
- scspill-0.1.0/scspill.egg-info/requires.txt +12 -0
- scspill-0.1.0/scspill.egg-info/top_level.txt +1 -0
- scspill-0.1.0/setup.cfg +4 -0
scspill-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Carlos Mendez
|
|
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.
|
scspill-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: scspill
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Bayesian spatial-spillover synthetic control (Sakaguchi & Tagawa) for causal inference on panel data.
|
|
5
|
+
Author-email: Carlos Mendez <carlosmendez777@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/quarcs-lab/scspill
|
|
8
|
+
Project-URL: Documentation, https://quarcs-lab.github.io/scspill/
|
|
9
|
+
Project-URL: Repository, https://github.com/quarcs-lab/scspill
|
|
10
|
+
Project-URL: Issues, https://github.com/quarcs-lab/scspill/issues
|
|
11
|
+
Keywords: synthetic control,spillover effects,spatial econometrics,bayesian inference,causal inference,panel data,MCMC
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
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: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: pandas>=2.0
|
|
25
|
+
Requires-Dist: numpy>=1.26
|
|
26
|
+
Requires-Dist: scipy>=1.11
|
|
27
|
+
Requires-Dist: matplotlib>=3.8
|
|
28
|
+
Requires-Dist: pydantic>=2.0
|
|
29
|
+
Requires-Dist: threadpoolctl>=3.6.0
|
|
30
|
+
Provides-Extra: numba
|
|
31
|
+
Requires-Dist: numba>=0.60; extra == "numba"
|
|
32
|
+
Provides-Extra: all
|
|
33
|
+
Requires-Dist: scspill[numba]; extra == "all"
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
<p align="center">
|
|
37
|
+
<img src="https://raw.githubusercontent.com/quarcs-lab/scspill/main/docs/images/hero-v2.png" alt="scspill — Bayesian synthetic control with spillovers" width="85%">
|
|
38
|
+
</p>
|
|
39
|
+
|
|
40
|
+
# scspill
|
|
41
|
+
|
|
42
|
+
[](https://github.com/quarcs-lab/scspill/actions/workflows/ci.yml)
|
|
43
|
+
[](https://quarcs-lab.github.io/scspill/)
|
|
44
|
+
[](https://pypi.org/project/scspill/)
|
|
45
|
+
[](https://pypi.org/project/scspill/)
|
|
46
|
+
[](LICENSE)
|
|
47
|
+
[](https://github.com/astral-sh/ruff)
|
|
48
|
+
[](https://colab.research.google.com/github/quarcs-lab/scspill/blob/main/notebooks/california.ipynb)
|
|
49
|
+
|
|
50
|
+
Synthetic control when the treatment leaks. **scspill** is a Python
|
|
51
|
+
implementation of the Bayesian spatial-spillover synthetic control of
|
|
52
|
+
Sakaguchi & Tagawa (*Identification and Bayesian Inference for Synthetic
|
|
53
|
+
Control Methods with Spillover Effects*, The Econometrics Journal): it
|
|
54
|
+
relaxes SUTVA by letting the treatment spill over to the donor pool through
|
|
55
|
+
a spatial-autoregressive channel with user-supplied weights, and estimates
|
|
56
|
+
both the treatment effect on the treated unit and the spillover effect
|
|
57
|
+
received by every donor — with full Bayesian uncertainty.
|
|
58
|
+
|
|
59
|
+
The estimator follows the
|
|
60
|
+
[mlsynth](https://github.com/jgreathouse9/mlsynth) architecture (a pydantic
|
|
61
|
+
config in, a standardized results object out) so the two libraries compose
|
|
62
|
+
naturally; the documentation site follows
|
|
63
|
+
[geometrics](https://github.com/quarcs-lab/geometrics).
|
|
64
|
+
|
|
65
|
+
## Installation
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install scspill # NumPy/SciPy sampler backend
|
|
69
|
+
pip install "scspill[numba]" # + JIT-compiled samplers (~10x faster)
|
|
70
|
+
pip install "scspill @ git+https://github.com/quarcs-lab/scspill.git" # latest
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Python 3.10+.
|
|
74
|
+
|
|
75
|
+
## At a glance
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from scspill import SCSPILL
|
|
79
|
+
from scspill.data import load_california
|
|
80
|
+
|
|
81
|
+
panel = load_california() # Prop 99 panel + rook-contiguity weights
|
|
82
|
+
result = SCSPILL(
|
|
83
|
+
{**panel.config_kwargs(), "m_iter": 20_000, "burn": 10_000, "seed": 42}
|
|
84
|
+
).fit()
|
|
85
|
+
|
|
86
|
+
result.att, result.att_ci # treatment effect on California + 95% CrI
|
|
87
|
+
result.rho_hat, result.rho_ci # spillover intensity posterior
|
|
88
|
+
result.spillover_panel["Nevada"] # the effect received by Nevada, per year
|
|
89
|
+
result.diagnostics() # ESS / R-hat / MCSE per chain
|
|
90
|
+
result.plot(kind="panel") # counterfactual | effect | top spillovers
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## What's inside
|
|
94
|
+
|
|
95
|
+
| Subpackage | What it does | Docs |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| `scspill` | `SCSPILL(config).fit()` — the two-step Bayesian sampler (horseshoe synthetic weights, SAR spillover block, adaptive Metropolis for the spillover intensity) and the identification formulas | [Get started](https://quarcs-lab.github.io/scspill/get-started.html) |
|
|
98
|
+
| `scspill.validation` | The Geweke (2004) joint distribution test of the sampler, prior-sensitivity grids, prior predictive checks | [Validation](https://quarcs-lab.github.io/scspill/articles/validation.html) |
|
|
99
|
+
| `scspill.simulate` | The paper's Monte Carlo engine: rook-lattice SAR DGP, SCM/BSCM/SCSPILL comparison, the Tables 1–2 grid | [Simulation study](https://quarcs-lab.github.io/scspill/articles/simulation-study.html) |
|
|
100
|
+
| `scspill.data` | The bundled California Prop 99 and Sudan secession case studies | [Datasets](https://quarcs-lab.github.io/scspill/articles/datasets.html) |
|
|
101
|
+
|
|
102
|
+
## Validated against the R replication package
|
|
103
|
+
|
|
104
|
+
The Python port is cross-validated against the authors' R replication
|
|
105
|
+
package (`python benchmarks/run_benchmarks.py --all --report`): California
|
|
106
|
+
and Sudan posteriors against the frozen R credible intervals, the Monte
|
|
107
|
+
Carlo grid against the paper's frozen Tables 1–2, prior predictive
|
|
108
|
+
statistics to three decimals, and the samplers against the Geweke joint
|
|
109
|
+
distribution test. The defaults are *paper-correct*: several documented bugs
|
|
110
|
+
of the reference implementation (a covariate memory-layout mismatch, a
|
|
111
|
+
missing horseshoe prior, alpha-frozen credible intervals, two incoherent
|
|
112
|
+
factor-block conditionals) are fixed here, each with an escape hatch or a
|
|
113
|
+
benchmark quantifying the difference — see the
|
|
114
|
+
[method article](https://quarcs-lab.github.io/scspill/articles/method.html).
|
|
115
|
+
|
|
116
|
+
## Documentation
|
|
117
|
+
|
|
118
|
+
Full documentation, executed tutorials, and the API reference live at
|
|
119
|
+
**<https://quarcs-lab.github.io/scspill/>**. Machine-readable entry points
|
|
120
|
+
for AI agents: [`llms.txt`](https://quarcs-lab.github.io/scspill/llms.txt)
|
|
121
|
+
and [`llms-full.txt`](https://quarcs-lab.github.io/scspill/llms-full.txt).
|
|
122
|
+
|
|
123
|
+
## Development
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
git clone https://github.com/quarcs-lab/scspill && cd scspill
|
|
127
|
+
uv sync --all-extras --group dev --group docs
|
|
128
|
+
make test # pytest (fast tier; `make test-slow` for the long tier)
|
|
129
|
+
make lint # ruff check + format
|
|
130
|
+
make typecheck # mypy
|
|
131
|
+
make docs # quartodoc build -> quarto render -> llms.txt
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Citing
|
|
135
|
+
|
|
136
|
+
If you use scspill, please cite the methodological article and the software
|
|
137
|
+
(see `CITATION.cff`):
|
|
138
|
+
|
|
139
|
+
> Sakaguchi, S., & Tagawa, H. Identification and Bayesian Inference for
|
|
140
|
+
> Synthetic Control Methods with Spillover Effects. *The Econometrics
|
|
141
|
+
> Journal*.
|
|
142
|
+
|
|
143
|
+
## Acknowledgments
|
|
144
|
+
|
|
145
|
+
The method and reference implementation are by Shosei Sakaguchi and Hayato
|
|
146
|
+
Tagawa. The estimator architecture follows Jared Greathouse's mlsynth; the
|
|
147
|
+
documentation stack follows the QuaRCS-lab geometrics package.
|
|
148
|
+
|
|
149
|
+
## License
|
|
150
|
+
|
|
151
|
+
MIT
|
scspill-0.1.0/README.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/quarcs-lab/scspill/main/docs/images/hero-v2.png" alt="scspill — Bayesian synthetic control with spillovers" width="85%">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# scspill
|
|
6
|
+
|
|
7
|
+
[](https://github.com/quarcs-lab/scspill/actions/workflows/ci.yml)
|
|
8
|
+
[](https://quarcs-lab.github.io/scspill/)
|
|
9
|
+
[](https://pypi.org/project/scspill/)
|
|
10
|
+
[](https://pypi.org/project/scspill/)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+
[](https://github.com/astral-sh/ruff)
|
|
13
|
+
[](https://colab.research.google.com/github/quarcs-lab/scspill/blob/main/notebooks/california.ipynb)
|
|
14
|
+
|
|
15
|
+
Synthetic control when the treatment leaks. **scspill** is a Python
|
|
16
|
+
implementation of the Bayesian spatial-spillover synthetic control of
|
|
17
|
+
Sakaguchi & Tagawa (*Identification and Bayesian Inference for Synthetic
|
|
18
|
+
Control Methods with Spillover Effects*, The Econometrics Journal): it
|
|
19
|
+
relaxes SUTVA by letting the treatment spill over to the donor pool through
|
|
20
|
+
a spatial-autoregressive channel with user-supplied weights, and estimates
|
|
21
|
+
both the treatment effect on the treated unit and the spillover effect
|
|
22
|
+
received by every donor — with full Bayesian uncertainty.
|
|
23
|
+
|
|
24
|
+
The estimator follows the
|
|
25
|
+
[mlsynth](https://github.com/jgreathouse9/mlsynth) architecture (a pydantic
|
|
26
|
+
config in, a standardized results object out) so the two libraries compose
|
|
27
|
+
naturally; the documentation site follows
|
|
28
|
+
[geometrics](https://github.com/quarcs-lab/geometrics).
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install scspill # NumPy/SciPy sampler backend
|
|
34
|
+
pip install "scspill[numba]" # + JIT-compiled samplers (~10x faster)
|
|
35
|
+
pip install "scspill @ git+https://github.com/quarcs-lab/scspill.git" # latest
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Python 3.10+.
|
|
39
|
+
|
|
40
|
+
## At a glance
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from scspill import SCSPILL
|
|
44
|
+
from scspill.data import load_california
|
|
45
|
+
|
|
46
|
+
panel = load_california() # Prop 99 panel + rook-contiguity weights
|
|
47
|
+
result = SCSPILL(
|
|
48
|
+
{**panel.config_kwargs(), "m_iter": 20_000, "burn": 10_000, "seed": 42}
|
|
49
|
+
).fit()
|
|
50
|
+
|
|
51
|
+
result.att, result.att_ci # treatment effect on California + 95% CrI
|
|
52
|
+
result.rho_hat, result.rho_ci # spillover intensity posterior
|
|
53
|
+
result.spillover_panel["Nevada"] # the effect received by Nevada, per year
|
|
54
|
+
result.diagnostics() # ESS / R-hat / MCSE per chain
|
|
55
|
+
result.plot(kind="panel") # counterfactual | effect | top spillovers
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## What's inside
|
|
59
|
+
|
|
60
|
+
| Subpackage | What it does | Docs |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| `scspill` | `SCSPILL(config).fit()` — the two-step Bayesian sampler (horseshoe synthetic weights, SAR spillover block, adaptive Metropolis for the spillover intensity) and the identification formulas | [Get started](https://quarcs-lab.github.io/scspill/get-started.html) |
|
|
63
|
+
| `scspill.validation` | The Geweke (2004) joint distribution test of the sampler, prior-sensitivity grids, prior predictive checks | [Validation](https://quarcs-lab.github.io/scspill/articles/validation.html) |
|
|
64
|
+
| `scspill.simulate` | The paper's Monte Carlo engine: rook-lattice SAR DGP, SCM/BSCM/SCSPILL comparison, the Tables 1–2 grid | [Simulation study](https://quarcs-lab.github.io/scspill/articles/simulation-study.html) |
|
|
65
|
+
| `scspill.data` | The bundled California Prop 99 and Sudan secession case studies | [Datasets](https://quarcs-lab.github.io/scspill/articles/datasets.html) |
|
|
66
|
+
|
|
67
|
+
## Validated against the R replication package
|
|
68
|
+
|
|
69
|
+
The Python port is cross-validated against the authors' R replication
|
|
70
|
+
package (`python benchmarks/run_benchmarks.py --all --report`): California
|
|
71
|
+
and Sudan posteriors against the frozen R credible intervals, the Monte
|
|
72
|
+
Carlo grid against the paper's frozen Tables 1–2, prior predictive
|
|
73
|
+
statistics to three decimals, and the samplers against the Geweke joint
|
|
74
|
+
distribution test. The defaults are *paper-correct*: several documented bugs
|
|
75
|
+
of the reference implementation (a covariate memory-layout mismatch, a
|
|
76
|
+
missing horseshoe prior, alpha-frozen credible intervals, two incoherent
|
|
77
|
+
factor-block conditionals) are fixed here, each with an escape hatch or a
|
|
78
|
+
benchmark quantifying the difference — see the
|
|
79
|
+
[method article](https://quarcs-lab.github.io/scspill/articles/method.html).
|
|
80
|
+
|
|
81
|
+
## Documentation
|
|
82
|
+
|
|
83
|
+
Full documentation, executed tutorials, and the API reference live at
|
|
84
|
+
**<https://quarcs-lab.github.io/scspill/>**. Machine-readable entry points
|
|
85
|
+
for AI agents: [`llms.txt`](https://quarcs-lab.github.io/scspill/llms.txt)
|
|
86
|
+
and [`llms-full.txt`](https://quarcs-lab.github.io/scspill/llms-full.txt).
|
|
87
|
+
|
|
88
|
+
## Development
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
git clone https://github.com/quarcs-lab/scspill && cd scspill
|
|
92
|
+
uv sync --all-extras --group dev --group docs
|
|
93
|
+
make test # pytest (fast tier; `make test-slow` for the long tier)
|
|
94
|
+
make lint # ruff check + format
|
|
95
|
+
make typecheck # mypy
|
|
96
|
+
make docs # quartodoc build -> quarto render -> llms.txt
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Citing
|
|
100
|
+
|
|
101
|
+
If you use scspill, please cite the methodological article and the software
|
|
102
|
+
(see `CITATION.cff`):
|
|
103
|
+
|
|
104
|
+
> Sakaguchi, S., & Tagawa, H. Identification and Bayesian Inference for
|
|
105
|
+
> Synthetic Control Methods with Spillover Effects. *The Econometrics
|
|
106
|
+
> Journal*.
|
|
107
|
+
|
|
108
|
+
## Acknowledgments
|
|
109
|
+
|
|
110
|
+
The method and reference implementation are by Shosei Sakaguchi and Hayato
|
|
111
|
+
Tagawa. The estimator architecture follows Jared Greathouse's mlsynth; the
|
|
112
|
+
documentation stack follows the QuaRCS-lab geometrics package.
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77.0.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "scspill"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Bayesian spatial-spillover synthetic control (Sakaguchi & Tagawa) for causal inference on panel data."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "Carlos Mendez", email = "carlosmendez777@gmail.com" }]
|
|
14
|
+
keywords = [
|
|
15
|
+
"synthetic control",
|
|
16
|
+
"spillover effects",
|
|
17
|
+
"spatial econometrics",
|
|
18
|
+
"bayesian inference",
|
|
19
|
+
"causal inference",
|
|
20
|
+
"panel data",
|
|
21
|
+
"MCMC",
|
|
22
|
+
]
|
|
23
|
+
classifiers = [
|
|
24
|
+
"Development Status :: 3 - Alpha",
|
|
25
|
+
"Intended Audience :: Science/Research",
|
|
26
|
+
"Programming Language :: Python :: 3",
|
|
27
|
+
"Programming Language :: Python :: 3.10",
|
|
28
|
+
"Programming Language :: Python :: 3.11",
|
|
29
|
+
"Programming Language :: Python :: 3.12",
|
|
30
|
+
"Programming Language :: Python :: 3.13",
|
|
31
|
+
"Topic :: Scientific/Engineering",
|
|
32
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
33
|
+
]
|
|
34
|
+
dependencies = [
|
|
35
|
+
"pandas>=2.0",
|
|
36
|
+
"numpy>=1.26",
|
|
37
|
+
"scipy>=1.11",
|
|
38
|
+
"matplotlib>=3.8",
|
|
39
|
+
"pydantic>=2.0",
|
|
40
|
+
"threadpoolctl>=3.6.0",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.optional-dependencies]
|
|
44
|
+
# JIT-accelerated Gibbs/SAR kernels. Optional because numba wheels can lag new
|
|
45
|
+
# Python releases; the pure-NumPy path is always available.
|
|
46
|
+
numba = ["numba>=0.60"]
|
|
47
|
+
all = ["scspill[numba]"]
|
|
48
|
+
|
|
49
|
+
[project.urls]
|
|
50
|
+
Homepage = "https://github.com/quarcs-lab/scspill"
|
|
51
|
+
Documentation = "https://quarcs-lab.github.io/scspill/"
|
|
52
|
+
Repository = "https://github.com/quarcs-lab/scspill"
|
|
53
|
+
Issues = "https://github.com/quarcs-lab/scspill/issues"
|
|
54
|
+
|
|
55
|
+
[dependency-groups]
|
|
56
|
+
dev = [
|
|
57
|
+
"pytest>=8",
|
|
58
|
+
"pytest-cov>=5",
|
|
59
|
+
"pytest-xdist>=3",
|
|
60
|
+
"ruff>=0.6",
|
|
61
|
+
"mypy>=1.10",
|
|
62
|
+
"pandas-stubs",
|
|
63
|
+
]
|
|
64
|
+
docs = [
|
|
65
|
+
"quartodoc>=0.11",
|
|
66
|
+
"griffe<1",
|
|
67
|
+
"jupyter",
|
|
68
|
+
"nbformat>=5.9",
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
# ---------------------------------------------------------------------------
|
|
72
|
+
# Packaging: flat layout, in-package tests excluded from the wheel (mlsynth
|
|
73
|
+
# convention), bundled case-study CSVs shipped as package data.
|
|
74
|
+
# ---------------------------------------------------------------------------
|
|
75
|
+
[tool.setuptools.packages.find]
|
|
76
|
+
include = ["scspill*"]
|
|
77
|
+
exclude = ["scspill.tests*"]
|
|
78
|
+
|
|
79
|
+
[tool.setuptools.package-data]
|
|
80
|
+
scspill = ["py.typed"]
|
|
81
|
+
"scspill.data" = ["files/*.csv"]
|
|
82
|
+
|
|
83
|
+
# ---------------------------------------------------------------------------
|
|
84
|
+
# Tooling
|
|
85
|
+
# ---------------------------------------------------------------------------
|
|
86
|
+
[tool.ruff]
|
|
87
|
+
line-length = 100
|
|
88
|
+
target-version = "py310"
|
|
89
|
+
src = ["scspill"]
|
|
90
|
+
|
|
91
|
+
[tool.ruff.lint]
|
|
92
|
+
select = ["E", "F", "W", "I", "UP", "B", "SIM", "D", "RUF"]
|
|
93
|
+
ignore = [
|
|
94
|
+
"D100", "D104", "D105", "D107", # module/package/magic/__init__ docstrings
|
|
95
|
+
"D106", # pydantic `class Config` blocks need no docstring
|
|
96
|
+
"E501", # line length handled by the formatter
|
|
97
|
+
]
|
|
98
|
+
# Greek symbols appear in scientific prose and labels: alpha donor weights,
|
|
99
|
+
# rho spillover intensity, tau treatment effect, sigma error scale.
|
|
100
|
+
allowed-confusables = ["α", "ρ", "τ", "σ", "β", "γ", "η", "ξ", "ω", "φ", "ψ", "λ", "−"]
|
|
101
|
+
|
|
102
|
+
[tool.ruff.lint.pydocstyle]
|
|
103
|
+
convention = "numpy"
|
|
104
|
+
|
|
105
|
+
[tool.ruff.lint.per-file-ignores]
|
|
106
|
+
"scspill/tests/*" = ["D"]
|
|
107
|
+
"docs/*" = ["D"]
|
|
108
|
+
"tools/*" = ["D"]
|
|
109
|
+
"benchmarks/*" = ["D"]
|
|
110
|
+
# json_encoders in the pydantic Config blocks (mlsynth-inherited surface).
|
|
111
|
+
"scspill/config_models.py" = ["RUF012"]
|
|
112
|
+
|
|
113
|
+
[tool.mypy]
|
|
114
|
+
python_version = "3.12"
|
|
115
|
+
warn_unused_configs = true
|
|
116
|
+
ignore_missing_imports = true
|
|
117
|
+
files = ["scspill"]
|
|
118
|
+
exclude = ["scspill/tests"]
|
|
119
|
+
|
|
120
|
+
[tool.pytest.ini_options]
|
|
121
|
+
minversion = "8.0"
|
|
122
|
+
addopts = "--strict-markers --strict-config"
|
|
123
|
+
testpaths = ["scspill/tests"]
|
|
124
|
+
markers = [
|
|
125
|
+
"slow: long-running tests (full-length MCMC chains, large Monte-Carlo designs)",
|
|
126
|
+
]
|
|
127
|
+
filterwarnings = ["ignore::DeprecationWarning"]
|
|
128
|
+
|
|
129
|
+
[tool.coverage.run]
|
|
130
|
+
source = ["scspill"]
|
|
131
|
+
branch = true
|
|
132
|
+
omit = ["scspill/tests/*"]
|
|
133
|
+
|
|
134
|
+
[tool.coverage.report]
|
|
135
|
+
show_missing = true
|
|
136
|
+
exclude_lines = ["pragma: no cover", "raise NotImplementedError", "if TYPE_CHECKING:"]
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""scspill: Bayesian spatial-spillover synthetic control.
|
|
2
|
+
|
|
3
|
+
Implements:
|
|
4
|
+
|
|
5
|
+
Sakaguchi, S., & Tagawa, H. "Identification and Bayesian Inference for
|
|
6
|
+
Synthetic Control Methods with Spillover Effects." The Econometrics
|
|
7
|
+
Journal.
|
|
8
|
+
|
|
9
|
+
A synthetic control method that relaxes SUTVA: spillovers from the treated
|
|
10
|
+
unit to the donor pool are modeled through a spatial-autoregressive (SAR)
|
|
11
|
+
structure with user-supplied spatial weights, and both the treatment effect on
|
|
12
|
+
the treated and the spillover effect received by every control unit are
|
|
13
|
+
identified from the synthetic-control weights ``alpha``, the spillover
|
|
14
|
+
intensity ``rho``, and the weights ``(w, W)``. Estimation is a two-step
|
|
15
|
+
Bayesian sampler: a horseshoe Gibbs sampler for ``alpha`` on the
|
|
16
|
+
pre-treatment fit, then a SAR block (latent AR(1) factors, covariates, and a
|
|
17
|
+
random-walk Metropolis step for ``rho``) conditional on the posterior mean of
|
|
18
|
+
``alpha``.
|
|
19
|
+
|
|
20
|
+
Public API::
|
|
21
|
+
|
|
22
|
+
from scspill import SCSPILL, SCSPILLConfig
|
|
23
|
+
|
|
24
|
+
result = SCSPILL(config).fit() # -> SCSPILLResults
|
|
25
|
+
|
|
26
|
+
plus the companion subpackages :mod:`scspill.validation` (Geweke joint
|
|
27
|
+
distribution test, prior sensitivity, prior predictive checks),
|
|
28
|
+
:mod:`scspill.simulate` (the paper's Monte Carlo engine), and
|
|
29
|
+
:mod:`scspill.data` (the bundled California Proposition 99 and Sudan
|
|
30
|
+
secession case studies).
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
34
|
+
|
|
35
|
+
try: # pragma: no cover - fallback exercised only in odd install states
|
|
36
|
+
__version__ = version("scspill")
|
|
37
|
+
except PackageNotFoundError: # pragma: no cover
|
|
38
|
+
__version__ = "0.0.0.dev0"
|
|
39
|
+
|
|
40
|
+
from scspill.exceptions import (
|
|
41
|
+
ScspillConfigError,
|
|
42
|
+
ScspillDataError,
|
|
43
|
+
ScspillError,
|
|
44
|
+
ScspillEstimationError,
|
|
45
|
+
ScspillPlottingError,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
__all__ = [
|
|
49
|
+
"SCSPILL",
|
|
50
|
+
"SCSPILLConfig",
|
|
51
|
+
"SCSPILLResults",
|
|
52
|
+
"ScspillConfigError",
|
|
53
|
+
"ScspillDataError",
|
|
54
|
+
"ScspillError",
|
|
55
|
+
"ScspillEstimationError",
|
|
56
|
+
"ScspillPlottingError",
|
|
57
|
+
"__version__",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
# Lazy exports (PEP 562): the estimator stack imports pandas/pydantic/scipy,
|
|
61
|
+
# so defer those imports until first attribute access for fast cold starts.
|
|
62
|
+
_LAZY_EXPORTS = {
|
|
63
|
+
"SCSPILL": ("scspill.estimators.scspill", "SCSPILL"),
|
|
64
|
+
"SCSPILLConfig": ("scspill.utils.scspill_helpers.config", "SCSPILLConfig"),
|
|
65
|
+
"SCSPILLResults": ("scspill.utils.scspill_helpers.structures", "SCSPILLResults"),
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def __getattr__(name: str):
|
|
70
|
+
"""Resolve lazily exported public names (PEP 562)."""
|
|
71
|
+
target = _LAZY_EXPORTS.get(name)
|
|
72
|
+
if target is not None:
|
|
73
|
+
import importlib
|
|
74
|
+
|
|
75
|
+
module_path, attr = target
|
|
76
|
+
return getattr(importlib.import_module(module_path), attr)
|
|
77
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def __dir__():
|
|
81
|
+
"""Include lazy exports in ``dir(scspill)``."""
|
|
82
|
+
return sorted(set(globals()) | set(_LAZY_EXPORTS))
|