Skip to content

Code, um die Ergebnisse hessischer Bürgermeisterwahlen abzubilden

License

Notifications You must be signed in to change notification settings

JanEggers-hr/obwahlen

Repository files navigation

obwahlen

(Stand: 9.9.2023)

R-Code, um den Auszählungsstand hessischer Bürgermeisterwahlen in Echtzeit abzurufen und mit Datawrapper darzustellen (Frankfurt, Kassel Darmstadt)

Benötigt:

  • eine config.csv mit dem Link zu den Votemanager-Daten, den Namen der Konfigurationsdateien, und der IDs der Datawrapper-Grafiken
  • die drei Konfigurationsdateien für Kandidaten, Stadtteile, Zuordnung der Stimmbezirke zu den Stadtteilen
  • vorbereitete Datawrapper-Grafiken und Karten mit dem korrekten Shapefile

Votemanager und Datawrapper sind Voraussetzung

Das Programm arbeitet mit den Daten, die das Programm "Votemanager" bereitstellt; es ist bei allen größeren hessischen Kommunen im Einsatz. Votemanager publiziert das Auszählungsergebnis live, sobald es vorliegt, nach verschiedenen Aggregationsebenen, bis hinunter auf die Ebene des einzelnen Stimmbezirks als "Schnellmeldung".

Votemanager und die Briefwahlbezirke

Eine Falle, in die ich zunächst gestolpert bin: Neben normalen Stimmbezirken - die mit einem Wahllokal verbunden sind - gibt es die Briefwahlbezirke. Die haben eine Besonderheit: Sie haben rechnerisch 0 Wahlberechtigte - solange sie noch nicht ausgezählt sind, fällt die Berechnung der Wahlbeteiligung in einem Stadtteil immer zu niedrig aus!

Datawrapper

Wir setzen Datawrapper zur Ausgabe der Grafiken ein, das auch unter Last äußerst stabil läuft und eigentlich immer gut aussieht (corona-erprobt). Um die Grafiken vom Skript aktualisieren zu lassen, muss man in DataWRAPPER einen API-Token generieren und im R-Environment hinterlegen - dazu das Paket DatawRappr von Github installieren, laden, und datawrapper_auth("abcdef") aufrufen (statt "abcdef" natürlich das API-Token.)

Die Datawrapper-Darstellungen müssen derzeit noch von Hand angelegt werden - im Fall der Karten mit einem korrekten Shapefile als .geojson. Mehr bei Datawrapper; wie man mit QGIS aus einem .shp-File ein .geojson mit Zentrierpunkten und Tabellen erstellt, ist stichpunktartig hier dokumentiert

Wenn die Datawrapper-Karten einmal angelegt sind, werden sie vom Vorbereitungs-Skript in die richtige Form gebracht - Parteifarben, Fortschrittsbalken, Beschriftung wird alles vom Code generiert.

Ordnerstruktur

  • R enthält den Code
  • index enthält die Konfigurationsdatei index.csv und Unterordner mit den Indexdateien: Kandidaten, Stadtteile, Stimmbezirke, Datawrapper-Zuordnungen.
  • daten wird vom Code beschrieben und enthält den aktuellen Datenstand.

Daten aufarbeiten

Ziele

Grafiken:

  • Säulengrafik erste (top); Ergebnis nach derzeitigem Auszählungsstand mit "Fortschrittsbalken"

  • Balkengrafik für alle Kandidierenden

  • Symbol-Karte Stadtteil-Sieger und für jeden Kandidierenden eine Choropleth-Karte mit dem Ergebnis nach Stadtteil

  • Tabelle nach Kandidaten (3 beste, 3 schlechteste Stadtteile)

  • Tabelle alle Ergebnisse nach Stadtteil

Aktualisierung via CORS/GBucket

Der normale Weg, eine Datawrapper-Grafik anzuzeigen, ist: pushe die Daten auf den Datawrapper-Server - mit dw_data_to_chart() - und aktualisiere.

Alternativ kann die Grafik aus live bereitgestellten Daten in einem Google Bucket bestückt werden. Die Adressen der Dateien, die an die Grafiken übergeben werden müssen, sind:

Konfiguration

Das Programm holt sich seine Daten aus einer Konfigurationsdatei - entweder für den Live- oder den Testbetrieb, was über die Variable TEST im Progammcode umgestellt wird. Die Indizes für die jeweile Wahl - Kandidatinnen und Kandidaten, Stadtteile und Wahllokal-Zuordnungen - liegen in einem Unterordner mit dem Namen der Wahl, als CSV oder XLSX.

  • Konfigurationsdatei index/config.csv - eine CSV-Datei mit den Spalten "name" und "value" für die Konfigurations-Variablen und ihre Werte.
name value (Erklärung)
wahl_name Name der Wahl, z.B. ob_ffm_2023. Auch Name der Unterordner.
stimmbezirke_url Die Votemanager-URL, unter der eine CSV-Datei mit den Ergebnissen und dem Meldungsstand nach Stimmbezirk abrufbar ist. (Beim Testen auf eine eigene URL oder einen Dateipfad umbiegen)
wahlberechtigt Anzahl der vom Wahlamt gemeldeten Wahlberechtigten am Tag der Wahl; derzeit nicht benötigt (wäre für Schätzung der Wahlbeteiligung erforderlich)
briefwahl Anzahl der vom Wahlamt gemeldeten Briefwahlstimmen insgesamt am Tag der Wahl; derzeit nicht benötigt (wäre für Schätzung der Wahlbeteiligung erforderlich)
kandidaten_fname Filename der Tabelle mit den Kandidaten
zuordnung_fname Filename der Tabelle mit den Wahlbezirken und der Zuordnung zu Stadtteilen
stadtteile_fname Filename einer Liste mit Stadtteilen und Nummer
startdatum Zeitpunkt, ab dem die Wahlauszählung laufen soll
top Anzahl der führenden Kandidatinnen, die die erste Säulengrafik und die Anzahl der Ergebnis Balken in den Tooltipps der Karten steuert
top_id Datawrapper-ID für die Säulengrafik für das derzeitige Ergebnis der führenden (top) Kandidatinnen und Kandidaten
karte_sieger_id Datawrapper-ID der Symbolkarte mit den Siegern nach Stadtteil
karte_kand1_id Die Datawrapper-IDs für die Choropleth-Karten der Kandidatinnen; für jede eine Karte - nummeriert nach der Reihenfolge auf dem Wahlzettel (wie in der Indexdatei kandidaten.xlsx hinterlegt)
...karte_kandn_id
tabelle_alle_id Die Datawrapper-ID für die Balkengrafik mit allen Kandidierenden - die technisch eigentlich eine Tabelle ist und deswegen tabelle_alle_id heißt
hochburgen_id Die Datawrapper-ID für die Tabelle mit den besten und schlechtesten Stadtteilergebnissen nach Kandidat
tabelle_stadtteile_id Die Datawrapper-ID für die Tabelle mit den Gesamtergebnissen
social1_id Für Social Media: ID der Top-Säulengrafik
social2_id Für Social Media: ID einer Kopie der Gesamt-Tabelle/Balkengrafik
  • Tabelle index/wahlname/kandidaten.csv (also z.B. index/obwahl_of_2023/kandidaten.csv) enthält folgende Spalten: Spalte | Wert ---- | ---- Nummer | laufende Nr. des Kandidierenden nach Wahlzettel als ID Vorname | (und ggf. Doktortitel) Name | Parteikürzel | Kurzform der Partei des Kandidaten (z.B. "PARTEI" statt "Partei für Arbeit, Rechtsstaat, Tierschutz, Elitenförderung und basisdemokratische Initiative"") Partei | Vollständiger Parteiname (derzeit nicht verwendet) Farbwert | Die Kampagnenfarbe bzw. die Farbe für die Darstellungen des Kandidierenden als Hex-RGB-String, also z.B. "#B92837" URL | Verlinkung auf den Hintergrundartikel zum Kandidaten (derzeit nicht verwendet)

index/wahlname/stadtteile.csv- Die Stadtteil-Datei kann man aus QGIS exportieren, wenn man das Shapefile erstellt (CSV oder XLSX):

Spalte Wert
nr Laufende Nummer, ID des Stadtteils
name Name des Stadtteils (dient auch als ID, also auf Tippfehler achten!)
lon Längengrad des Zentrierpunkts für den Stadtteil
lat Breitengrad des Zentrierpunkts für den Stadtteil

index/wahlname/zuordnung_wahllokale.csv- Die Stimmbezirks-Datei enthält die Zuordnungen für die Wahlbezirke zu Stadtteilen und wird aus der Open-Data-Beispieldatei des votemanagers erstellt:

Spalte Wert
nr ID des Stimmbezirks
ortsteilnr ID des Stadtteils
ortsteil Name des Stadtteils

Nicht benötigte Spalten können in der Tabelle bleiben, sollten aber möglichst nicht "name" oder so heißen.

Aufarbeitung

  • Daten nach Stimmbezirk abfragen
  • Zuordnung Stimmen zu Kandidaten, Umrechnung Prozente gültige Stimmen Aggregation auf Stadtteilebene
  • Zuordnung Stimmbezirk->Stadtteil
  • Prozentanteile je Kandidat, Wahlbeteiligung Aggregation auf Stadtebene
  • Prozentanteile je Kandidat, Gewinner
  • Fortschrittsbalken ausgezählte Wahllokale
  • Fortschrittsbalken ausgezählte Stimmen (mit akt. Briefwahlstimmendaten)

Struktur des Codes: Was tut was?

(siehe "Sitemap" für den Code)

Vorbereitung einer Wahl

  • Shapefile für die Stadt besorgen; Stimmbezirksebene; Stadtteile
  • Stadtteile aggregieren, GEOJSON generieren
  • Ordner für die Wahl im Index-Ordner; Datei Kandidaten, Stadtteile (mit Geokoordinaten für die Zentrumspunkte), Stimmbezirke (mit Zuordnung Stadtteil)
  • Kopien für die vier Grafiken anlegen: Top, alle Stimmen, Hochburgen, Stadtteile. Link zum Wahlamt nicht vergessen.
  • Leerdatei Ergebnisse nach Stadtteil vorbereiten
  • Kopie der Sieger-Karte mit GEOJSON anlegen; GEOJSON hochladen, Leerdatei hochladen. Link zum Wahlamt korrigieren.
  • Eine erste Kopie der Choropleth-Karten nach Kandidat: Wahlamt-Link ändern und Karte und Leerdatei hochladen, dann kopieren.
  • Kopien für alle Kandidierenden anlegen. Jeweils die Werte-Spalte des jeweiligen Kandidaten auswählen; benennen, um sie zuordnen zu können. (Farben und Namen werden automatisch nachgetragen.)
  • Indexdatei vorbereiten: Wahlname, Anzahl TOP, Dateinahmen der Index-Dateien, Datawrapper-IDs für die Karten und Diagramme

TODO

  • Aufruf mit Parametern ermöglichen ("main.R obwahl_ffm_2023")

Nice-To-Have

  • Zusatzfeature: Briefwahlprognostik - wieviele Stimmen fehlen vermutlich noch?
  • Vergleich letzte Kommunalwahl regulär

About

Code, um die Ergebnisse hessischer Bürgermeisterwahlen abzubilden

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages