*********************************************
*AnalyzeWAVotersVBM.do
**
*Analyze the treatment effect of Washington counties who
*switched to all-mail elections on individual registrants,
*identifying heterogeneous treatment effects by individual
*characteristic.
**
*Note: this code is memory intensive, and requires a Stata version
*that can handle large matrices and memory.
**
*Alan Gerber, Gregory Huber, Seth Hill, "Identifying the Effects of Elections Held All-Mail on
*Turnout: Staggered Reform in the Evergreen State."
*********************************************

set more off
qui set mem 12g
qui set matsize 11000
capture set maxvar 7500
capture log close

*The minimum number of observations in a precinct for those cases used with fixed effects
local minsize 100
local mincellsize 20

log using StackedVBMAnalysis-logitandols_fe_minprecinctsize`minsize'_mincell`mincellsize'.log, text replace
di c(current_date)+ " " + c(current_time)

use PublicReplicationDataset.dta

**********************
* Because logit is having a hard time with the fixed effects, we want to manually eliminate small precincts and those with no variation in either VBM status or turnout
* This subset is indicated with the variable fixedeffectssample.
**********************

*Logit.
qui logit voted treatedXpriorpoll priorpoll2* priorvoteXelection2008 priorvoteXelection2010 if decaycase == 0, vce(cluster electioncountyfe)

*Precinct fixed effects only for those precincts that vary on dv voted, of size greater than `minsize', and with at least one prior absentee and one prior poll voter and variation in turnout within those cells
 gen fixedeffectssample=e(sample)
 tab fixedeffectssample
 *Minimum precinct size
 bys precinct: gen precinctsize = _N if fixedeffectssample==1
 replace fixedeffectssample=0 if fixedeffectssample==1 & precinctsize < `minsize'
 bys precinct priorpollingplace: gen precinctvbmsize = _N if fixedeffectssample==1
 replace fixedeffectssample=0 if fixedeffectssample==1 & precinctvbmsize < `mincellsize'
 replace fixedeffectssample=0 if fixedeffectssample==1 & (precinctsize-precinctvbmsize) < `mincellsize'
 tab fixedeffectssample
 sort precinct
 summ precinctsize if fixedeffectssample==1 & precinct~=precinct[_n-1], detail
 *Variation in turnout within vbm and precinct cell
 egen sdvoted = sd(voted) if fixedeffectssample==1, by(precinct priorpollingplace) 
 replace fixedeffectssample=0 if fixedeffectssample==1 & (sdvoted==. | sdvoted==0)
 tab fixedeffectssample
 *Variation in vbm within precinct
 egen sdpriorpoll = sd(priorpollingplace) if fixedeffectssample==1, by(precinct) 
 replace fixedeffectssample=0 if fixedeffectssample==1 & (sdpriorpoll==. | sdpriorpoll==0)
 tab fixedeffectssample
 drop precinctsize precinctvbmsize
 bys precinct: gen precinctsize = _N if fixedeffectssample==1
 replace fixedeffectssample=0 if fixedeffectssample==1 & precinctsize < `minsize'
 bys precinct priorpollingplace: gen precinctvbmsize = _N if fixedeffectssample==1
 replace fixedeffectssample=0 if fixedeffectssample==1 & precinctvbmsize < 25
 tab fixedeffectssample
 sort precinct
 summ precinctsize if fixedeffectssample==1 & precinct~=precinct[_n-1], detail
 
 qui tab precinct if fixedeffectssample==1, gen(pd_)
 drop pd_1

************************************************************************************************************************************************
************************************************************************************************************************************************
*Supplemental Individual-level analysis, Not used in paper
************************************************************************************************************************************************
************************************************************************************************************************************************
local columncounter 1
local outfile "SupplementalTableX_Individual_minpsize`minsize'_mincellsize`mincellsize'.out"

*****************************************************
*Models without precinct fixed effects, no covariates
*****************************************************
*Logit.
logit voted treatedXpriorpoll priorpoll2* priorvoteXelection2008 priorvoteXelection2010 if decaycase == 0, vce(cluster electioncountyfe)
  *Calculate marginal effect of treatment.
  preserve
  *Only what obs. from regression in marginal effects
  keep if e(sample)
  *Predicted turnout under observed values.
  predict preds, pr
  *Change treatment value for treatment cases to 0 and calculate new predicted value.
  replace treatedXpriorpoll = 0 if treatedcounty == 1
  predict preds_alt, pr
  gen treatmenteffect = preds - preds_alt
  *Average treatment effect on the treated.
  summ treatmenteffect if treatedcounty == 1 & decaycase == 0 & priorpollingplace == 1
  local res = `r(mean)'
  restore
outreg using "`outfile'", se ctitle("All Registrants, Logit") addstat("Precinct-Election fixed effects",0,"Average treatment effect on the treated",`res') adec(4) bracket rdec(3) 3aster replace
  *Grab number of cases per specification, associate with this column.
  levelsof electioncounty, local(elections)
  foreach i of local elections {
    qui count if electioncounty == "`i'" & e(sample) == 1
    local `i'_`columncounter' = `r(N)'
  }
  local columncounter = `columncounter' + 1
*Capture sample used in the logit.
qui gen logitsample = e(sample)

*OLS.
reg voted treatedXpriorpoll priorpoll2* priorvoteXelection2008 priorvoteXelection2010 if decaycase == 0 & logitsample == 1, vce(cluster electioncountyfe)
outreg using "`outfile'", se ctitle("All Registrants, OLS") addstat("Precinct-Election fixed effects",0) adec(4) bracket rdec(3) 3aster append
  *Grab number of cases per specification, associate with this column.
  levelsof electioncounty, local(elections)
  foreach i of local elections {
    qui count if electioncounty == "`i'" & e(sample) == 1
    local `i'_`columncounter' = `r(N)'
  }
  local columncounter = `columncounter' + 1
  
*****************************************************
*Models without precinct fixed effects with covariates.
*****************************************************
*Logit.
logit voted treatedXpriorpoll priorpoll2* priorvoteXelection2008 priorvoteXelection2010 maleX* age*X* if decaycase == 0, vce(cluster electioncountyfe)
  *Calculate marginal effect of treatment.
  preserve
  *Predicted turnout under observed values.
  predict preds, pr
  *Change treatment value for treatment cases to 0 and calculate new predicted value.
  replace treatedXpriorpoll = 0 if treatedcounty == 1
  predict preds_alt, pr
  gen treatmenteffect = preds - preds_alt
  *Average treatment effect on the treated.
  summ treatmenteffect if treatedcounty == 1 & decaycase == 0 & priorpollingplace == 1
  local res = `r(mean)'
  restore
outreg using "`outfile'", se ctitle("All Registrants, Logit") addstat("Precinct-Election fixed effects",0,"Average treatment effect on the treated",`res') adec(4) bracket rdec(3) 3aster append
  *Grab number of cases per specification, associate with this column.
  levelsof electioncounty, local(elections)
  foreach i of local elections {
    qui count if electioncounty == "`i'" & e(sample) == 1
    local `i'_`columncounter' = `r(N)'
  }
  local columncounter = `columncounter' + 1

*OLS.
reg voted treatedXpriorpoll priorpoll2* priorvoteXelection2008 priorvoteXelection2010 maleX* age*X* if decaycase == 0 & logitsample == 1, vce(cluster electioncountyfe)
outreg using "`outfile'", se ctitle("All Registrants, OLS") addstat("Precinct-Election fixed effects",0) adec(4) bracket rdec(3) 3aster append
  *Grab number of cases per specification, associate with this column.
  levelsof electioncounty, local(elections)
  foreach i of local elections {
    qui count if electioncounty == "`i'" & e(sample) == 1
    local `i'_`columncounter' = `r(N)'
  }
  local columncounter = `columncounter' + 1

*****************************************************
*FE Sample, no covariates
***************************************************** 
 
*Models without precinct fixed effects, fixed effects sample
*Logit.
logit voted treatedXpriorpoll priorpoll2* priorvoteXelection2008 priorvoteXelection2010 if fixedeffectssample==1 , vce(cluster electioncountyfe)
  *Calculate marginal effect of treatment.
  preserve
  *Only what obs. from regression in marginal effects
  keep if e(sample)
  *Predicted turnout under observed values.
  predict preds, pr
  *Change treatment value for treatment cases to 0 and calculate new predicted value.
  replace treatedXpriorpoll = 0 if treatedcounty == 1
  predict preds_alt, pr
  gen treatmenteffect = preds - preds_alt
  *Average treatment effect on the treated.
  summ treatmenteffect if treatedcounty == 1 & decaycase == 0 & priorpollingplace == 1
  local res = `r(mean)'
  restore
outreg using "`outfile'", se ctitle("FE Sample, All Registrants, Logit") addstat("Precinct-Election fixed effects",0,"Average treatment effect on the treated",`res') adec(4) bracket rdec(3) 3aster append
  *Grab number of cases per specification, associate with this column.
  levelsof electioncounty, local(elections)
  foreach i of local elections {
    qui count if electioncounty == "`i'" & e(sample) == 1
    local `i'_`columncounter' = `r(N)'
  }
  local columncounter = `columncounter' + 1

*OLS.
reg voted treatedXpriorpoll priorpoll2* priorvoteXelection2008 priorvoteXelection2010 if fixedeffectssample==1, vce(cluster electioncountyfe)
outreg using "`outfile'", se ctitle("FE Sample, All Registrants, OLS") addstat("Precinct-Election fixed effects",0) adec(4) bracket rdec(3) 3aster append
  *Grab number of cases per specification, associate with this column.
  levelsof electioncounty, local(elections)
  foreach i of local elections {
    qui count if electioncounty == "`i'" & e(sample) == 1
    local `i'_`columncounter' = `r(N)'
  }
   
*******************************
*Write out county-election sample sizes to stacked models frame.
********************************
file open myfile using "`outfile'", write append
levelsof electioncounty, local(elections)
foreach i of local elections {
  file write myfile "`i' cases in model" _tab
  forvalues j = 1/`columncounter' {
    local val ``i'_`j''
    file write myfile "`val'" _tab
  }
  file write myfile _n
}
file close myfile

************************************************************************************************************************************************
************************************************************************************************************************************************
*Individual-level analysis
************************************************************************************************************************************************
************************************************************************************************************************************************
local columncounter 1
local outfile "Table05_Individual_minpsize`minsize'_mincellsize`mincellsize'.out"
 
*****************************************************
*Models with precinct fixed effects, no covariates
***************************************************** 
 
*Models with precinct fixed effects.
*Logit.
logit voted treatedXpriorpoll priorpoll2* priorvoteXelection2008 priorvoteXelection2010 pd_* if fixedeffectssample==1, robust cluster(electioncountyfe) 
  *Calculate marginal effect of treatment.
  preserve
  *Only what obs. from regression in marginal effects
  keep if e(sample)
  *Predicted turnout under observed values.
  predict preds, pr
  *Change treatment value for treatment cases to 0 and calculate new predicted value.
  replace treatedXpriorpoll = 0 if treatedcounty == 1
  predict preds_alt, pr
  gen treatmenteffect = preds - preds_alt
  *Average treatment effect on the treated.
  summ treatmenteffect if treatedcounty == 1 & decaycase == 0 & priorpollingplace == 1
  local res = `r(mean)'
  restore
outreg treatedXpriorpoll priorpoll2* priorvoteXelection2008 priorvoteXelection2010 using "`outfile'", se ctitle("All Registrants, Logit") addstat("Precinct-Election fixed effects",1,"Average treatment effect on the treated",`res') adec(4) bracket rdec(3) 3aster replace
  *Grab number of cases per specification, associate with this column.
  levelsof electioncounty, local(elections)
  foreach i of local elections {
    qui count if electioncounty == "`i'" & e(sample) == 1
    local `i'_`columncounter' = `r(N)'
  }
  local columncounter = `columncounter' + 1

*OLS.
xtreg voted treatedXpriorpoll priorpoll2* priorvoteXelection2008 priorvoteXelection2010 if fixedeffectssample==1 , vce(cluster electioncountyfe) fe i(precinct)
outreg using "`outfile'", se ctitle("All Registrants, OLS") addstat("Precinct-Election fixed effects",1) adec(4) bracket rdec(3) 3aster append
  *Grab number of cases per specification, associate with this column.
  levelsof electioncounty, local(elections)
  foreach i of local elections {
    qui count if electioncounty == "`i'" & e(sample) == 1
    local `i'_`columncounter' = `r(N)'
  }
  local columncounter = `columncounter' + 1

*****************************************************
*Models with precinct fixed effects, with covariates
***************************************************** 

*Logit.
logit voted treatedXpriorpoll priorpoll2* priorvoteXelection2008 priorvoteXelection2010 maleX* age*X* pd_* if fixedeffectssample==1, robust cluster(electioncountyfe) 
  *Calculate marginal effect of treatment.
  preserve
  *Only what obs. from regression in marginal effects
  keep if e(sample)
  *Predicted turnout under observed values.
  predict preds, pr
  *Change treatment value for treatment cases to 0 and calculate new predicted value.
  replace treatedXpriorpoll = 0 if treatedcounty == 1
  predict preds_alt, pr
  gen treatmenteffect = preds - preds_alt
  *Average treatment effect on the treated.
  summ treatmenteffect if treatedcounty == 1 & decaycase == 0 & priorpollingplace == 1
  local res = `r(mean)'
  restore
outreg treatedXpriorpoll priorpoll2* priorvoteXelection2008 priorvoteXelection2010 maleX* age*X* using "`outfile'", se ctitle("All Registrants, Logit") addstat("Precinct-Election fixed effects",1,"Average treatment effect on the treated",`res') adec(4) bracket rdec(3) 3aster append
  *Grab number of cases per specification, associate with this column.
  levelsof electioncounty, local(elections)
  foreach i of local elections {
    qui count if electioncounty == "`i'" & e(sample) == 1
    local `i'_`columncounter' = `r(N)'
  }
  local columncounter = `columncounter' + 1

*OLS.
xtreg voted treatedXpriorpoll priorpoll2* priorvoteXelection2008 priorvoteXelection2010 maleX* age*X* if fixedeffectssample==1 , vce(cluster electioncountyfe) fe i(precinct)
outreg using "`outfile'", se ctitle("All Registrants, OLS") addstat("Precinct-Election fixed effects",1) adec(4) bracket rdec(3) 3aster append
  *Grab number of cases per specification, associate with this column.
  levelsof electioncounty, local(elections)
  foreach i of local elections {
    qui count if electioncounty == "`i'" & e(sample) == 1
    local `i'_`columncounter' = `r(N)'
  }
  
*******************************
*Write out county-election sample sizes to stacked models frame.
********************************
file open myfile using "`outfile'", write append
levelsof electioncounty, local(elections)
foreach i of local elections {
  file write myfile "`i' cases in model" _tab
  forvalues j = 1/`columncounter' {
    local val ``i'_`j''
    file write myfile "`val'" _tab
  }
  file write myfile _n
}
file close myfile
*/

************************************************************************************************************************************************
************************************************************************************************************************************************
*Heterogeneous effects, age. Only in appendix
************************************************************************************************************************************************
************************************************************************************************************************************************
local columncounter 1
local logitoutfile "TableA07_AgeHeterogeneous_logit_minpsize`minsize'_mincellsize`mincellsize'.out"
local olsoutfile "TableA08_AgeHeterogeneous_ols_minpsize`minsize'_mincellsize`mincellsize'.out"

********************************
*By age bins.
********************************

qui levelsof agecat, local(agevalues)
foreach i of local agevalues {
  local repl "append"
  if (`i' == 1) { 
    local repl "replace" 
  }

  local categ : label(agecat) `i', strict
  
  di _n
  di "Sample is Ages `categ'"
  di _n
  
  logit voted treatedXpriorpoll priorpoll2* priorvoteXelection2008 priorvoteXelection2010 maleX* age*X* pd_* if fixedeffectssample==1 & agecat == `i', vce(cluster electioncountyfe)
    *Calculate marginal effect of treatment.
    preserve
    keep if e(sample)
	*Predicted turnout under observed values.
    predict preds, pr
    *Change treatment value for treatment cases to 0 and calculate new predicted value.
    replace treatedXpriorpoll = 0 if treatedcounty == 1
    predict preds_alt, pr
    gen treatmenteffect = preds - preds_alt
    *Average treatment effect on the treated.
    summ treatmenteffect if treatedcounty == 1 & decaycase == 0 & agecat == `i' & priorpollingplace == 1
    local res = `r(mean)'
    restore
  outreg treatedXpriorpoll priorpoll2* priorvoteXelection2008 priorvoteXelection2010 maleX* age*X* using "`logitoutfile'", se ctitle("Ages `categ'") addstat("Precinct-Election fixed effects",1,"Average treatment effect on the treated",`res') adec(4) bracket rdec(3) 3aster `repl'

  xtreg voted treatedXpriorpoll priorpoll2* priorvoteXelection2008 priorvoteXelection2010 maleX* age*X* if e(sample), vce(cluster electioncountyfe) fe i(precinct)	
  outreg using "`olsoutfile'", se ctitle("Ages `categ'") addstat("Precinct-Election fixed effects",1) adec(4) bracket rdec(3) 3aster `repl'
    *Grab OLS Treatment Effect to put in logit table
    local olseffect_`columncounter'=_b[treatedXpriorpoll]
	local olseffectse_`columncounter'=_se[treatedXpriorpoll]
    *Grab number of cases per specification, associate with this column.
	qui levelsof electioncounty, local(elections)
    foreach j of local elections {
      qui count if electioncounty == "`j'" & e(sample) == 1
      local `j'_`columncounter' = `r(N)'
    }
    local columncounter = `columncounter' + 1   
	
}

********************************
*Write out county-election sample sizes to heterogeneous models frame.
********************************
*Decrement columncounter from most recent increment.
local maxcols=`columncounter'-1

file open myfile using "`logitoutfile'", write append
local columncounter = `maxcols'

file write myfile "OLS Treatment Effect" _tab
forvalues j = 1/`columncounter' {
    local val `olseffect_`j''
    file write myfile "`val'" _tab
  }
  file write myfile _n
  
file write myfile "OLS SE" _tab
forvalues j = 1/`columncounter' {
    local val `olseffectse_`j''
    file write myfile "`val'" _tab
  }
  file write myfile _n
    
levelsof electioncounty, local(elections)
foreach i of local elections {
  file write myfile "`i' cases in model" _tab
  forvalues j = 1/`columncounter' {
    local val ``i'_`j''
    file write myfile "`val'" _tab
  }
  file write myfile _n
}
file close myfile

file open myfile using "`olsoutfile'", write append
local columncounter = `maxcols'

levelsof electioncounty, local(elections)
foreach i of local elections {
  file write myfile "`i' cases in model" _tab
  forvalues j = 1/`columncounter' {
    local val ``i'_`j''
    file write myfile "`val'" _tab
  }
  file write myfile _n
}
file close myfile
*/
************************************************************************************************************************************************
************************************************************************************************************************************************
*Heterogeneous effects, prior vote history.
************************************************************************************************************************************************
************************************************************************************************************************************************
local columncounter 1
local logitoutfile "Table06_VoteHistoryHeterogeneous_logit_minpsize`minsize'_mincellsize`mincellsize'.out"
local olsoutfile "TableA06_VoteHistoryHeterogeneous_ols_minpsize`minsize'_mincellsize`mincellsize'.out"

********************************
*Separately by prior vote history in 06 07 08. Only for 2010 turnout.
********************************

* Need to redo fixed effects here, because sample is different

**********************
* Because logit is having a hard time with the fixed effects, we want to manually eliminate small precincts and those with no variation in either VBM status or turnout
* This subset is indicated with the variable fixedeffectssample
**********************

*Logit.
qui logit voted treatedXpriorpoll priorpoll2* priorvoteXelection2010 if fixedeffectssample==1 & electionyear == 2010, vce(cluster electioncountyfe)
replace fixedeffectssample=e(sample)
drop pd_*
qui tab precinct if fixedeffectssample==1, gen(pd_)
drop pd_1

levelsof votehiststring, local(vhvalues)
foreach i of local vhvalues {
  
  local repl "append"
  if (`i' == 1) { 
    local repl "replace" 
  }
  local categ : label(votehiststring) `i', strict
  
  di _n
  di "Sample is `categ'"
  di _n
  
  
  logit voted treatedXpriorpoll priorpoll2008 maleXelection2010 ageXelection2010 age_sqXelection2010 pd_* if fixedeffectssample==1 & votehiststring == `i' & electionyear == 2010, vce(cluster electioncountyfe)
    *Calculate marginal effect of treatment.
    preserve
	keep if e(sample)
    *Predicted turnout under observed values.
    predict preds, pr
    *Change treatment value for treatment cases to 0 and calculate new predicted value.
    replace treatedXpriorpoll = 0 if treatedcounty == 1
    predict preds_alt, pr
    gen treatmenteffect = preds - preds_alt
    *Average treatment effect on the treated.
    summ treatmenteffect if treatedcounty == 1 & decaycase == 0 & votehiststring == `i' & electionyear == 2010 & priorpollingplace == 1
    local res = `r(mean)'
    restore
  outreg treatedXpriorpoll priorpoll2008 maleXelection2010 ageXelection2010 age_sqXelection2010 using "`logitoutfile'", se ctitle("`categ'") addstat("Precinct-Election fixed effects",1,"Average treatment effect on the treated",`res') adec(4) bracket rdec(3) 3aster `repl'
  
  xtreg voted treatedXpriorpoll priorpoll2008 maleXelection2010 ageXelection2010 age_sqXelection2010 if e(sample), vce(cluster electioncountyfe) fe i(precinct)		
  outreg using "`olsoutfile'", se ctitle("`categ'") addstat("Precinct-Election fixed effects",1) adec(4) bracket rdec(3) 3aster `repl'
    *Grab OLS Treatment Effect to put in logit table
    local olseffect_`columncounter'=_b[treatedXpriorpoll]
	local olseffectse_`columncounter'=_se[treatedXpriorpoll]
    *Grab number of cases per specification, associate with this column.
	qui levelsof electioncounty, local(elections)
    foreach j of local elections {
      qui count if electioncounty == "`j'" & e(sample) == 1
      local `j'_`columncounter' = `r(N)'
    }
    local columncounter = `columncounter' + 1   
	
}

********************************
*Write out county-election sample sizes to heterogeneous models frame.
********************************
*Decrement columncounter from most recent increment.
local maxcols=`columncounter'-1

file open myfile using "`logitoutfile'", write append
local columncounter = `maxcols'

file write myfile "OLS Treatment Effect" _tab
forvalues j = 1/`columncounter' {
    local val `olseffect_`j''
    file write myfile "`val'" _tab
  }
  file write myfile _n

file write myfile "OLS SE" _tab
forvalues j = 1/`columncounter' {
    local val `olseffectse_`j''
    file write myfile "`val'" _tab
  }
  file write myfile _n  
  
levelsof electioncounty, local(elections)
foreach i of local elections {
  file write myfile "`i' cases in model" _tab
  forvalues j = 1/`columncounter' {
    local val ``i'_`j''
    file write myfile "`val'" _tab
  }
  file write myfile _n
}
file close myfile

file open myfile using "`olsoutfile'", write append
local columncounter = `maxcols'

levelsof electioncounty, local(elections)
foreach i of local elections {
  file write myfile "`i' cases in model" _tab
  forvalues j = 1/`columncounter' {
    local val ``i'_`j''
    file write myfile "`val'" _tab
  }
  file write myfile _n
}
file close myfile

log close
