← Back to the post
Interactive data dictionary

Bayesian Spatial Synthetic Control in Python: California's Proposition 99

The Abadie et al. (2010) tobacco panel — 39 US states, 1970–2000 — together with the rook-contiguity weights that let a synthetic control estimate who ELSE was treated.

3
datasets
39
states
1,209
panel rows
1
donor bordering CA

Downloads

Each dataset is available as a labeled Stata .dta and its source file.

⇩ Download all data (ZIP)stata_codebook.do

DatasetGrainRowsStataSource
python_sc_bayes_spatial_source_datastate-year1,209 × 6python_sc_bayes_spatial_source_data.dtapython_sc_bayes_spatial_source_data.csv
python_sc_bayes_spatial_spatial_edgesordered state pair150 × 3python_sc_bayes_spatial_spatial_edges.dtapython_sc_bayes_spatial_spatial_edges.csv
python_sc_bayes_spatial_spatial_summarystate38 × 5python_sc_bayes_spatial_spatial_summary.dtapython_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
notes

Python

!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.

Three files. 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

SourceProvidesReference / URL
Abadie, Diamond &amp; Hainmueller (2010)The California tobacco panel (cigsale, retprice) and the synthetic control method itselfAbadie, 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 &amp; Tagawa (2026)The Bayesian spatial spillover model, and the replication package the panel and weights are exported fromSakaguchi, 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/LineThe 2024 state boundary shapefile from which rook contiguity is derivedUS Census Bureau (2024). TIGER/Line Shapefiles: States. Contiguity computed with spdep::poly2nb(queen = FALSE).
SoftwareEstimatorsscspill 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/utag006

BibTeX

@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.

VariableTypeDistributionLabelDefinitionUnitsIn filesSource
borders_california#dummyshare coded 1 = 0.026Borders California (flag)Integer duplicate of w_california, for convenience when filtering.0/1python_sc_bayes_spatial_spatial_summaryDerived
cigsale#continuousmin 40.7 | median 116 | max 296Per-capita cigarette sales (packs)Annual per-capita cigarette pack sales. This is the synthetic-control outcome.packs per capita per yearpython_sc_bayes_spatial_source_dataAbadie et al. (2010) via scspill
contiguous#dummyshare coded 1 = 1.000Shares a land borderAlways 1 in this file — zero-contiguity pairs are omitted rather than stored.0/1python_sc_bayes_spatial_spatial_edgesTIGER/Line 2024 boundaries
degree#continuousmin 1 | median 4 | max 8Number of neighbouring donorsHow many other donor states this state borders. Its row sum in W.countpython_sc_bayes_spatial_spatial_summaryDerived from the contiguity matrix
neighbour_list#identifierComma-separated neighbour namesThe donor states this state borders, listed alphabetically. Human-readable form of the edge list.stringpython_sc_bayes_spatial_spatial_summaryDerived from the contiguity matrix
retprice#continuousmin 27.3 | median 95.5 | max 351Real retail cigarette priceAverage retail price per pack. The single covariate entering the SAR layer.cents per packpython_sc_bayes_spatial_source_dataAbadie et al. (2010) via scspill
state#identifierState nameUS state identifier. The treated unit is California; the other 38 states are donors.stringpython_sc_bayes_spatial_source_data, python_sc_bayes_spatial_spatial_summaryscspill package (Abadie et al. 2010)
state_i#identifierOrigin state of the contiguity pairThe donor state whose neighbour is recorded in state_j.stringpython_sc_bayes_spatial_spatial_edgesTIGER/Line 2024 boundaries, spdep::poly2nb(queen = FALSE)
state_id#identifierState numeric IDInteger index for the state (1-39).integer (1-39)python_sc_bayes_spatial_source_datascspill package
state_j#identifierNeighbour state of the contiguity pairA donor state sharing a land border with state_i.stringpython_sc_bayes_spatial_spatial_edgesTIGER/Line 2024 boundaries, spdep::poly2nb(queen = FALSE)
treated#dummyshare coded 1 = 0.011Treatment indicator1 for California from 1988 onward; 0 otherwise. Note this is 1988, not 1989 — see the caveats.0/1python_sc_bayes_spatial_source_dataConstructed
w_california#dummyshare coded 1 = 0.026Contiguity with California1 if this donor borders California, 0 otherwise. THIS IS the w vector of the SAR model.0/1python_sc_bayes_spatial_spatial_summaryTIGER/Line 2024 boundaries
year#yearCalendar yearAnnual time index of the panel.yearpython_sc_bayes_spatial_source_datascspill package (Abadie et al. 2010)

Cross-file variable index

Which file each variable appears in (● = present).

Variablepython_sc_bayes_spatial_source_datapython_sc_bayes_spatial_spatial_edgespython_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:

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

state-year  1,209 × 6 · 1970-2000 · 39 US states (balanced)

Panel key: state (state_id) x year · Fit classical, Bayesian-horseshoe and Bayesian-spatial synthetic control for California's Proposition 99 ATT.

Variable dictionary

VariableLabelDefinitionConstructionUnitsSourceCoverage
state identifierState nameUS state identifier. The treated unit is California; the other 38 states are donors.From the scspill package panel (Abadie et al. 2010).stringscspill package (Abadie et al. 2010)39 states in the panel, 38 in the spatial files
state_id identifierState numeric IDInteger index for the state (1-39).Sequential package index aligned to the alphabetical state list.integer (1-39)scspill package39 states
year yearCalendar yearAnnual time index of the panel.Observed year, 1970-2000 (balanced; 31 years per state).yearscspill package (Abadie et al. 2010)1970-2000
cigsale continuousPer-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 yearAbadie et al. (2010) via scspill1,209 observations, no missing
retprice continuousReal retail cigarette priceAverage 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 packAbadie et al. (2010) via scspill1,209 observations, no missing
treated dummyTreatment indicator1 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/1Constructed13 treated rows of 1,209

Distribution & statistics (click a header to sort)

VariableDistributionCoverageNDistinctMinMeanMedianMaxSD
state100%1,20939
state_id100%1,20939
year100%1,2093119701985.0198520008.95
cigsalemin 40.7 | median 116 | max 296100%1,20970340.70118.9116.3296.232.77
retpricemin 27.3 | median 95.5 | max 351100%1,20984927.30108.395.50351.264.38
treatedshare coded 1 = 0.011100%1,209200.01101.000.103

ordered state pair  150 × 3 · time-invariant · 38 donor states; 150 directed rows = 75 undirected borders

Panel key: state_i x state_j · The W matrix of the SAR layer: which donors are each other's neighbours.

Variable dictionary

VariableLabelDefinitionConstructionUnitsSourceCoverage
state_i identifierOrigin state of the contiguity pairThe donor state whose neighbour is recorded in state_j.Row index of the 38x38 rook contiguity matrix.stringTIGER/Line 2024 boundaries, spdep::poly2nb(queen = FALSE)38 donor states
state_j identifierNeighbour state of the contiguity pairA donor state sharing a land border with state_i.Column index of the 38x38 rook contiguity matrix, kept only where the entry is 1.stringTIGER/Line 2024 boundaries, spdep::poly2nb(queen = FALSE)38 donor states
contiguous dummyShares a land borderAlways 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/1TIGER/Line 2024 boundaries150 directed rows = 75 undirected borders

Distribution & statistics (click a header to sort)

VariableDistributionCoverageNDistinctMinMeanMedianMaxSD
state_i100%15038
state_j100%15038
contiguousshare coded 1 = 1.000100%15011.001.001.001.000

state  38 × 5 · time-invariant · 38 donor states

Panel key: state · The w vector of the SAR layer (exposure to the treated unit), plus each donor's position in the contiguity graph.

Variable dictionary

VariableLabelDefinitionConstructionUnitsSourceCoverage
state identifierState nameUS state identifier. The treated unit is California; the other 38 states are donors.From the scspill package panel (Abadie et al. 2010).stringscspill package (Abadie et al. 2010)39 states in the panel, 38 in the spatial files
degree continuousNumber of neighbouring donorsHow many other donor states this state borders. Its row sum in W.Row sum of the 38x38 rook contiguity matrix.countDerived from the contiguity matrixrange 1-8, mean 3.95
w_california dummyContiguity with California1 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/1TIGER/Line 2024 boundariesexactly one non-zero entry: Nevada
borders_california dummyBorders California (flag)Integer duplicate of w_california, for convenience when filtering.1 if w_california > 0.0/1Derived1 of 38 donors
neighbour_list identifierComma-separated neighbour namesThe 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.stringDerived from the contiguity matrix38 donor states

Distribution & statistics (click a header to sort)

VariableDistributionCoverageNDistinctMinMeanMedianMaxSD
state100%3838
degreemin 1 | median 4 | max 8100%3881.003.954.008.001.90
w_californiashare coded 1 = 0.026100%38200.02601.000.162
borders_californiashare coded 1 = 0.026100%38200.02601.000.162
neighbour_list100%3837

Known limitations & caveats