elections-vote-transfer

Israeli Elections Vote Transfer Analysis

Interactive visualizations for analyzing voting patterns and vote transfers between Israeli Knesset elections (2003-2022, Knesset 16-25).

קולות נודדים - Visit the Website

Overview

This project provides a suite of interactive tools to explore Israeli election data at the ballot-box level (~10,000-12,000 polling stations per election). It answers questions like:

All pages are fully bilingual (Hebrew/English) and have both desktop and mobile-optimized versions.

Features

1. Dashboard (Landing Page)

A central hub with key stats and card navigation to all visualizations. Shows live visitor count.

2. Vote Transfer Sankey Diagram

Visualizes the flow of votes between consecutive elections using a Sankey diagram.

The transfer matrix is computed using convex optimization to find the best-fit stochastic matrix M where Votes_before × M ≈ Votes_after.

3. T-SNE Ballot Clustering

A 2D visualization of all polling stations, positioned by similarity of voting patterns.

4. Geographic Map

Interactive Leaflet map showing all ballot stations across Israel.

5. Party Support Scatter Plot

Compare support for two parties (or the same party across elections) at the ballot-box level.

6. Bader-Ofer Seat Calculator

Interactive calculator showing how Knesset seats are allocated using the Bader-Ofer (modified D’Hondt) method.

7. Irregular Ballot Analysis

Identifies polling stations with unusual voting patterns compared to their surroundings.

8. Regional Elections Simulator

Simulates a hypothetical regional election system for Israel using Voronoi district mapping and D’Hondt seat allocation.

9. Party Profile

Deep-dive page for party families showing their evolution across elections:

Accessible via party.html?name=<party_family_name>.

10. Settlement Profile

Deep-dive page for individual settlements showing:

Accessible via settlement.html?name=<settlement_name> or by clicking settlement links in the map, T-SNE, and scatter views.

Methodology

Vote Transfer Estimation

The vote transfer matrix is estimated by solving a constrained optimization problem:

minimize ||V_from × M - V_to||²
subject to:
  - M[i,j] ≥ 0 for all i,j (non-negative transfers)
  - Σⱼ M[i,j] = 1 for all i (rows sum to 1, i.e., stochastic matrix)

This assumes voters transfer between parties in a consistent pattern across all polling stations—a simplification, but one that produces interpretable results.

Solver: CVXPY with SCS backend

Ballot Box Matching

When comparing elections, ballot boxes are matched by settlement name and ballot number. Israeli ballot boxes sometimes get subdivided between elections (e.g., box 14 becomes 14.1, 14.2, 14.3). The matching logic:

T-SNE Dimensionality Reduction

Polling stations are embedded in 2D using t-SNE on the vector of party vote proportions. Stations with similar voting profiles cluster together, often revealing geographic and demographic patterns.

Data Sources

Elections Covered

Election Knesset Date Turnout
16 16th Knesset January 2003 67.8%
17 17th Knesset March 2006 63.6%
18 18th Knesset February 2009 64.7%
19 19th Knesset January 2013 67.8%
20 20th Knesset March 2015 72.3%
21 21st Knesset April 2019 68.5%
22 22nd Knesset September 2019 69.8%
23 23rd Knesset March 2020 71.5%
24 24th Knesset March 2021 67.4%
25 25th Knesset November 2022 70.6%

Local Development

Prerequisites

Setup

# Clone the repository
git clone https://github.com/harelc/elections-vote-transfer.git
cd elections-vote-transfer

# Create and activate virtual environment
python3 -m venv venv
source venv/bin/activate

# Install dependencies
pip install -r requirements.txt

# Start local server
cd site
python3 -m http.server 8888

Then open http://localhost:8888 in your browser.

Regenerating Data

source venv/bin/activate

# Vote transfer matrices
python generate_transfer_data.py
cp data/transfer_*.json site/data/

# T-SNE clustering
python generate_tsne_data.py
python add_locations_to_tsne.py
cp data/tsne_*.json site/data/

# Geographic map data (writes directly to site/data/)
python generate_map_data.py

# Wikipedia enrichment for settlement profiles (writes to site/data/)
python enrich_settlements_wikipedia.py

Project Structure

├── site/                          # Static website files
│   ├── index.html                 # Dashboard landing page
│   ├── sankey.html                # Sankey vote transfer diagram
│   ├── tsne.html                  # T-SNE ballot clustering
│   ├── geomap.html                # Geographic map
│   ├── scatter.html               # Party scatter plot
│   ├── dhondt.html                # Bader-Ofer seat calculator
│   ├── irregular.html             # Irregular ballot analysis
│   ├── regional.html              # Regional elections simulator
│   ├── settlement.html            # Settlement profile page
│   ├── discussions.html           # Community discussions (Giscus)
│   ├── i18n.js                    # Internationalization & navigation
│   ├── og-image.png               # Social preview image
│   ├── m/                         # Mobile-optimized versions of all pages
│   └── data/                      # JSON data files for frontend
├── data/                          # Source and intermediate data
├── party_config.py                # Election metadata & party config (K16-K25)
├── generate_transfer_data.py      # Transfer matrix computation
├── generate_tsne_data.py          # T-SNE embedding computation
├── generate_map_data.py           # Geographic data generation
├── download_statistical_zones.py  # CBS 2011 zone matching pipeline
├── process_statistical_zones.py   # CBS socioeconomic data processing
├── download_historical_ballots.py # K16-K20 ballot data from CEC CKAN API
├── enrich_settlements_wikipedia.py # Wikipedia data enrichment
├── prepare_election_26.py         # Election 26 data workflow
└── ballot*.csv                    # Raw election results per election (16-25)

Credits

License

This project is licensed under CC BY-NC-SA 4.0 (Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International).

You are free to share and adapt this work for non-commercial purposes, with attribution.

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.