Castle Doctrine Example
This vignette applies Endid.jl to the Castle Doctrine dataset with staggered adoption timing.
Data Preparation
using Endid
using DataFrames
using CSV
using Statistics
using Plots
using Random
Random.seed!(42)
castle = CSV.read(joinpath(pkgdir(Endid), "vignettes", "data", "castle.csv"), DataFrame)
castle.gvar = [ismissing(y) || y == 0 ? missing : y for y in castle.effyear]
controls = ["poverty", "unemployrt", "blackm_15_24", "whitem_15_24"]
cohorts = combine(groupby(castle, :sid), :gvar => first => :gvar)
combine(groupby(cohorts, :gvar), :sid => length => :count)6×2 DataFrame
| Row | gvar | count |
|---|---|---|
| Int64? | Int64 | |
| 1 | 2005 | 1 |
| 2 | 2006 | 13 |
| 3 | 2007 | 4 |
| 4 | 2008 | 2 |
| 5 | 2009 | 1 |
| 6 | missing | 29 |
Distributional Estimation
fit_endid = endid_staggered(
castle,
:lhomicide,
:sid,
:year,
:gvar;
controls = controls,
rolling = "demean",
num_epochs = 100,
nboot = 5,
seed = 42,
)
println(fit_endid)┌ Warning: Cohort 2005: skipping (degenerate cross-section).
└ @ Endid ~/work/Endid.jl/Endid.jl/src/Endid.jl:339
Training Engression... 23%|██████▌ | ETA: 0:00:02
Training Engression... 100%|████████████████████████████| Time: 0:00:01
loss: 0.36839837
┌ Warning: Cohort 2009: skipping (degenerate cross-section).
└ @ Endid ~/work/Endid.jl/Endid.jl/src/Endid.jl:339
Endid Result (staggered design)
------------------------------
ATT Estimate: 0.1007
Std. Error : 0.034
95% CI : (0.0659, 0.1433)
Quantile Treatment Effects (QTE):
9×3 DataFrame
Row │ quantile effect se
│ Float64 Float64 Float64
─────┼────────────────────────────────
1 │ 0.1 0.0502398 0.0235922
2 │ 0.2 0.0484497 0.0203099
3 │ 0.3 0.0501444 0.0169832
4 │ 0.4 0.0518725 0.0136774
5 │ 0.5 0.0559127 0.0134986
6 │ 0.6 0.060126 0.0146324
7 │ 0.7 0.0718326 0.023724
8 │ 0.8 0.12527 0.0774524
9 │ 0.9 0.314252 0.161099Quantile Treatment Effects
p = plot(fit_endid)
savefig(p, "castle_qte.svg")
nothing