Downloads
Each dataset is available as a labeled Stata .dta and its source file.
⇩ Download all data (ZIP)stata_codebook.do
| Dataset | Grain | Rows | Stata | Source |
|---|---|---|---|---|
python_sc_bayes_spatial_source_data | state-year | 1,209 × 6 | python_sc_bayes_spatial_source_data.dta | python_sc_bayes_spatial_source_data.csv |
python_sc_bayes_spatial_spatial_edges | ordered state pair | 150 × 3 | python_sc_bayes_spatial_spatial_edges.dta | python_sc_bayes_spatial_spatial_edges.csv |
python_sc_bayes_spatial_spatial_summary | state | 38 × 5 | python_sc_bayes_spatial_spatial_summary.dta | python_sc_bayes_spatial_spatial_summary.csv |
Run stata_codebook.do in Stata once to attach long-form per-variable notes to the .dta files.
Load directly in code
Every file loads straight from GitHub (raw URLs). Swap the file name to load any dataset.
Stata
* Stata 14+ : `use` reads an https URL directly
global BASE "https://raw.githubusercontent.com/cmg777/starter-academic-v501/master/content/post/python_sc_bayes_spatial/data/"
use "${BASE}python_sc_bayes_spatial_source_data.dta", clear
describe
notesPython
!pip install -q pyreadstat
import pandas as pd
BASE = "https://raw.githubusercontent.com/cmg777/starter-academic-v501/master/content/post/python_sc_bayes_spatial/data/"
df = pd.read_stata(BASE + "python_sc_bayes_spatial_source_data.dta")
# load every dataset at once
files = ["python_sc_bayes_spatial_source_data", "python_sc_bayes_spatial_spatial_edges", "python_sc_bayes_spatial_spatial_summary"]
data = {f: pd.read_stata(BASE + f + ".dta") for f in files}
# pyreadstat (richest metadata) reads LOCAL files -> download first
import pyreadstat, urllib.request
urllib.request.urlretrieve(BASE + "python_sc_bayes_spatial_source_data.dta", "python_sc_bayes_spatial_source_data.dta")
df, meta = pyreadstat.read_dta("python_sc_bayes_spatial_source_data.dta")Copy and paste this snippet in Google Colab app. https://colab.research.google.com/notebooks/empty.ipynb
R
# R : haven::read_dta auto-downloads an https URL
library(haven)
BASE <- "https://raw.githubusercontent.com/cmg777/starter-academic-v501/master/content/post/python_sc_bayes_spatial/data/"
df <- read_dta(paste0(BASE, "python_sc_bayes_spatial_source_data.dta"))Overview & sources
Companion data for a Python tutorial that fits three nested synthetic-control estimators to California's Proposition 99: the classical simplex of Abadie, Diamond & Hainmueller (2010), a Bayesian horseshoe prior on unconstrained weights, and the Bayesian spatial (SAR) model of Sakaguchi & Tagawa (2026). The outcome panel is the same real tobacco data used throughout the synthetic-control literature: per-capita cigarette sales (cigsale) and real retail price (retprice) for 39 US states over 1970–2000, as distributed in the scspill package. California is the one treated unit; the other 38 states form the donor pool.
python_sc_bayes_spatial_source_data.csv is the balanced annual state panel — one row per state × year, 39 × 31 = 1,209 rows, no missing values. 18 pre-treatment years (1970–1987) and 13 post-treatment years (1988–2000); the treated dummy is 1 only for California from 1988 onward (13 rows). The other two files carry the spatial structure, which the third estimator needs and which the outcome panel cannot express. python_sc_bayes_spatial_spatial_edges.csv is the 38×38 donor-to-donor rook contiguity matrix in long form: one row per adjacent pair, 150 directed rows = 75 undirected borders. python_sc_bayes_spatial_spatial_summary.csv is one row per donor with its degree, its exposure to California, and its neighbour list. The single most consequential fact in these files: exactly one donor borders California. Oregon and Arizona do too, but neither is in the donor pool.
Data sources
| Source | Provides | Reference / URL |
|---|---|---|
| Abadie, Diamond & Hainmueller (2010) | The California tobacco panel (cigsale, retprice) and the synthetic control method itself | Abadie, A., Diamond, A. & Hainmueller, J. (2010). Synthetic control methods for comparative case studies: Estimating the effect of California's tobacco control program. Journal of the American Statistical Association, 105(490), 493–505. https://doi.org/10.1198/jasa.2009.ap08746 |
| Sakaguchi & Tagawa (2026) | The Bayesian spatial spillover model, and the replication package the panel and weights are exported from | Sakaguchi, S. & Tagawa, H. (2026). Identification and Bayesian Inference for Synthetic Control Methods with Spillover Effects. The Econometrics Journal. https://doi.org/10.1093/ectj/utag006 (replication package: Zenodo record 19066186). |
| US Census Bureau TIGER/Line | The 2024 state boundary shapefile from which rook contiguity is derived | US Census Bureau (2024). TIGER/Line Shapefiles: States. Contiguity computed with spdep::poly2nb(queen = FALSE). |
| Software | Estimators | scspill 0.2.1 (https://quarcs-lab.github.io/scspill/); mlsynth (https://mlsynth.readthedocs.io/); Carvalho, Polson & Scott (2010, horseshoe prior); LeSage & Pace (2009, spatial econometrics). |
Cite this data
Please cite this dataset as follows.
APA
Mendez, C. (2026). Bayesian Spatial Synthetic Control in Python: California's Proposition 99 with scspill and mlsynth [Data set]. https://carlos-mendez.org/post/python_sc_bayes_spatial/
Abadie, A., Diamond, A., & Hainmueller, J. (2010). Synthetic control methods for comparative case studies: Estimating the effect of California's tobacco control program. Journal of the American Statistical Association, 105(490), 493–505. https://doi.org/10.1198/jasa.2009.ap08746
Sakaguchi, S., & Tagawa, H. (2026). Identification and Bayesian Inference for Synthetic Control Methods with Spillover Effects. The Econometrics Journal. https://doi.org/10.1093/ectj/utag006BibTeX
@misc{mendez2026pythonscbayesspatial,
author = {Mendez, Carlos},
title = {Bayesian Spatial Synthetic Control in Python: California's Proposition 99 with scspill and mlsynth},
year = {2026},
howpublished = {\url{https://carlos-mendez.org/post/python_sc_bayes_spatial/}},
note = {Data set}
}
@article{abadie2010synthetic,
author = {Abadie, Alberto and Diamond, Alexis and Hainmueller, Jens},
title = {Synthetic Control Methods for Comparative Case Studies: Estimating the Effect of California's Tobacco Control Program},
journal = {Journal of the American Statistical Association},
volume = {105}, number = {490}, pages = {493--505}, year = {2010},
doi = {10.1198/jasa.2009.ap08746}
}
@article{sakaguchi2026spillover,
author = {Sakaguchi, Shosei and Tagawa, Hisahiro},
title = {Identification and {Bayesian} Inference for Synthetic Control Methods with Spillover Effects},
journal = {The Econometrics Journal},
year = {2026},
doi = {10.1093/ectj/utag006}
}Variable explorer search & filter all 13 variables
Type to filter by name or label, or use the chips to filter by type. Each row shows a mini distribution. Click a header to sort.
| Variable | Type | Distribution | Label | Definition | Units | In files | Source |
|---|---|---|---|---|---|---|---|
borders_california# | dummy | Borders California (flag) | Integer duplicate of w_california, for convenience when filtering. | 0/1 | python_sc_bayes_spatial_spatial_summary | Derived | |
cigsale# | continuous | Per-capita cigarette sales (packs) | Annual per-capita cigarette pack sales. This is the synthetic-control outcome. | packs per capita per year | python_sc_bayes_spatial_source_data | Abadie et al. (2010) via scspill | |
contiguous# | dummy | Shares a land border | Always 1 in this file — zero-contiguity pairs are omitted rather than stored. | 0/1 | python_sc_bayes_spatial_spatial_edges | TIGER/Line 2024 boundaries | |
degree# | continuous | Number of neighbouring donors | How many other donor states this state borders. Its row sum in W. | count | python_sc_bayes_spatial_spatial_summary | Derived from the contiguity matrix | |
neighbour_list# | identifier | – | Comma-separated neighbour names | The donor states this state borders, listed alphabetically. Human-readable form of the edge list. | string | python_sc_bayes_spatial_spatial_summary | Derived from the contiguity matrix |
retprice# | continuous | Real retail cigarette price | Average retail price per pack. The single covariate entering the SAR layer. | cents per pack | python_sc_bayes_spatial_source_data | Abadie et al. (2010) via scspill | |
state# | identifier | – | State name | US state identifier. The treated unit is California; the other 38 states are donors. | string | python_sc_bayes_spatial_source_data, python_sc_bayes_spatial_spatial_summary | scspill package (Abadie et al. 2010) |
state_i# | identifier | – | Origin state of the contiguity pair | The donor state whose neighbour is recorded in state_j. | string | python_sc_bayes_spatial_spatial_edges | TIGER/Line 2024 boundaries, spdep::poly2nb(queen = FALSE) |
state_id# | identifier | – | State numeric ID | Integer index for the state (1-39). | integer (1-39) | python_sc_bayes_spatial_source_data | scspill package |
state_j# | identifier | – | Neighbour state of the contiguity pair | A donor state sharing a land border with state_i. | string | python_sc_bayes_spatial_spatial_edges | TIGER/Line 2024 boundaries, spdep::poly2nb(queen = FALSE) |
treated# | dummy | Treatment indicator | 1 for California from 1988 onward; 0 otherwise. Note this is 1988, not 1989 — see the caveats. | 0/1 | python_sc_bayes_spatial_source_data | Constructed | |
w_california# | dummy | Contiguity with California | 1 if this donor borders California, 0 otherwise. THIS IS the w vector of the SAR model. | 0/1 | python_sc_bayes_spatial_spatial_summary | TIGER/Line 2024 boundaries | |
year# | year | – | Calendar year | Annual time index of the panel. | year | python_sc_bayes_spatial_source_data | scspill package (Abadie et al. 2010) |
Cross-file variable index
Which file each variable appears in (● = present).
| Variable | python_sc_bayes_spatial_source_data | python_sc_bayes_spatial_spatial_edges | python_sc_bayes_spatial_spatial_summary |
|---|---|---|---|
borders_california | ● | ||
cigsale | ● | ||
contiguous | ● | ||
degree | ● | ||
neighbour_list | ● | ||
retprice | ● | ||
state | ● | ● | |
state_i | ● | ||
state_id | ● | ||
state_j | ● | ||
treated | ● | ||
w_california | ● | ||
year | ● |
Construction & formulas
Three nested estimators are fitted to these files. Each keeps everything the previous one assumed except a single restriction:
- Stage 1 — classical SCM.
α̂ = argmin ‖Y₁,pre − Y_c,pre · α‖²subject toα_j ≥ 0andΣ α_j = 1— the simplex. Fitted withmlsynth.VanillaSC. - Stage 2 — Bayesian horseshoe SCM.
α_j | λ_j ~ N(0, λ_j²)withλ_j | τ ~ C⁺(0, τ)— the hard constraint replaced by a shrinkage prior that prefers zero without forbidding anything. Fitted withmlsynth.BSCM, and available for free as theρ = 0case of Stage 3. - Stage 3 — Bayesian spatial SCM.
Y_c,t = ρ (w · Y₁,t + W · Y_c,t) + X_t β + u_t— a spatial autoregressive layer on the donor outcomes, using the two files documented here. Dropping SUTVA makes a second estimand estimable: the spilloverξ_c,t = Y_c,t − Y_c,t(0)received by each donor. Fitted withscspill.SCSPILL(method="sar").
The treated dummy is 1 if state == "California" and year ≥ 1988 else 0
— the replication package's convention. Everything else in these files is observed data or a
deterministic function of the TIGER/Line boundaries.
The datasets
Switch datasets with the tabs. Each shows the full variable dictionary plus a sortable statistics table with mini distributions and data coverage.
expand to search (Ctrl/⌘+F) or print across all datasets
Variable dictionary
| Variable | Label | Definition | Construction | Units | Source | Coverage |
|---|---|---|---|---|---|---|
state identifier | State name | US state identifier. The treated unit is California; the other 38 states are donors. | From the scspill package panel (Abadie et al. 2010). | string | scspill package (Abadie et al. 2010) | 39 states in the panel, 38 in the spatial files |
state_id identifier | State numeric ID | Integer index for the state (1-39). | Sequential package index aligned to the alphabetical state list. | integer (1-39) | scspill package | 39 states |
year year | Calendar year | Annual time index of the panel. | Observed year, 1970-2000 (balanced; 31 years per state). | year | scspill package (Abadie et al. 2010) | 1970-2000 |
cigsale continuous | Per-capita cigarette sales (packs) | Annual per-capita cigarette pack sales. This is the synthetic-control outcome. | Observed tax-paid cigarette sales per capita, from the Abadie et al. (2010) tobacco data. | packs per capita per year | Abadie et al. (2010) via scspill | 1,209 observations, no missing |
retprice continuous | Real retail cigarette price | Average retail price per pack. The single covariate entering the SAR layer. | Observed state-level retail price, from the Abadie et al. (2010) tobacco data. | cents per pack | Abadie et al. (2010) via scspill | 1,209 observations, no missing |
treated dummy | Treatment indicator | 1 for California from 1988 onward; 0 otherwise. Note this is 1988, not 1989 — see the caveats. | Constructed as 1 if state == 'California' and year >= 1988 else 0 (the replication package's convention). | 0/1 | Constructed | 13 treated rows of 1,209 |
Distribution & statistics (click a header to sort)
| Variable | Distribution | Coverage | N | Distinct | Min | Mean | Median | Max | SD |
|---|---|---|---|---|---|---|---|---|---|
state | – | 100% | 1,209 | 39 | — | — | — | — | — |
state_id | – | 100% | 1,209 | 39 | — | — | — | — | — |
year | – | 100% | 1,209 | 31 | 1970 | 1985.0 | 1985 | 2000 | 8.95 |
cigsale | 100% | 1,209 | 703 | 40.70 | 118.9 | 116.3 | 296.2 | 32.77 | |
retprice | 100% | 1,209 | 849 | 27.30 | 108.3 | 95.50 | 351.2 | 64.38 | |
treated | 100% | 1,209 | 2 | 0 | 0.011 | 0 | 1.00 | 0.103 |
Variable dictionary
| Variable | Label | Definition | Construction | Units | Source | Coverage |
|---|---|---|---|---|---|---|
state_i identifier | Origin state of the contiguity pair | The donor state whose neighbour is recorded in state_j. | Row index of the 38x38 rook contiguity matrix. | string | TIGER/Line 2024 boundaries, spdep::poly2nb(queen = FALSE) | 38 donor states |
state_j identifier | Neighbour state of the contiguity pair | A donor state sharing a land border with state_i. | Column index of the 38x38 rook contiguity matrix, kept only where the entry is 1. | string | TIGER/Line 2024 boundaries, spdep::poly2nb(queen = FALSE) | 38 donor states |
contiguous dummy | Shares a land border | Always 1 in this file — zero-contiguity pairs are omitted rather than stored. | Rook contiguity: 1 if the two states share a boundary segment, not merely a corner. | 0/1 | TIGER/Line 2024 boundaries | 150 directed rows = 75 undirected borders |
Distribution & statistics (click a header to sort)
| Variable | Distribution | Coverage | N | Distinct | Min | Mean | Median | Max | SD |
|---|---|---|---|---|---|---|---|---|---|
state_i | – | 100% | 150 | 38 | — | — | — | — | — |
state_j | – | 100% | 150 | 38 | — | — | — | — | — |
contiguous | 100% | 150 | 1 | 1.00 | 1.00 | 1.00 | 1.00 | 0 |
Variable dictionary
| Variable | Label | Definition | Construction | Units | Source | Coverage |
|---|---|---|---|---|---|---|
state identifier | State name | US state identifier. The treated unit is California; the other 38 states are donors. | From the scspill package panel (Abadie et al. 2010). | string | scspill package (Abadie et al. 2010) | 39 states in the panel, 38 in the spatial files |
degree continuous | Number of neighbouring donors | How many other donor states this state borders. Its row sum in W. | Row sum of the 38x38 rook contiguity matrix. | count | Derived from the contiguity matrix | range 1-8, mean 3.95 |
w_california dummy | Contiguity with California | 1 if this donor borders California, 0 otherwise. THIS IS the w vector of the SAR model. | California's row of the full 39x39 contiguity matrix, restricted to the donor pool. | 0/1 | TIGER/Line 2024 boundaries | exactly one non-zero entry: Nevada |
borders_california dummy | Borders California (flag) | Integer duplicate of w_california, for convenience when filtering. | 1 if w_california > 0. | 0/1 | Derived | 1 of 38 donors |
neighbour_list identifier | Comma-separated neighbour names | The donor states this state borders, listed alphabetically. Human-readable form of the edge list. | Names of the non-zero entries of this state's row of W. | string | Derived from the contiguity matrix | 38 donor states |
Distribution & statistics (click a header to sort)
| Variable | Distribution | Coverage | N | Distinct | Min | Mean | Median | Max | SD |
|---|---|---|---|---|---|---|---|---|---|
state | – | 100% | 38 | 38 | — | — | — | — | — |
degree | 100% | 38 | 8 | 1.00 | 3.95 | 4.00 | 8.00 | 1.90 | |
w_california | 100% | 38 | 2 | 0 | 0.026 | 0 | 1.00 | 0.162 | |
borders_california | 100% | 38 | 2 | 0 | 0.026 | 0 | 1.00 | 0.162 | |
neighbour_list | – | 100% | 38 | 37 | — | — | — | — | — |
Known limitations & caveats
- Narrow predictor set. The shipped panel carries only
cigsaleandretprice— not the log income, youth-share or beer-sales predictors Abadie et al. (2010) matched on. This is the main reason the classical ATT here (≈ −18.4) is smaller in magnitude than the ≈ −27 usually quoted from the original paper. - Treatment timing is 1988, not 1989. Proposition 99 passed in November 1988 and the tax took effect on 1 January 1989. Abadie et al. and mlsynth's own example treat 1989 as the first treated year; the scspill replication convention used here codes 1988. Neither is wrong, but they cannot be mixed — comparisons against other sources should check which convention that source used.
- Contiguity is a modelling choice, not a measurement. The edge list is rook contiguity from a 2024 shapefile applied to a 1970–2000 panel. Borders did not move, but 'neighbour' could reasonably have meant trade intensity, commuting flows or inverse distance instead — and the estimated spillover intensity would differ. The post's section 17 discusses when each is appropriate.
- Eleven states are absent. Alaska, Arizona, Florida, Hawaii, Maryland, Massachusetts, Michigan, New Jersey, New York, Oregon and Washington are excluded from the donor pool for having run their own large tobacco-control programmes. Two of them — Oregon and Arizona — border California. Their exclusion is why Nevada is California's only contiguous donor, and therefore why the spatial parameter is identified off a single channel.
- The weights are unnormalised here. Both files store raw 0/1 contiguity. Row-normalisation happens inside the estimator, not in the data.