Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
| sidebar_position: 7 | |
| displayed_sidebar: developersSidebar | |
| # Ballot Measures & Election Results | |
| Official data sources for tracking ballot initiatives, referendums, propositions, and election outcomes. Essential for monitoring water fluoridation votes, school bond measures, health policy propositions, and other civic engagement opportunities. | |
| ## π Data Scale & Coverage | |
| | Data Type | Source | Coverage | Cost | | |
| |-----------|--------|----------|------| | |
| | **Ballot Measures** | Ballotpedia | All states, historical | API limited (paid at scale) | | |
| | **Election Results** | MIT Election Lab | Presidential/Congressional | Free | | |
| | **Certified Results** | OpenElections | State-by-state | Free (CSV) | | |
| --- | |
| ## π³οΈ Primary Data Sources | |
| ### 1. Ballotpedia β **Most Comprehensive** | |
| **Organization:** Lucy Burns Institute | |
| **URL:** https://ballotpedia.org/ | |
| **API:** https://ballotpedia.org/API-documentation | |
| **What It Contains:** | |
| - **State ballot measures** - Propositions, referendums, constitutional amendments | |
| - **Local ballot measures** - City/county questions, bond issues, tax levies | |
| - **Initiative campaigns** - Signature gathering, qualification status | |
| - **Election results** - Historical outcomes, vote counts, passage status | |
| - **Full text** - Complete measure language and official summaries | |
| - **Timeline data** - Filing dates, election dates, certification dates | |
| **Coverage:** | |
| - β All 50 states + DC | |
| - β Historical data back to 1990s | |
| - β Local measures in major cities | |
| - β Water fluoridation votes (highly relevant!) | |
| - β School bond measures | |
| - β Tax and spending propositions | |
| **API Access:** | |
| - **Free tier:** Limited queries (suitable for testing) | |
| - **Paid tier:** Full API access required for production scale | |
| - **Alternative:** Web scraping (permitted with rate limiting) | |
| **How We Use It:** | |
| ```python | |
| # Example: Find fluoridation ballot measures | |
| import requests | |
| # Ballotpedia search (web scraping approach) | |
| def search_fluoridation_measures(state_code, year): | |
| """Search for water fluoridation ballot measures""" | |
| base_url = "https://ballotpedia.org" | |
| search_query = f"{state_code} fluoridation ballot measure {year}" | |
| # Return measure details | |
| return { | |
| 'measure_id': 'CA-2024-PROP-15', | |
| 'jurisdiction_id': 'ocd-division/country:us/state:ca', | |
| 'title': 'Water Fluoridation Mandate', | |
| 'election_date': '2024-11-05', | |
| 'result': 'passed', | |
| 'yes_percentage': 67.2, | |
| 'ballotpedia_url': 'https://ballotpedia.org/...' | |
| } | |
| ``` | |
| **Data Model Integration:** | |
| ```sql | |
| -- BALLOT_MEASURE entity includes: | |
| ballotpedia_url TEXT -- Direct link to Ballotpedia page | |
| measure_number TEXT -- e.g., "Proposition 15", "Question 2" | |
| result TEXT -- passed, failed, pending | |
| yes_votes INTEGER | |
| no_votes INTEGER | |
| yes_percentage FLOAT | |
| ``` | |
| **Use Cases:** | |
| - β Track fluoridation votes across all states | |
| - β Monitor school bond elections (dental program funding) | |
| - β Alert advocates when measures qualify for ballot | |
| - β Historical analysis of health policy votes | |
| --- | |
| ### 2. MIT Election Data + Science Lab | |
| **Organization:** Massachusetts Institute of Technology | |
| **URL:** https://electionlab.mit.edu/data | |
| **Repository:** https://github.com/MEDSL/official-returns | |
| **What It Contains:** | |
| - **Presidential election results** (1976-2020) by state and county | |
| - **U.S. Senate election results** (1976-2020) | |
| - **U.S. House election results** (1976-2020) | |
| - **Gubernatorial elections** (1976-2020) | |
| - **County-level results** - Granular vote totals | |
| - **Certified official results** - From Secretaries of State | |
| **Coverage:** | |
| - β Federal elections only (not ballot measures) | |
| - β All 50 states + DC | |
| - β County-level granularity | |
| - β Historical trends (45+ years) | |
| - β 100% free bulk downloads | |
| **Format:** | |
| - **CSV files** - Easy to ingest | |
| - **Standardized schema** - Consistent across states | |
| - **Annual updates** - New elections added promptly | |
| **How We Use It:** | |
| ```python | |
| import pandas as pd | |
| # Download county-level presidential results | |
| url = "https://dataverse.harvard.edu/api/access/datafile/4299753" | |
| df = pd.read_csv(url) | |
| # Filter for specific state/county | |
| results = df[ | |
| (df['state'] == 'NORTH CAROLINA') & | |
| (df['year'] == 2020) | |
| ] | |
| # Join with JURISDICTION data to link elections to jurisdictions | |
| merged = results.merge( | |
| jurisdictions_df, | |
| left_on=['state_po', 'county_name'], | |
| right_on=['state_code', 'county'] | |
| ) | |
| ``` | |
| **Data Model Integration:** | |
| ```sql | |
| -- Can link to JURISDICTION for context | |
| -- Useful for understanding political climate in each jurisdiction | |
| CREATE TABLE election_results ( | |
| result_id TEXT PRIMARY KEY, | |
| jurisdiction_id TEXT REFERENCES jurisdictions(jurisdiction_id), | |
| election_date DATE, | |
| office TEXT, -- President, Senate, House, etc. | |
| candidate TEXT, | |
| party TEXT, | |
| votes INTEGER, | |
| vote_percentage FLOAT | |
| ); | |
| ``` | |
| **Use Cases:** | |
| - β Understand political composition of jurisdictions | |
| - β Correlate election outcomes with policy decisions | |
| - β Identify swing counties for targeted advocacy | |
| - β Historical context for ballot measure success rates | |
| --- | |
| ### 3. OpenElections β **Free & Certified** | |
| **Organization:** Open Elections Project | |
| **URL:** https://openelections.net/ | |
| **GitHub:** https://github.com/openelections | |
| **What It Contains:** | |
| - **State-by-state certified election results** | |
| - **All offices** - Presidential, Congressional, State, Local | |
| - **All election types** - General, Primary, Special, Runoff | |
| - **Precinct-level data** - Highly granular (where available) | |
| - **Official certified results** - Directly from election officials | |
| - **Standardized CSV format** - Easy to parse and analyze | |
| **Coverage:** | |
| - β All 50 states (various completion levels) | |
| - β Presidential elections (nearly complete) | |
| - β Statewide races (good coverage) | |
| - β Local races (partial coverage) | |
| - β οΈ **Ballot measures coverage varies by state** | |
| **State Coverage Status:** | |
| See: https://github.com/openelections/openelections-data-ok | |
| **Format:** | |
| ```csv | |
| county,precinct,office,district,party,candidate,votes | |
| Wake,01-001,President,,DEM,Joe Biden,1234 | |
| Wake,01-001,President,,REP,Donald Trump,987 | |
| ``` | |
| **How We Use It:** | |
| ```python | |
| import pandas as pd | |
| # Download North Carolina 2020 results | |
| url = "https://raw.githubusercontent.com/openelections/openelections-data-nc/master/2020/20201103__nc__general__precinct.csv" | |
| df = pd.read_csv(url) | |
| # Filter for specific county | |
| wake_results = df[df['county'] == 'Wake'] | |
| # Aggregate by jurisdiction | |
| jurisdiction_totals = wake_results.groupby(['office', 'candidate']).agg({ | |
| 'votes': 'sum' | |
| }).reset_index() | |
| ``` | |
| **Data Model Integration:** | |
| ```sql | |
| -- Similar to MIT Election Lab, but more granular | |
| CREATE TABLE precinct_results ( | |
| result_id TEXT PRIMARY KEY, | |
| jurisdiction_id TEXT REFERENCES jurisdictions(jurisdiction_id), | |
| precinct_id TEXT, | |
| election_date DATE, | |
| office TEXT, | |
| district TEXT, | |
| party TEXT, | |
| candidate TEXT, | |
| votes INTEGER | |
| ); | |
| ``` | |
| **Use Cases:** | |
| - β Precinct-level advocacy targeting | |
| - β Voter turnout analysis | |
| - β Identify competitive jurisdictions | |
| - β Track local races (school board, city council) | |
| **Lakehouse Integration:** | |
| 1. **Bronze Layer** - Raw CSV downloads from GitHub | |
| 2. **Silver Layer** - Standardized, deduplicated results | |
| 3. **Gold Layer** - Aggregated to jurisdiction level with OCD-IDs | |
| 4. **Join with JURISDICTION** - Link elections to government entities | |
| --- | |
| ## ποΈ Local office elections (best sources) | |
| If your goal is **local offices** (mayors, city councils, county executives/legislatures, sheriffs, prosecutors, school boards), the most important distinction is: | |
| - **Historical results** (what happened) vs | |
| - **Upcoming/current ballot content** (what will be on the next ballot) | |
| There is no single free source that covers **upcoming/current ballot content** for all local jurisdictions at national scale. For truly current candidate/ballot measure data you typically either **pay** (commercial aggregators) or scrape **individual county election administrator** websites. | |
| ### 1. American Local Government Elections Database (ALGEE) β **Best single free source** | |
| A publicly available dataset covering **57,139 contests** and **77,853 unique candidates** across **1,747** cities, counties, prosecutor districts, and school districts (1989β2021). | |
| **Offices covered:** mayors, city councils, county executives, county legislatures, sheriffs, prosecutors, school boards. | |
| **Candidate attributes:** partisanship, gender, race/ethnicity, incumbency status. | |
| **Publication:** Nature / Scientific Data (downloadable for free). | |
| **Reference:** [Nature / Scientific Data paper](https://www.nature.com/articles/s41597-023-02792-x) | |
| **Dataset / project page:** [OSF overview](https://osf.io/mv5e6/overview) | |
| ### 2. Ballotpedia β School Board Elections CSV (2018β2024) | |
| Candidate-level dataset for school board election results from the **100 largest cities** and the **top 200 districts by enrollment**, available as **CSV** via Ballotpedia research publications (free download). | |
| ### 3. Our Campaigns (ourcampaigns.com) β scrapeable, not clean bulk | |
| Volunteer-contributed election results for many local county and municipal offices, typically in HTML tables and often with source links. | |
| **Trade-off:** broad coverage, but not a standardized bulk download β best treated as a scrape target. | |
| ## π― Fluoridation Vote Tracking (Use Case) | |
| **Goal:** Track all water fluoridation ballot measures across the United States | |
| **Data Sources Combination:** | |
| 1. **Ballotpedia** - Identify fluoridation measures, get full text | |
| 2. **OpenElections** - Get precinct-level results where available | |
| 3. **MIT Election Lab** - County-level context for political analysis | |
| **Example Query:** | |
| ```python | |
| # Find all fluoridation votes | |
| fluoridation_measures = ballot_measures_df[ | |
| ballot_measures_df['title'].str.contains('fluorid', case=False, na=False) | |
| ] | |
| # Get results | |
| for measure_id in fluoridation_measures['measure_id']: | |
| results = get_election_results(measure_id) | |
| # Alert advocates if measure is upcoming | |
| if results['status'] == 'qualified': | |
| send_advocacy_alert(measure_id) | |
| ``` | |
| --- | |
| ## π Data Availability Summary | |
| | Source | Ballot Measures | Election Results | Historical Data | Cost | Format | | |
| |--------|----------------|------------------|-----------------|------|--------| | |
| | **Ballotpedia** | β Comprehensive | β Yes | β 1990s+ | π° API paid | HTML/API | | |
| | **MIT Election Lab** | β No | β Federal only | β 1976+ | β Free | CSV | | |
| | **OpenElections** | β οΈ Varies by state | β All levels | β State-dependent | β Free | CSV | | |
| **Recommendation:** | |
| - Use **Ballotpedia** for ballot measure discovery and tracking | |
| - Use **OpenElections** for detailed precinct-level results (free) | |
| - Use **MIT Election Lab** for county-level political context (free) | |
| --- | |
| ## π Integration with Data Model | |
| ### BALLOT_MEASURE Entity | |
| ```mermaid | |
| erDiagram | |
| BALLOT_MEASURE { | |
| string measure_id PK | |
| string jurisdiction_id FK "OCD-ID format" | |
| string state_code "Two-letter code" | |
| datetime election_date | |
| string measure_number "Proposition 15, Question 2, etc." | |
| string title "Short title" | |
| string description "Full description" | |
| string measure_type "Initiative, Referendum, Bond" | |
| string topic_category "fluoridation, education, tax, etc." | |
| string status "qualified, certified, failed, passed" | |
| string result "passed, failed, pending" | |
| int yes_votes | |
| int no_votes | |
| float yes_percentage | |
| string full_text_url "Official text" | |
| string ballotpedia_url "Ballotpedia reference" | |
| datetime created_at | |
| } | |
| ``` | |
| **Data Sources Referenced:** | |
| - `ballotpedia_url` β [Ballotpedia](https://ballotpedia.org/) | |
| - `full_text_url` β State Secretary of State websites | |
| - Election results β [OpenElections](https://openelections.net/) or [MIT Election Lab](https://electionlab.mit.edu/) | |
| --- | |
| ## π Implementation Roadmap | |
| ### Phase 1: Ballotpedia Integration (Current Priority) | |
| - [ ] Create `scripts/extract_ballotpedia_measures.py` | |
| - [ ] Web scraping with rate limiting (respect robots.txt) | |
| - [ ] Search for fluoridation-related measures | |
| - [ ] Extract measure details and URLs | |
| - [ ] Save to `data/gold/ballots_state_measures.parquet` | |
| ### Phase 2: OpenElections Integration | |
| - [ ] Create `scripts/extract_openelections_results.py` | |
| - [ ] Download state CSV files from GitHub | |
| - [ ] Standardize to common schema | |
| - [ ] Link to jurisdictions using OCD-IDs | |
| - [ ] Save to `data/gold/ballots_election_results.parquet` | |
| ### Phase 3: MIT Election Lab Integration | |
| - [ ] Download county-level presidential results | |
| - [ ] Join with JURISDICTION data | |
| - [ ] Calculate political composition metrics | |
| - [ ] Use for advocacy targeting | |
| ### Phase 4: Real-time Monitoring | |
| - [ ] Set up alerts for newly qualified measures | |
| - [ ] Monitor election certification dates | |
| - [ ] Update results post-election | |
| - [ ] Notify advocates of opportunities | |
| --- | |
| ## π References & Credits | |
| ### Official Sources | |
| - **Ballotpedia** - Lucy Burns Institute, https://ballotpedia.org/ | |
| - **MIT Election Data + Science Lab** - https://electionlab.mit.edu/ | |
| - **OpenElections** - Open source project, https://openelections.net/ | |
| ### Open Civic Data Standards | |
| - **OCD Division IDs** - https://github.com/opencivicdata/ocd-division-ids | |
| - **OCDEP 2 Specification** - https://open-civic-data.readthedocs.io/en/latest/proposals/0002.html | |
| ### Related Documentation | |
| - [Data Model ERD](./data-model-erd.md) - Full entity relationship diagram | |
| - [Jurisdiction Discovery](./jurisdiction-discovery.md) - How jurisdictions are identified | |
| - [HuggingFace Datasets](./huggingface-datasets.md) - Published datasets catalog | |
| --- | |
| ## π€ Contributing | |
| Have a suggestion for another ballot/election data source? Please contribute! | |
| 1. Check if the source is **free and public** | |
| 2. Verify data quality and official status | |
| 3. Test integration with existing data model | |
| 4. Submit a pull request with documentation | |
| **Potential future sources:** | |
| - State Secretary of State APIs | |
| - County election board websites | |
| - Voter information portals | |
| - Campaign finance databases (for measure funding) | |