DB_Delay

Eine Visualisierung der Bahnverspätungen in Zusammenhang mit Umwelteinflüssen und besonderen Ereignissen.

DB_Delay Informationsgrafik Printmockup

Fast jeden Morgen kommt meine Bahn zu spät zur Weiterfahrt am Bahnhof an und ich muss in der Kälte warten. Jedoch geht es nicht nur mir so. Durchschnittlich jeder fünfte Zug der Bahn ist unpünktlich – Sagt die Bahn! Aber stimmt das und warum ist das so?

In meinem Projekt habe ich eine Informationsgrafik entwickelt, welche die Verspätung der Bahn je nach Zuggattung visualisiert. Diese entstandenen Graphen stelle ich Klimadaten gegenüber. So wird der Zusammenhang von Wetter und Verspätung deutlich. Zusätzlich sind Informationen zum Tagesereignis an den Großen Ausschlägen der Verspätungen positioniert. Auch die in 2015 stattgefundenen GDL-Streiks sind Markiert, sie haben jedoch keine sonderlichen Auswirkungen auf die Verspätung. Im unteren Teil befinden sich weitere statistische Auswertungen und Informatonen zu den Daten.

Schau Dir die Grafik in der Detailansicht an. In der Detailansicht kannst Du die Grafik zoomen und sie mit der Maus bzw den Fingern bewegen. So wie man es von Online-Weltkarten kennt.

Prozess
Geschätzte Lesezeit: 7 Minuten

Ausgangspunkt / Problemstellung

Zu Beginn stand erstmal nur die Idee und jede Menge Zugdaten von OpenDataCity´s „Zugmonitor“ (API – Datenbankschnittstelle). Dort werden die Daten sowohl in TSV-Formatierung, als auch im JSON-Format angeboten. Für jeden Tag seit dem 11. April 2014 existiert eine Datei, in welcher ca. 60.000 Züge hinterlegt sind. Dazu kommen noch Daten vom Deutschen Wetterdienst und die Recheche von Ereignissen rund um die Bahn. Daten habe ich also genug, doch irgendwie muss man mit einer Datenmenge von über 140 GB ersmal klar kommen.

Konzept / Lösungsansatz

Um nicht zu viele Daten auswerten zu müssen, beschränke ich den Zeitraum für die Auswertung auf ein Jahr. In den Aufzeichnungen sind Werte wie Zuglabel, Ziel, GPS-Position, Fahrtrichtung, Verspätung, Zeit, Bahnhof und Zeitstempel für jeden Zug hinterlegt. Damit könnte ich nach Zugtyp, Bahnhof, Tageszeit, Jahreszeit, Ort usw. Kategorisieren. Die Wetterdaten möchte ich klassisch darstellen. Senkrechte Balken für Niederschlag und Punkte für Temperatur.

Zur Auswertung nutze ich Processing und gehe Zeile für Zeile durch die Daten und errechne Tageswerte. Diese scheibe ich in eine kleine Datei, deren Werte ich als Graph zeichnen kann. – So einfach sollte es aber dann nicht werden.

Umsetzung

Ich habe mich zuerst auf die TSV-Daten konzentriert, da ich von JSON keine Ahnung hatte. Mit einem Programm welches ich in Processing geschrieben habe, errechnete ich zuerst Tageswerte für die Verspätungen. Schnell wurde jedoch klar: mit den TSV´s wird es zu kompliziert. Denn in den Daten wiederholen sich die Züge im Minutentakt, was eine Auswertung erschwert, denn alle einträge müssten zusammengefasst werden um jeweils die korrekten werte zu erhalten

DB_Delay - Generieren einer ersten Grafik
Generieren einer ersten Grafik mit Processing.

Erste Grafik

Als nächstes dachte ich, das z.B. an Weihnachten, Verspätungen durch viele Pendler entstehen. Um das herauszufinden generierte ich in Processing eine Grafik, welche an den GPS-Koordinaten eine Punkt, der je nach verspätung größer und gesättigter wird. Daraus entstanden diese Grafiken:

Zugverspätung am 11.06.2014
Zugverspätung am 11.06.2014
Zugverspätung am 24.12.2014
Zugverspätung am 24.12.2014

Ich habe einen Tag im Sommer 2014, sowie einen Tag im Winter 2014 (Weihnachten) verglichen. Dabei habe ich entgegen meiner Vermutung feststellen müssen, dass an Weihnachten, durch Pendler keine große Verspätungen verursacht wurden.

Am 10. bzw 11.06.2014 war es jedoch sehr heiß und es gab einige schwere Unwetter. An diesem Tag traten erhebliche Verspätungen auf.

Als nächstes wollte ich weterhin für jeden Tag die Anzahl der verspäteten Züge ermitteln und diese dann dem Wetter und verschiedenen Ereignissen gegenüberstellen.

Skizze

Für die Visualisierung dachte ich natürlich zuerst an eine Standartgrafik, in der ich Daten mit Linien darstelle und jeweils an Peeks usw. eventuelle Auslöser oder Nebeninformationen platziere.

Skizze - Lineare Graphen
Skizze - Lineare Graphen

Später habe ich noch andere Varianten ausprobiert und mich dafür entschieden das Jahr in einem Kreis aufzuteilen. Hier wird die Anzahl der verspäteten Züge pro Tag, unterschieden nach der Art, visualisiert. Zusätzlich ist im inneren Kreis die dargestellt zu welcher Uhrzeit am Tag die Züge am verspätesten sind. Umweltfaktoren wie Niederschlag und Temperatur sollen auch noch integriert werden. Jeweils an den Peek´s wird eine Information mit dem Auslöser der Verspätung gegeben und der Nutzer kann sich durch einen QR-Code zusätzlich weitere Informationen dieses Auslösers holen.

Skizze - radiale Graphen
Skizze - radiale Graphen

Als ergänzende Informationen dachte ich an Zahlen, welche die Gesamtanzahl der Züge, Züge im Nah- und Fernverkehr, Prozentwerte der verspäteten Züge (5, 10, 15, 30, 60 min), Rankings wie die Top10 der verspäteten Züge und Welcher Zug die längste bzw. kürzeste Strecke zurücklegt.

Datenbank

Nachdem das grobe Erscheinungsbild soweit stand, gings weiter mit programmieren. Nun wollte ich die Daten in eine Datenbank schreiben. Zuerst entschid ich mich für die Apache CouchDB, ein freies Datenbankmanagementsystem nach dem Ansatz einer objektorientierten Datenbank. Jedoch konnte ich die TSV-Daten hier nicht einfach importieren, JSON schon, aber mit Umweg. Die JSON-Daten beinhalten dies:

Beschreibung JSON-Datenmodells OpenDataCity
Beschreibung des JSON-Datenmodells von OpenDataCity

Wieder schrieb ich ein Programm in Processing. Es schickt meine JSON-Stream´s automatisch, zeile für zeile, per HTML-Request an die API der CouchDB. Dabei wird am Ende jeder Datei, die jeweils einen Tag beinhaltet, die nächste geladen – und weiter geht´s.

An sich funktioniert mein Programm sehr gut, ABER wie im Screenshot zu sehen erhalte ich immer wieder Bad-Request´s mit „Invalid JSON“, die zeilen bzw. JSONObjects sind jedoch valid. Zunächst dachte ich sie sind vielleicht zu lang, sind sie aber nicht, denn Sendet man die selbe Zeile per Terminal, geht´s. Eine andere Überlegung war, dass die Requests zu schnell gesendet werden und der Server überlastet aber auch mit nur einem Request pro Sekunde erhalte ich die selbe Meldung in der selben Zeile.

Datentransfer zu CouchDB
Datenverarbeitung und -transfer zu CouchDB

Nach weiteren Recherchen und Tipps habe ich versucht die vielen Daten über das Terminal in die Datenbank zu Schreiben. Dabei sind wieder einige Probleme aufgetreten. Zum einen mussten alle, bis auf jeweils die letzten JSON-Objekte in den Dateien mit einem Komma getrennt werden und zum anderen musste jeweils an den Beginn einer Datei die Zeile {„docs“:[ und ans ende eine Zeile mit ]} eingefügt werden. Allerdings war das mit den Bordmitteln von OS X nicht ohne weiteres möglich. So habe ich gleich alle Befehle durch die GNU Befehle ersetzt. Anschließend hätte ich die Daten in die Datenbank schreiben können, währe da nicht die Größe pro Datei gewesen, die chochdb ablehnt. Also habe ich die Dateien gesplittet, nochmal formatiert und dann wieder den Versuch mit der Datenbank gawagt. – Und wieder eine Fehlermeldung. Eigentlich wollte ich die Dateien automatisiert „rüber schicken“, aber das Terminal wartet zwischendurch nicht, bis nach einer Datei eine Rückmeldung kommt und schickt so alles hintereinander. CouchDB kommt dann durcheinander.

Hier kam Processing wieder ins Spiel und ich habe mir einen Sketch geschrieben, der das übernimmt. Allein dieser Vorgang hätte 60 Stunden gedauert! Noch schlimmer waren die Anfragezeiten. Mit einem Datenbankvolumen von 10.000 Einträgen dauerte eine Anfrage über 5 minuten und sie sind schrecklich zu programmieren.

Tschüss Couch, hallo mongoDB!

Nach einer weiteren Recherche erschien mir mongoDB als das Mittel der Wahl. MongoDB läuft auf mehreren Prozessorkernen, man kann die JSON-Dateien direkt importieren, die Datenmenge wird komprimiert (74GB) und die Konsole versteht die Programmiersprache Java. Fast die gesammte restliche Programmierung erfolgte dann in der Konsole von mongoDB.

Nach dem Import muste ich zuerst alle UNIX-Zeitstempel in ein ISO Datums-Objekt umwandeln damit mongoDB ihn versteht, danach mussten alle Datenfelder auf ihren Inhalt überprüft werden. Ist der Inhalt leer, wird er gelöscht. Hierdurch wurden mir später die maximalen und durchschnittlichen Werte, welche ich als neue Felder erzeugt habe, nicht verfälscht.

Auch die Wetterdaten konnte ich einfach Importieren und bereinigen. Hier waren -999 als Wert hinterlegt, wenn die Wetterstation ihn nicht gemessen hat.

Nachdem die Datenbasis nun stimmte, konnte ich mit den Daten arbeiten und wieder etwas aus der Datenbank zurückholen – Sogenennte „Aggregation´s“ auführen. Zuerst habe ich mir Klimawerte aller Stationen nach tag zusammenfassen lassen, diese aufsteigend nach Tag sortiert und als JSON ausgegeben. Damit konnte ich in Processing sehr gut arbeiten.

Dann waren die Zugdaten ander Reihe. Diese habe ich zunächst aus das Wesendliche reduziert, also die Einträge der Positionen zusammengefasst. Danach hatte ich eine handliche Datenbankgröße von 3GB.  Ähnlich wie bei den Wetterdaten konnte ich dann verschiedene Aggregation´s durchführen, mir die Daten separiert nach Zuggattun ausgeben und in Processing zeichnen. In den Bildern sieht man alle Werte auf einmal und zusätzlich noch überlagert. Um sie in Adobe Illustrator später einfach auswählen zu können, sind sie farbig codiert. Im rechten Bild sind die Werte in eine Skala skalliert.

Plot Tagesdurchschnittsverspätung
Radialer Plot der Tagesdurchschnittsverspätung
Plot Tagesdurchschnittsverspätung (Skalliert)
Radialer Plot der Tagesdurchschnittsverspätung (Skalliert)

Ich musste also einfach alle gleichfarbigen Elemente selektieren. Noch etwas Gestaltungsarbeit, Icons für die Zuggattungen, Ereignisse, Legende, Zusatzgrafiken und Erklärungen … dann sah die Grafik so aus.

DB_Delay - Informationsgrafik
Fertiggestellte Informationsgrafik

Im oberen Teil befindet sich die Hauptgrafik, sie zeigt die Zugverspätung in Deutschland, getrennt nach Zuggattung, über ein Jahr, von Dezember 2014 bis Ende November 2015. Die Zuggattungen sind farbig kodiert, ihre Verspätungen werden durch Linien in der jeweiligen Farbe dargestellt. Bei einem großen Ausschlag ist das Ereignis, welches für das hohe Verspätungsaufkommen verantwortlich ist, angebracht. Monate werden durch einen kurzen Strich getennt. Der Sonntag einer jeden Woche ist durch eine hellere Zahl gekennzeichnet. Im April bzw. in Mai haben der 5. 6. und 7. GDL-Bahnstreik stattgefunden, diese sind durch graue Bereiche gekennzeichnet. Im inneren Teil sind Niederschlag, Minimal- sowie Maximaltemperatur, Windstärke und Schneehöhe untergebracht. Maximalwerte sind von einer orangenen Kontur umrandet.

Die „Uhr“ in der Mitte zeigt, zu welcher Uhrzeit die meißten Züge verspätet sind. Zur Erklärung der Grafik befindet sich darunter eine Legende.

Im unteren Teil zeigen sich Zusatzinformationen und Statistiken über Datenmenge, Rechenzeit, Datenaufbau, Positionen der Wetterstationen, allgemeine Zugverspätung und auf welchen Strecken die züge am verspätesten fahren. Daraus kann man z.B.: entnehmen, dass unster Netz der Wetterstationen sehr homogen aufgebaut ist oder Züge auf den Strecken zwischen Großstädten oft verspätet fahren.

Schau Dir die Grafik in der Detailansicht an. In der Detailansicht kannst Du die Grafik zoomen und sie mit der Maus bzw den Fingern bewegen. So wie man es von Online-Weltkarten kennt.

Hat Dir das Projekt gefallen?

Schau Dir auch meine anderen Projekte an.

Projekte