Regionale Nahverkehrs-Visualisierung
Streckenbelastung im Schienennetz des RNV

Svenja Hering, Katharina Spinner, Eva Sennerich & Henrik Lawall

Regionale Nahverkehrs-Visualisierung

Untersuchung der Verspätungen auf der Linie 1 und der Streckenbelastungen im gesamten Schienennetz des Rhein-Neckar-Verkehrsverbundes

Verspätungen und Umleitungen aufgrund von Baustellen oder hohem Verkehrsaufkommen gehören zu den wohl häufigsten, außerordentlichen Erscheinungen im städtischen Nahverkehr. Es ist sowohl für den Betreiber des Streckennetzes als auch für den normalen Fahrgast von erheblichem Vorteil die Ursachen für solche Ereignisse zu kennen und auch zu verstehen. Zu diesem Zweck hat das Projektteam öffentlich zugängliche Daten des Rhein-Neckar-Verkehrsverbundes gesammelt, ausgewertet und anschließend auf verschiedene Weisen visualisiert. Die Ergebnisse geben Aufschluss darüber, welche Streckenabschnitte im Schienennetz des RNV besonders stark belastet sind und an welchen Haltestellen die Stadtbahnlinie besonders häufig verspätet abgefahren ist.

Einführung / Konzept

Einführung

Dieses Projekt ist im Rahmen der Veranstaltung Grundlagen der Datenvisualisierung (GDV) an der Hochschule Mannheim entstanden und hat zum Ziel, eine oder mehrere Datenquelle(n) aus einem urbanen Kontext auszuwerten und die Ergebnisse zu visualisieren. Wir haben uns für Daten des Rhein-Neckar-Verkehrsverbundes (RNV) entschieden, weil wir in der Rhein-Neckar Region leben und Daten visualisieren wollten, zu denen wir einen konkreten und persönlichen Bezug haben.

Motivation / Konzept

Während der Sperrung eines zentralen Streckenabschnitts, wurde ein Großteil der Bahnen für mehrere Monate umgeleitet. Die dadurch resultierende Mehrbelastung eines anderen Abschnitts führte dazu, dass die dort verlegten Schienen vorzeitig ausgetauscht werden mussten. Hierdurch entstand bei uns die Idee, die Belastung der verschiedenen Streckenabschnitte zu visualisieren. Auch mit dem Hintergedanken, dass man mit der Hilfe einer solchen Visualisierung eine Mehrbelastung frühzeitig erkennen und dementsprechend Maßnahmen einleiten kann.

Nicht nur Baustellen und Umleitungen sorgen bei Fahrgästen für eine zusätzliche Anspannung. Auch Verspätungen führen schnell zu Frustration. Doch welche Haltestellen oder Tageszeiten besonders stark betroffen sind, ist für Fahrgäste kaum ersichtlich. Durch unseren persönlichen Bezug zum öffentlichen Nahverkehr, den wir nahezu täglich nutzen, fanden wir diesen Aspekt zusätzlich interessant und wollten betrachten, wie viele Straßenbahnen zu spät von ihrerer Haltestelle abfahren. Im besten Fall können so Rückschlüsse gezogen werden, worin die Ursache liegt und ob dabei bestimmte Wochentage oder Uhrzeiten eine Rolle spielen.

Hauptthesen

  • “Gibt es Streckenabschnitte, die im Vergleich zu anderen besonders stark belastet sind?”

  • “Gibt es Haltestellen, an denen die Line 1 besonders häufig verspätet abfährt?”

  • “Gibt es eine Tageszeit, an der es häufiger zu Verspätungen kommt?”

  • “Gibt es Wochentage, an denen es häufiger zu Verspätungen kommt?”

Unsere Hauptthesen haben sich bezüglich der Verspätung im Laufe des Projektes leicht geändert. Am Anfang gingen wir davon aus von allen Straßenbahnlinien Daten auswerten zu können, jedoch mussten wir uns aufgrund von Limitierungen der Datenquelle auf eine Linie beschränken.

Daten / Auswertung

Daten

Datenquellen

Über das OpenData-Portal des Rhein-Neckar-Verkehrsverbundes werden Daten in verschiedenen Formaten angeboten. Neben CSV und JSON Dateien finden sich sogenannte GTFS-Daten (Google Transit Feed Specification). Dieses für Google Maps entworfene Format enthält für einen festgelegten Zeitraum die Fahrplandaten aller Linien. Darüber hinaus bietet der RNV auch eine REST-API (Start.Info API) an, über die sich Live-Informationen abfragen lassen. Hierüber ist beispielsweise ermittelbar, ob eine Fahrt verspätet ist. Doch ist hier keine Historie verfügbar, also ist es lediglich möglich, Daten für die Situation zum Zeitpunkt der Abfrage zu erhalten, jedoch nicht über in der Vergangenheit verspätet abgefahrene Züge.

Datenerhebung

Für die Auswertung der Streckenbelastung enthalten die GTFS-Daten alle benötigten Informationen. Aus diesen Fahrplandaten lässt sich ableiten, wie viele Züge in einem bestimmten Zeitpunkt zwischen zwei Stationen verkehren. Die GTFS-Daten lassen sich vom OpenData-Portal ohne Registrierung herunterladen. Dabei gibt es eine breite Auswahl an verfügbaren Zeiträumen. Wir wählten den Datensatz 1711v3, der die Zeit vom 24.11.2017 bis zum 10.01.2018 abdeckt, da dies zum Zeitpunkt des Projektstarts der aktuellste Datensatz war.

Die Analyse der Verspätungen ist dagegen lediglich über die Start.Info API möglich und aufgrund der fehlenden Historie mussten die Daten mit Hilfe eines Skripts zunächst gesammelt werden. Hierbei war die Vorgehensweise wie folgt: Jede Haltestelle hat eine eindeutige Haltestellen ID, die sich allerdings von denen in den GTFS-Daten unterscheidet. Um eine Liste mit allen Haltestellen einer Linie und deren zugehörigen IDs zu bekommen muss eine Abfrage an die API ausgeführt werden, die eine TourID der gewünschten Linie des aktuellen Tages enthält. Aus der Antwort kann man anschließend die benötigten Informationen extrahieren. Mit den erhaltenen Haltestellen IDs können nun die Live-Informationen über die Abfahrten der Straßenbahnen abfragt werden. Eine solche Abfrage sieht folgendermaßen aus:

http://rnv.the-agent-factory.de:8080/easygo2/api/regions/rnv/modules/stationmonitor/element?hafasID=2544&time=null&transportFilter=1

hafasID ist hierbei die Haltestellen ID und 2544 ist die Haltestelle Rheinau Karlsplatz. transportfilter=1 bedeutet, dass nur die Daten der Linie 1 zurückgegeben werden sollen. Diese Abfrage wurde für alle Haltestellen der Linie 1 minütlich mit einem NodeJS-Skript wiederholt. Der hierfür benötigte Server wurde uns freundlicherweise von CuByte zur Verfügung gestellt. Die Ergebnisse wurden anschließend in eine MongoDB Collection gespeichert. Vor dem Abspeichern wurden außerdem alle überflüssigen Parameter entfernt und das aktuelle Datum sowie die abgefragte Haltestellen ID ergänzt.

Ergebnis-JSON der Start.Info API

Normalerweise fährt die Linie 1 zwischen den Haltestellen Schönau und Rheinau Bahnhof. Da jedoch in dem Zeitraum, in dem die Daten gesammelt wurden, die Haltestelle Rheinau Bahnhof umgebaut wurde und deshalb die Strecke zwischen den Haltestellen Rheinau Karlsplatz und Rheinau Bahnhof nur von Schienenersatzverkehr in Form eines Busses bedient wurde, wurden nur die Daten der Straßenbahn von Schönau bis Rheinau Karlsplatz betrachtet. Der Erfassungszeitraum umfasst die Zeit vom 06.12.17 bis zum 05.01.18. Es gab zwischenzeitlich eine Ausfallzeit von ca. 4-5 Minuten am Nachmittag des 09.12.17. Die größte Herausforderung beim Erheben der Daten war die veraltete Dokumentation der Start.info API. Teilweise stimmten die URL-Parameter nicht oder hilfreiche Parameter wie transportfilter waren nicht dokumentiert. Auch die Struktur der Antworten der API wichen zum Teil von der Dokumentation ab. Hierbei war die Hilfe einer RNV Mitarbeiterin unerlässlich.

Datenauswertung

GTFS-Daten

Die GTFS-Daten bestehen zunächst aus mehreren Textdateien. Mit Hilfe des GTFS-Leitfadens von Google und einiger Analyse-Tools, die wir auf Github fanden, machten wir uns mit der Datenstruktur vertraut. Dabei stellte sich heraus, dass sich die Daten mit wenig Aufwand in CSV-Dateien umwandeln lassen und generell einem relationalen Aufbau folgen. Infolgedessen entschieden wir uns, die Daten in eine SQL Datenbank zu importieren. Die Wahl fiel dabei auf MariaDB, eine Open-Source Adaption von MySQL, da wir diese bereits aus früheren Projekten kannten. Mit dem Tool HeidiSQL führten wir die Erzeugung der Tabellen, sowie den Import der CSV-Dateien durch. Eine Datei entsprach dabei genau einer Tabelle. Anhand des Google Leitfadens erstellten wir zudem Primär- und Fremdschlüssel, um Abfragen über mehrere Tabellen hinweg zu ermöglichen. Anschließend begannen wir damit, einen SQL-View zu entwickeln, der Daten von mehreren Tabellen verbindet und bereits die Spalten auswählt, die für unser Vorhaben von Relevanz sind.

Datenbank-View zur Beschaffung der relevanten Datensätze

Die Datenstruktur von GTFS folgt einem klaren Muster. Die Trip ID ist ein eindeutiger Identifikator für eine Fahrt (z.B. Linie 1 von Schönau nach Rheinau beginnend um 07:30 Uhr). Mit Hilfe der Tabelle calendar lässt sich ermitteln, an welchen Wochentagen diese Fahrt stattfindet (z.B. Montag bis Freitag). Zu jeder Trip ID gibt es nun mehrere Datensätze, die jeweils einen Halt auf der Fahrt darstellen. Darin enthalten sind sowohl Name und Koordinaten der Haltestelle als auch die Abfahrtszeit.

Um nun die Anzahl der Züge in einem bestimmten Streckenabschnitt zu ermitteln, war der erste Ansatz, mit JavaScript (NodeJS) über das Ergebnisobjekt des Views zu iterieren und zu zählen, wie oft eine Kombination von zwei Haltestellen auftaucht. Dieser Ansatz wurde jedoch durch mehrere Faktoren erschwert. So musste zum einen überprüft werden, ob die Fahrt im gewünschten Zeitraum liegt und an den jeweiligen Wochentagen überhaupt stattfindet. Zudem gibt es im GTFS-Format Ausnahmefälle (z.B. wenn eine Fahrt an Weihnachten nicht verkehrt), die in einer zusätzlichen Tabelle hinterlegt sind und hier auch herangezogen werden müssen. Zum anderen erlaubt GTFS Abfahrtszeiten wie 26:15:00. Gemeint ist damit 02:15:00 am Folgetag, wenn die Fahrt vor Mitternacht begonnen hat.

Aufgrund all dieser Sonderfälle entschieden wir schließlich, den Ansatz zu überarbeiten und entwickelten eine neue Abfragestrategie. Diese sah vor, dass zunächst ein einmalig ausgeführtes Skript die Tabellen calendar und calendar_dates analysierte und in eine eigens hierfür angelegte Hilfstabelle die Information speicherte, an welchen Tagen eine Fahrt wirklich stattfindet.

Hilfsabelle: TripDates

Durch diese Hilfstabelle konnte die eigentliche Analyse der Daten deutlich vereinfacht werden. Lediglich das Problem mit Abfahrtszeiten wie 26:15:00 war so schwierig zu beheben, dass wir aus Zeitgründen schließlich entscheiden mussten, diesen Umstand größtenteils zu ignorieren. Eine Zeit wie 26:15:00 wurde lediglich in 02:15:00 umgewandelt, ohne jedoch den Tag der Abfahrt zu beachten. Die dadurch entstandene Ungenauigkeit der Ergebnisse erwies sich jedoch, vorausgesetzt der Nutzer möchte nicht explizit Nachtfahrten betrachten, als gering und vernachlässigbar.

Auszug aus dem Zwischenergebnis der Datenauswertung
Start.Info API

Die Auswertung der Verspätungsdaten gestaltete sich weit einfacher, als die der GTFS-Daten, doch auch hier gab es mehrere Herausforderungen zu bewältigen. Da die Rohdaten, so wie sie vom Erhebungsskript in die MongoDB gespeichert wurden, umfangreich und unstrukturiert waren, entschieden wir ein NodeJS-Skript zu entwickeln, dass die Daten analysiert, ordnet und anschließend in die bereits vorhandene MariaDB ablegt.

Folgende Vorgaben wurden dabei definiert:

  • Es sollen lediglich Fahrten betrachtet werden, deren Ziel entweder Schönau oder Rheinau Karlsplatz ist, da dies mit Abstand die häufigsten Fahrtziele sind.
  • Eine Abfahrt von einer Haltestelle wird eindeutig identifiziert durch die Kombination des Namens der Haltestelle, der geplanten Abfahrtszeit und dem Ziel der Fahrt.
  • Da die API minütlich abgefragt wurde, taucht eine Fahrt mehrfach auf, während sie sich einer Haltestelle annähert. Dabei muss lediglich das zeitlich gesehen letzte Vorkommnis dieser Fahrt betrachtet werden, da dieser Datensatz die genaueste Schätzung der Verspätung enthält.

Anhand dieser Vorgaben verarbeitete die folgende JavaScript-Funktion die Rohdaten. Als Parameter erhält die Funktion die Daten von jeweils einer Haltestelle.

const moment = require('moment');
const dateFormat = 'YYYY-MM-DDTHH:mm:ss';
module.exports.processData = (data) => {
    let resultObject = {};
    data.forEach(obj => {
        let listOfDepartues = obj.listOfDepartures;
        let requestTimestamp = moment(obj.date);

        listOfDepartues.forEach(departure => {
            if (departure.direction === 'Schönau' || departure.direction === 'Rheinau Karlsplatz') {
                let times = parseTimeString(requestTimestamp, departure.time);
                let plannedDeparture = moment(times.plannedDeparture);
                let projectedDeparture;
                if (times.delay > 0) projectedDeparture = moment(plannedDeparture).add(times.delay, 'minutes');
                else projectedDeparture = plannedDeparture;

                let objectIdentifier = plannedDeparture + '___' + departure.direction;
                // if tour id is already in result object change all fields that could have changed
                if (resultObject[objectIdentifier]) {
                    resultObject[objectIdentifier].differenceTime = departure.differenceTime;
                    resultObject[objectIdentifier].delay = times.delay;
                    resultObject[objectIdentifier].projectedDeparture = projectedDeparture.format(dateFormat);
                    resultObject[objectIdentifier].requestTimestamp = requestTimestamp.format(dateFormat);
                } else {
                    resultObject[objectIdentifier] = {
                        tourId: departure.tourId,
                        positionInTour: departure.positionInTour,
                        direction: departure.direction,
                        differenceTime: departure.differenceTime,
                        plannedDeparture: plannedDeparture.format(dateFormat),
                        projectedDeparture: projectedDeparture.format(dateFormat),
                        delay: times.delay,
                        requestTimestamp: requestTimestamp.format(dateFormat)
                    }
                }
            }
        })
    });
    return resultObject;
};

Eine besondere Hürde bei der Verarbeitung ergab sich vor allem durch die eindeutige Identifikation einer Abfahrt, sowie durch die Ermittlung der genauen Abfahrtszeit. Ersteres wurde nämlich dadurch erschwert, dass die in den Rohdaten enthaltene Tour ID (nicht zu verwechseln mit der Trip ID der GTFS-Daten) kein eindeutiger Identifikator einer Fahrt ist. Die Ermittlung der Abfahrtszeit führte vor allem deshalb zu Problemen, da das vom RNV verwendete Format keinem bekannten Standard entspricht. Die Informationen zur Abfahrtszeit und Verspätung werden von der API als 12:45+2 ausgegeben, wobei 12:45 die geplante Abfahrtszeit am Tag der Abfrage ist und +2 die erwartete Verspätung. In einigen Fällen fehlte jedoch die erwartete Verspätung, wobei davon ausgegangen werden kann, dass die Fahrt keine Verspätung hat ( → 12:45= 12:45+0 ). Falls die Fahrt erst am Folgetag der Abfrage stattfinden soll, enthält dieses Feld zusätzlich noch das jeweilige Datum. Erst nachdem uns alle möglichen Varianten dieses Attributs bekannt waren, konnten wir ein Skript entwickeln, dass den gegebenen String in ein gültiges Zeitformat konvertiert.

function parseTimeString(requestTime, timeString) {
    let delay;
    let date;
    if (timeString.length > 9) {
        let day = timeString.substr(0, 2);
        let month = timeString.substr(3, 2);
        let year = timeString.substr(6, 4);
        let hours = timeString.substr(11, 2);
        let minutes = timeString.substr(14, 2);
        date = moment(year + '-' + month + '-' + day + 'T' + hours + ':' + minutes + ':00').format();
        if (timeString.length > 16) delay = timeString.substr(17);
    } else {
        date = moment(requestTime);
        date.hours(parseInt(timeString.substr(0, 2)));
        date.minutes(parseInt(timeString.substr(3, 2)));
        date.seconds(0);
        date = date.format();
        if (timeString.length > 5) delay = timeString.substr(6);
    }
    delay = parseInt(delay);
    return {
        plannedDeparture: date,
        delay: isNaN(delay) ? 0 : delay
    };
}

Die verarbeiteten Rohdaten konnten, nachdem sie mit zusätzlichen Haltestelleninformationen wie den Geo-Koordinaten angereichert wurden, in die MariaDB gespeichert werden.

Verarbeitete Verspätungsdaten

Nachdem wir einige Experimente zur Datenvalidierung durchgeführt hatten, entschieden wir, zwei weitere Änderungen vorzunehmen:

  • Alle Fahrten vom 06.12.2017 wurden gelöscht, da an diesem Tag das Abfrageskript gestartet und lediglich ein Zeitraum von 2 Stunden erfasst wurde.
  • Ein mit hoher Wahrscheinlichkeit fehlerhafter Datensatz wurde manuell entfernt. Es handelt sich dabei um einen Zug mit der Endhaltestelle Schönau, für den eine Abfahrtszeit für eben diese Endhaltestelle vorlag. Für Endhaltestellen kann es jedoch keine Abfahrt geben.

Prototyp / Ergebnisse

Fragestellungen und Thesen

Zu Beginn des Projektes stellten wir Fragestellungen auf, die es mit Hilfe unserer Visualisierungen zu beantworten galt:

  • Gibt es Streckenabschnitte, die im Vergleich zu anderen besonders stark befahren und damit belastet sind?
  • Gibt es Haltestellen, an denen die Line 1 besonders häufig verspätet abfährt?
  • Gibt es eine Tageszeit, an der es häufiger zu Verspätungen kommt?
  • Gibt es Wochentage, an denen es häufiger zu Verspätungen kommt?

Erste Visualisierungsideen und Toolauswahl

Da zwei verschiedene Aspekte visualisiert werden sollten, galt es nun, jeweils geeignete Visualisierungsarten zu finden.

Auslastung / Frequenz

Es war schnell klar, dass die Darstellung der Netzauslastung mittels einer interaktiven Karte realisiert werden soll. Bei der Recherche nach einer geeigneten Bibliothek stießen wir auf Mapbox als Anbieter einer JavaScript API, welche sowohl mit fertigen Themes, als auch individualisierten Karten verwendet werden kann. Mit Hilfe von Mapbox konnten wir eine Karte erzeugen, auf der die Stadtbahn-Haltestellen mit ihren Geo-Koordinaten projiziert wurden. In einem nächsten Schritt stellten wir verschiedene Überlegungen an, wie die Frequenz zwischen zwei Haltestellen auf der Karte visualisiert werden kann. Dies zeigt die folgende Abbildung.

Überlegungen zur Visualisierung der Streckenbelastung

Hierbei stellten sich beispielsweise die folgenden Fragen: * Soll die Anzahl der Züge im gewählten Zeitraum neben der Linie angezeigt werden? (Links oben) * Soll die Dicke der Linie Aufschluss über die Höhe der Frequenz geben? (Rechts oben) * Soll die Linie eine Farbcodierung, evlt. entlang des Ampelschemas (hohe Frequenz: rote Farbe, niedrige Frequenz: grüne Farbe), erhalten? * Soll bei einer Auswahl mehrerer Stadtbahnlinien die Anzahl aufaddiert werden, oder soll die Frequenz der einzelnen Linien erkennbar bleiben? (Rechts unten)

Um die Übersichtlichkeit zu wahren, verzichteten wir auf die Anzeige der Zuganzahl neben der Linie, ebenso verhielt es sich mit der Farbcodierung. Darüber hinaus ist die eigentliche Intention der Visualisierung, zu zeigen, wie viele Bahnen auf einer Strecke gefahren sind. Unwichtig ist dabei welche der Stadtbahnlinien dort gefahren sind. Daher werden die Daten der ausgewählten Linien aggregiert.

Die Interaktion mit dem Nutzer sollte sich auf die minutengenaue Auswahl des Zeitraums, sowie die Auswahl der gewünschten Stadtbahnlinien beschränken. Unsere Überlegungen zu den Interaktionen ließ jedoch noch Spielraum zu. Der Zeitraum könnte sowohl über einen Datepicker, als auch über verschiedene Schieberegler bestimmt werden.

Verspätungen

Bezüglich der Visualisierung der Verspätungsdaten erstellten wir in einem Brainstormingprozess unter anderem die beiden untenstehenden Darstellungen, welche zu diesem Zeitpunkt lediglich fiktive Daten enthielten. Die Höhe der Verspätung könnte mit Hilfe von Kreisen abgebildet werden. Je größer der Kreis, desto größer die durchschnittliche Verspätung an dieser Haltestelle. Alternativ ist auch eine Linie vorstellbar, die ebenfalls durch die Dicke aufzeigt, wann die Verspätung am größten war.

Visualisierungsexperiment: Liste aller Haltestellen sortiert nach der durchschnittlichen Verspätung
Visualisierungsexperiment: Verspätungen in der Tagesübersicht für die Haltestelle Universität

Für die Umsetzung der Visualisierung benötigten wir noch ein geeignetes Tool bzw. eine Bibliothek, mit welcher wir die Diagramme in unsere finale Anwendung einbetten konnten. Da keines unserer Mitglieder bislang mit einer Bibliothek wie beispielsweise D3 gearbeitet hatte und der Einarbeitungsaufwand hier sehr groß schien, entschieden wir uns für Tableau, was uns bereits vertraut war. Hierbei verwendeten wir die Erweiterung Tableau Public, mit welcher es möglich war, die erstellten Visualisierungen mit Hilfe einer JavaScript API in unsere eigene Anwendung zu integrieren. Diese Erweiterung ist kostenfrei nutzbar.

Datenaufbereitung

Um die Daten auf die gewünschte Art und Weise visualisieren zu können, müssen diese zunächst aufbereitet werden.

GTFS-Daten

Für die Visualisierung der Netzauslastung im RNV-Gebiet erforder Mapbox, dass die Daten im GeoJSON Format vorliegen. Die Umwandlung des in Kapitel 2 beschrieben Ergebnisobjekts findet hierbei noch im Backend statt. Sobald das Frontend die Daten erhält, wird auf Grundlage der Frequenzen die Liniendicke berechnet. Diese Berechnung findet für jeden Streckenabschnitt, also für jeden Abschnitt zwischen zwei Haltestellen, statt. Die dickste Linie ist dabei immer 16px breit, die dünnste 2px. Das bedeutet, dass je nach Auswahl des Nutzers die dickste Linie eine Frequenz von 10, oder auch von 1000 abbilden kann. Grund dafür ist die bessere Lesbarkeit, da sonst sehr hohe Frequenzen andere Linien verdecken würden und sehr niedrige Frequenzen kaum erkennbar wären.

Daten aus der Start.Info API

Die Aufbereitung der Verspätungsdaten gestaltete sich deutlich weniger aufwendig. Die bereits geordneten Daten aus der MariaDB wurden von uns einmalig in Tableau übertragen, wo in ein statisches Datenextrakt erzeugt wurde. Dort legten wir zusätzlich berechnete Spalten an. Dazu gehören “Anteil verspäteter Züge” in Prozent (Anzahl verspäteter Züge geteilt durch Gesamtzahl der Züge) und die Spalte “Verspätet” mit den möglichen Werten “Verspätet” und “Nicht verspätet”. Als verspätet gilt hierbei ein Zug, wenn dieser mindestens zwei Minuten nach der geplanten Abfahrtszeit die Haltestelle verlässt.

Visualisierungsexperimente mit Tableau auf dem Weg zum Prototypen

Während wir versuchten, unsere Vorstellungen und geplanten Visualisierungen mit den gewählten Tools umzusetzen, experimentierten wir mit weiteren Möglichkeiten und Darstellungsformen. So entwickelten wir beispielsweise die folgende Visualisierung:

Visualisierungsexperiment: Stündliche Verspätungen für eine Haltestelle und einen Tag

Abgebildet wird, wie viele Züge verspätet (blau) und wie viele nicht verspätet (grau) waren. Der Tag, die Haltestelle und die Fahrtrichtung können dabei vom Nutzer bestimmt werden. Der gewählte Tag wird dann stundenweise abgebildet. Diese Visualisierung wirkt zwar zunächst ansprechend, allerdings auch etwas unübersichtlich, sobald mehrere Tage und Haltestellen gewählt werden, wie die untenstehende Abbildung zeigt.

Für den Nutzer ist hierbei nicht mehr intuitiv erkennbar, wie viele Züge insgesamt gefahren sind und wie viele davon verspätet waren. Darüber hinaus ist es schwierig Trends abzulesen. Daher entschieden wir uns dagegen, diese Visualisierung dem Nutzer im Rahmen des Prototyps anzubieten.

Visualisierungsexperiment: Stündliche Verspätungen für alle Haltestellen und Tage

Prototyp

Der fertige Prototyp, der auch im Rahmen der iExpo Studierenden und Professoren der Hochschule Mannheim vorgestellt wurde, bestand letztendlich aus zwei Teilen. Zum einen visualisierten wir die Verspätungsdaten mit einer Heatmap. Diese zeigt dem Nutzer auf der y-Achse die Haltestellen der Stadtbahnlinie 1 und auf der x-Achse das jeweilige Datum inklusive Wochentagsangabe. Die jeweiligen Felder sind nach dem Anteil der verspäteten Züge eingefärbt. Die Farbskala folgt dabei dem Ampelschema und deckt den Datenraum von 0 bis 60 % ab.

Der Nutzer kann durch Hovern Informationen bezüglich der durchschnittlichen Verspätung in Minuten, der prozentualen Verspätung, sowie der absoluten Anzahl verspäteter Züge erhalten. Er kann sowohl eine bestimmte Haltestelle als auch einen bestimmten Tag durch Klicken hervorheben.

Neben der Heatmap werden dem Nutzer zusätzlich Kreisdiagramme angeboten, die sich entsprechend der getroffenen Auswahl in der Heatmap verändern. Angezeigt wird der Anteil, sowie durch Hovern die absolute Anzahl, verspäteter und pünktlicher Züge. Ein Kreisdiagramm bildet dabei eine Stunde des Tages ab.

Damit entspricht der Prototyp zu den Verspätungsdaten nahezu vollständig nicht mehr den geplanten Visualisierungen. Grund dafür ist, dass wir dem Nutzer so viele Informationen wie möglich anbieten wollten, denn insbesondere mit Hilfe der Heatmap sind Zusammenhänge und Entwicklungen über den gesamten Zeitraum besser erkennbar und analysierbar.
Die Visualisierung ist über Tableau Public öffentlich zugänglich und kann unter diesem Link aufgerufen werden.

Die Visualisierung der Karte, also der Streckenbelastung, wurde hingegen wie geplant umgesetzt. Der Nutzer kann am linken Bildschirmrand mittels eines klassischen Datepickers den zu betrachtenden Zeitraum sowie die Stadtbahnlinien auswählen.

Während des Testens der Anwendung stellten wir fest, dass die Visualisierung noch um einige Punkte ergänzt werden könnte, um die Nutzerfreundlichkeit zu verbessern. So wird dem Nutzer nun die Dauer des gewählten Zeitraumes in textueller Form angezeigt. Darüber hinaus wird je nach Abfrageparameter eine Tabelle erzeugt, die für alle Streckenabschnitte die absolute Anzahl an Stadtbahnen zeigt. Die Tabelle ist absteigend sortiert, sodass die Abschnitte mit der höchsten Frequenz an oberster Stelle stehen.

Möglichkeit zur Interaktion bietet diese Visualisierung beispielsweise durch das Rotieren der Karte. Zusätzlich kann durch Klicken auf eine Frequenzlinie die absolute Anzahl an Stadtbahnen angezeigt werden, sowie durch Klick auf einen Streckenabschnitt in der Tabelle, die Position auf der Karte automatisch angepasst werden. Klickt der Nutzer auf eine Haltestelle, wird die Karte an dieser Position zentriert.

Im Folgenden ist eine Übersicht der im finalen Prototyp verwendeten Technologien.

Backend

  • NodeJS mit ExpressJS Webserver
  • MariaDB
  • Tableau Public

Frontend

  • Mapbox GL JS
  • jQuery
  • Bootstrap
  • Date Range Picker
  • Tableau JavaScript API

Fazit

Ergebnisse

Nach Auswertung der Visualisierungen, sowie bereits während der Sichtung der Daten, konnten wir verschiedene Ergebnisse in Bezug auf die definierten Fragestellungen ableiten. So ließ die Betrachtung der Frequenzdaten die folgenden Schlüsse zu:

  • Die Strecken in der Mannheimer Innenstadt um die Haltestellen Abendakademie, Paradeplatz, Hauptbahnhof und Wasserturm sind deutlich stärker belastet als Streckenabschnitte in Außenbezirken.
  • An einem Werktag fahren ca. doppelt so viele Züge wie an einem Sonntag. D.h. an einem Wochentag sind die Strecken doppelt so stark belastet wie an einem Sonntag.
  • Fast alle Linien bedienen zu bestimmten Zeiten (z.B. nachts) auch Haltestellen, die nicht zur regulären Strecke gehören.

Die Verspätungsdaten ergaben die folgenden Erkenntnisse:

  • Gegen Ende einer Fahrt treten Verspätungen häufiger auf.
  • Morgens zwischen 7 Uhr und 9 Uhr treten vermehrt Verspätungen auf, zwischen 16 Uhr und 19 Uhr ist der Anteil der verspäteten Züge nochmals höher als am Morgen.
  • Ab dem 23.12. gab es im Durchschnitt ca. 10% weniger Verspätungen als zuvor.
  • Sonntage sind am wenigsten von Verspätungen betroffen.

Auffälligkeiten

Wir stellten neben den genannten Erkenntnissen allerdings auch einige unerwartete Dinge fest. Beispielsweise rückte die Haltestelle Neuer Meßplatz insbesondere bei der Betrachtung der Heatmap in unseren Fokus. Auffällig ist hier besonders die Fahrtrichtung nach Schönau. Denn hier ist der Neue Meßplatz die Haltestelle mit der größten Verspätung über den gesamten Zeitraum hinweg. Darüber hinaus ist zu beobachten, dass die Verspätungen nach dieser Haltestelle wieder kontinuierlich abnehmen. Erwartet hatten wir allerdings die größten Verspätungen im Innenstadtbereich, von welchem der Neue Meßplatz aber einige Kilometer entfernt ist. Zusätzlich hatten wir nicht erwartet, dass die aufgebaute Verspätung zum Fahrtende hin wieder abnimmt, nachdem der Neue Meßplatz passiert wurde.

Heatmap: Verspätungen Fahrtrichtung Schönau

Ausblick

Trotz der Vielzahl an aussagekräftiger Ergebnisse, gab es einige Aspekte, die wir aus zeitlichen Gründen nicht weiter verfolgen konnten. So wäre es denkbar Informationen zur Verspätung auch auf der Karte zusammen mit den Streckenbelastungen anzuzeigen. Auch eine Erweiterung des Untersuchungszeitraums oder die Hinzuziehung weiterer Linien für die Verspätungsanalyse würde die Qualität und den Umfang der Ergebnisse aufwerten.