Package: op-verification
Verification of Election ShapefilesThis verification script generates a report that compares aPrecinct-Level Election Shapefilewith expected election results and geometries.SourcesExpected election results (for 2016 Data) are sourced fromMIT Election Data + Science Lab (MEDSL)Expected geometries are sourced fromThe United States Census Bureauand theAlaska Division of ElectionsUsageInputs and OutputsInput:state_prec_gdf(GeoDataFrame) containing precinct geometries and election results.state_abbreviation(str) e.g. 'MA' for Massachusettssource(str) person or organization that made the 'state_prec_gdf' e.g 'VEST'county_level_results_df(DataFrame) containing official county-level election resultsoffice(str) office to be evaluated in vote validation e.g. 'U.S. Senate'year(str) 'YYYY' indicating the year the election took place e.g. '2016'd_col(str) denotes the column for democratic vote counts in each precinctr_col(str) denotes the column for republican vote counts in each precinctpath(str) filepath to which the report should be saved (if None it won't be saved)Output:state_report(StateReport) for thestate_prec_gdfcounty_reports((CountyReport) list) for thestate_prec_gdfSchemasPay close attention to the name anddtypeof your columns to ensure the script works correctly. It's permissible to include more columns than those listed here (they will just be ignored by the script).state_prec_gdf:Column Namedtypeexampled_colint5936r_colint6395geometrygeometryPOLYGON ((-71.99365 44.49649, -71.99262 44.496...GEOIDobject'01001'GEOID is optional forstate_prec_gdf, but strongly reccomended.Learn more...county_level_results_df:Column Namedtypeexamplecountyobject'Essex County'GEOIDobject'01001'partyobject'democrat' or 'republican'votesint5936Thecounty_level_results_dfDataFrame should only contain results for theofficethat's passed as an input.GEOID/County assignment for each precinctWikipedia linkThis script compares precinct level election results from thestate_prec_gdfwith the expected election results from official state election data records at the state and county level. In both cases the precinct level results are aggregated up to their state and county respectively and then compared to the expected results. Likewise, the precinct geometries are aggregated up to the county level and compared with the county shapefiles from the US Census Bureau.In order to do the comparisons detailed above, the script needs to know about the makeup ofstate_prec_gdf. Specifically, it needs to know the county (or equivalent) for each precinct and which columns correspond with the votes for the Democratic and Republican candidate for each precinct.The precincts need to be assigned a county in the form of the county's 5 digit GEOID code described below:GEOID SPECElements of the GEOID column are 5 character strings. The first 2 characters
are the StateFP code and the last 3 characters are the CountyFP code. e.g.Massachusetts' StateFP = '25'Essex County's CountyFP = '009'Essex County, Massachusetts' GEODID = '25009'If either code has fewer digits than are allocated, the string representation should
be zero-padded from the left. e.g. Alaska (StateFP = 2) should be '02'.The GEOID may be given for each precinct instate_prec_gdffile. In this case, the column must conform to the spec above and be named'GEOID'. If the GEOID column is missing then the script will attempt to create it using theMAUP packageto assign each precinct to the county which contains it. Omission of the GEOID label in the input file and failure to assign counties with MAUP (e.g. script throws an exception) will result in the report skipping county level metrics (denoted with -1 metric values).Candidate vote countsThe script needs to know which column contains votes for the Democratic and Republican candidate(s) being reviewed by the script. They can be manually entered as arguments:d_coldenotes the column for Democratic vote counts in each precinctr_coldenotes the column for Republican vote counts in each precinct.Without those arguments, the script will guess based on the expected number of votes for each candidate.Election Year reccomendations2016 Precinct-Level Election ShapefilesTheverify.verify_state_2016(...)function will callverify.verify_state(...)and automatically apply 2016 specific defaults:Uses Official County Results from the 2016 Presidential Election already in this repositorySets year to '2016'Sets office to 'President'Using this funciton for a 2016 Precinct-Level Election Shapefile has the benefit of standardizing 2016 reports. Moreover, it saves you the time of finding official county level results and conforming the data to the expected schema for input data.Non-2016 Precinct-Level Election ShapefileFor non-2016 Precinct-Level Election Shapefiles, you do need to supply a schema-conformingcounty_level_results_dftoverify.verify_state(...). I reccomend looking on the Department of State website for the state being validated. For example, I found official county results for Pennsylannia's 2018 electionhereCheckoutVerification Example Notebook.ipynbfor examples of both cases.Verification Report BreakdownQuality ScoresVote ScoreCompute the ratio of votes observed instate_prec_gdfto the votes expected (based on official state election data records incounty_level_results_df) for the democratic and republican candidate. Then the Vote Score is the weighted average of these ratios.Python ImplementationIdeally Vote Score = 1A Vote Score above 1 indicates that theInputcontains more recorded votes than the official state election dataA Vote Score below 1 indicates that theInputcontains fewer recorded votes than the official state election data.County Vote Score DispersionFor each county, compute the square of the difference between the expected number of votes for the democratic and republican candidate. Then, County Vote Score Dispersion is the average of the square difference across all the counties in the state.Python ImplementationIdeally County Vote Score Dispersion = 0As the County Vote Score Dispersion increases, so does the degree to which theInputdiffers with respect to official state election data records about the county-level results.Area Difference ScoreCompute the symmetric difference between theInput'sgeometries and the expected geometries for that state from the Census Bureau. Then Area Difference Score is the ratio of the symmetric difference's area to the area of the precinct shapefiles.Python ImplementationIdeally Area Difference Score is 0As the Area Difference Score increases it indicates a greater geometric difference between the observed geometry in theInputand the expected geometry.An Area Difference Score of -1 indicates an error was encountered when attempting to compute the metric. Therefore, it is the worst value possible for the Area Difference score.Library CompatibilityCheck theInputfor compatibility with libraries and packages that we hope our end users will be able to apply to the map.can_use_maup:(boolean)Can useMAUP, a geospatial toolkit for redistricting data.can_use_gerrychain:(boolean)Can useGerrychainwhich is useful for applying sensitivity testing via Markov chain Monte Carlo sampling.Raw Datan_votes_democrat_expected:(int)number of votes for the democratic candidate in MEDSL datasetn_votes_republican_expected:(int)number of votes for the republican candidate in MEDSL datasetn_two_party_votes_expected:(int)n_votes_republican_expected + n_votes_republican_expectedn_votes_democrat_observed:(int)number of votes for the democratic candidate in theInputn_votes_republican_observed:(int)number of votes for the republican candidate in theInputn_two_party_votes_observed:(int)n_votes_democrat_observed + n_votes_republican_observedall_precincts_have_a_geometry:(int)every precinct has a valid geometry