OpenData: Haltestellen in Baden-Württemberg

Am 15. Juni 2019 hat die Nahverkehrsgesellschaft Baden-Württemberg (NVBW) den ersten Datensatz als OpenData bereitgestellt: die Haltestellen in Baden-Württemberg. Wir haben uns die Daten mal etwas näher angeschaut...

Vorbemerkungen

Für die Untersuchung des NVBW-Haltestellen-Datensatzes haben wir die CSV-Version vom 04.06.2019 verwendet.
Das dieser Datei zugrundeliegende Datenmodell umfasst Haltestellen, Bereiche und Steige.

Für diese gelten folgende Beziehungen:

  • Eine Haltestelle kann keinen, einen oder mehrere Bereiche haben.
  • Eine Haltestelle kann keinen, einen oder mehrere Steige haben.
  • Ein Steig ist genau einer Haltestelle und maximal einem Bereich zugeordnet.

Hat ein Halt mehrere Steige so ist jeder Steig als Zeile des Datensatzes gelistet und enthält in den ersten Spalten nochmals die Daten des übergeordneten Bereichs / Halts.

Vorbereitung

Wir importieren die Haltestellen-Liste in eine SQLite Datenbank, um einfacher Auswertungen vornehmen zu können.
Zuvor ersetzen wir in Spaltenbezeichnern der CSV-Datei die Umlaute, da wir sonst Probleme bei unseren Abfragen bekommen.

Importeinstellungen DB Browser for SQLite
Import der Haltestellen-Daten mit DB Browser for SQLite

HalteTyp

Ein Halt im Haltestellen-Datensatz kann abweichend von einer "normalen" Haltestelle im Linienverkehr auch andere Bedeutungen haben.

SELECT HalteTyp, COUNT(*) 
  FROM haltestellen 
 GROUP BY HalteTyp 
 ORDER BY COUNT(*) DESC;
HalteTyp Anzahl
normal 56928
Bedarfshaltestelle 660
nichtImNetzbereich 473
Übergangstarif 310
EinAusbringer 53
Zeitposition 47
BedarfshaltestelleAußerhalbNetzbereich 1
Schulhaltestelle 1

Insbesondere Halte vom Typ Übergangstarif, Zeitposition, EinAusbringer werden wir teilweise für weitere Analysen ausnehmen, da es sich hierbei nicht um reale Ein-/Austiegsmöglichkeiten handelt. Bei Halten außerhalb des Netzbereichs scheint es sich unter anderem um inofizielle Verkehre wie Bürgerbusse (z.B. im VVS-Gebiet) zu handeln, der auch wenn er offiziell ohne Haltestellen verkehrt, über virtuelle Haltestellen verfügt.

IFOPT-Format

Die sogenannte IFOPT-Kennung (Identification of Fixed Objects in Public Transport) ist eine internationale Kennung zur Identifikation von z.B. Haltestellen, Steige, Bahnhofsbereiche oder Bahnhöfen. In Deutschland erfolgt die Vergabe in der Regel durch den regional zuständigen Verkehrsverbund. Allerdings ist die Formatierung mitunter uneinheitlich. Teilweise wird der Gemeindeschlüssel mit führender Null, teilweise ohne angebeben. Die NVBW gibt den Gemeindeschlüssel mit führender Null an, in OSM fehlt diese in der Regel. Dies muss bei Abgleichen berücksichtigt werden.

Auch die Groß-/Kleinschreibung variiert in unterschiedlichen Datenquellen. Für den NVBW-Datensatz wird die Länderkennung de in Kleinbuchstaben angegeben, in OSM kommen auch ref:IFOPT-Werte mit großem DE vor.

Fazit: Vor einem Matching muss die IFOPT normalisiert werden, z.B. lowercase und numerische Werte ohne führende Nullen.

Probleme

Keine Haltestellen-Namen

Für 1395 Haltestellen ist der Name (Feld Haltestelle) nicht gesetzt. Für 5 davon ist immerhinHaltestelle_lang gesetzt.

SELECT Gemeinde, globaleID_Steig 
  FROM haltestellen 
 WHERE Haltestelle IS NULL
Gemeinde globaleID_Steig
Baltmannsweiler de:08116:4079:1:3
Baltmannsweiler de:08116:4079:1:4
Achern de:08317:30032:1:1
Achern de:08317:30033:1:1

(Auszug)

Keine globaleID

Für 22 Haltestellen ist die globaleID nicht gesetzt. Für 6 davon jedoch zumindest die globaleID_Steig

SELECT Gemeinde, globaleID_Steig, Haltestelle
  FROM haltestellen
 WHERE globaleID IS NULL 
Gemeinde globaleID_Steig Haltestelle
Calw de:08235:1048:0:3 SEV Calwer Str.
Calw de:08235:1048:0:4 SEV Calwer Str.
Nagold Pfrondorfer Mühle
Nagold Pfrondorfer Mühle
Wildberg de:08235:080:0:3 Schönbuchstr.
Freudenstadt FDS Zum Waldcafe
Freudenstadt Friedrichsturm
Freudenstadt Berghütte
Karlsruhe Betriebshof Hagro
Meißenheim de:08317:1:0:1 Im Wald
Rust de:08317:19113:1:Bus 1 Europa-Park Verwaltung
Rust de:08317:19113:1:Bus 2 Europa-Park Verwaltung
Iffezheim Staustufe
Iffezheim Staustufe
Kuppenheim Ausstieg Walz
Kuppenheim Weingärtenstraße
Rheinmünster Airpark Victoria Blvd
Rheinmünster Airpark Victoria Blvd
Rheinmünster Airpark Winnipeg Ave
Rheinmünster Airpark Winnipeg Ave
Rheinmünster Airpark Yellowknife Ave
Rheinmünster Airpark Yellowknife Ave

Keine Steige

Ca. 25% der Halte in Baden-Württemberg sind noch nicht mit Steiginformationen erfasst. Das bedeutet, das z.B. ein Fußgängerrouting nicht zum tatsächlichen Abfahrtsort des Busses/der Bahn routet, sondern zu einem als repräsentativ angenommenen Punkt der gesamten Haltestelle. Da unterschiedliche Gleise/Steige eines Haltes mitunter mehrere Fußminuten voneinander entfernt liegen können, sind für diese 25% der Halte keine aussagekräftigen Umsteigezeiten ableitbar.

Karte der Halte in Baden-Württemberg mit und ohne Steiginformation
Halte mit (gelb) und ohne (rot) Steiginformation (Datensatz der NVBW GmbH, Hintergrundkarte © OpenStreetMap Mitwirkenden)
SELECT hat_steig, COUNT(*) 
  FROM (SELECT CASE 
                 WHEN globaleID_Steig IS NULL THEN 'Kein Steig' 
                 ELSE "Mit Steig" 
               END hat_steig 
          FROM haltestellen 
         WHERE HalteTyp NOT IN ('Übergangstarif', 'Zeitposition', 'EinAusbringer')) 
  GROUP BY hat_steig;
Steig? Anzahl
Kein Steig 14549
Mit Steig 43514

Keine Koordinaten

Für knappe 10% der Datensätze sind die Koordinaten der Steige/Haltestellen nicht angegeben.

SELECT 'Halltestellen ohne Koordinate', COUNT(*) 
  FROM haltestellen 
 WHERE lat IS NULL 
 UNION 
SELECT 'Steige ohne Koordinate', COUNT(*) 
  FROM haltestellen 
 WHERE globaleID_Steig IS NOT NULL 
   AND lat_Steig IS NULL;
Problem Anzahl
Halltestellen ohne Koordinate 2051
Steige ohne Koordinate 4165

Einen ungefähres Bild der Verantworlichkeiten ergibt sich, wenn man die nicht abgleichbaren Stops der OSM-Daten hinsichtlich ihres network-Attributs auswertet. Nachfolgend die häufigsten Verbünde:

Verbund Anzahl ungematchter Stops
(kein Network in OSM) 1796
VRN 1168
HNV 677
TNW 151
VVS 60
bodo 51
VHB Verkehrsverbund Hegau Bodensee 34
Verkehrsverbund Rhein-Neckar 22
DING 16
RVF 16
OstalbMobil 14
RMV 13

Quelle: (C) OpenStreetMap, Mitwirkende

Fehlerhafte Koordinaten

Für ein Dutzend Steige befindet sich Position der Halte in der Nähe von São Tomé und Príncipe. Sind solche Halte einer Linie zugeordnet, kann dies dazu führen, dass ein Routenplaner diese Stops und in der Folge die gesamte Linie nicht übernehmen kann.

Halte in der Nähe des Koordinatenursprungs bei São Tomé und Príncipe
Halte in der Nähe des Koordinatenursprungs bei São Tomé und Príncipe (© OpenStreetMap Mitwirkende, Datensatz der NVBW GmbH)
SELECT globaleID, lat, lon 
  FROM haltestellen 
 WHERE lat NOT BETWEEN 47.533 AND 49.792 
    OR lon NOT BETWEEN 7.511 AND 10.492
 UNION 
SELECT globaleID_Steig, lat_Steig, lon_Steig 
  FROM haltestellen 
 WHERE lat_Steig NOT BETWEEN 47.533 AND 49.792 
    OR lon_Steig NOT BETWEEN 7.511 AND 10.492
IFOPT ID lat lon
de:08425:2670:0:1 0.0785147 0.3547421
de:08327:7965:1:1 0.0881413185121585 0.484615029294516
de:08327:7965:1:2 0.0881323750067003 0.484615031246505
de:08327:5122:0:1 0.0877299133496377 0.484597351583878
de:08327:5122:0:2 0.0877299133496377 0.484597351583878
de:08237:5121:0:1 0.0877835763368072 0.4846062235684
de:08237:5121:0:2 0.0877925198420635 0.484606221624505
de:08327:5111:0:1 0.0874705263586282 0.484481920484227
de:08327:5111:0:2 0.0874705263586282 0.484481920484227
de:08237:5112:0:1 0.087425799104188 0.484437511963712
de:08237:5112:0:2 0.087425799104188 0.484437511963712
de:08335:74640:1:1 0.868906851441604 3.4867815104852

Mehrfache vergebene globaleID für Steige

129 globalID_Steig-Werte sind mehr als einmal vergeben. Schaut man sich diese genauer an, hat dies scheinbar verschiedene Ursachen:

  • tatsächlich falsch vergebene IDs, Steig-Id in globaleID_Steig weicht von der in Name_Steig angegebenen ab
  • Mehrfache Datensätze für den selben Steig, mutmaßlich um alternative Bezeichner zu verwenden (uns ist unklar, ob die Ursache ein Problem beim Export ist oder in der Modellierung)
  • Selber Steig mit mehreren Koordinaten. Mutmaßlich wurde die Lage in den Daten korrigiert, der alte Datensatz jedoch nicht gelöscht. Hätte es sich um eine Verlegung gehandelt, hätten wir erwartet, dass sich gültigVon und gültigBis bei beiden Datensätzen unterscheiden. Womöglich handelt es sich jedoch auch um ein Export-Problem, falls die Gültigkeitsinformation nur für den gesamten Halt, nicht jedoch die Steige exportiert wurden.
SELECT COUNT(*) 
  FROM (SELECT globaleID_Steig, COUNT(*) 
          FROM haltestellen 
         WHERE globaleID_Steig IS NOT NULL 
         GROUP BY globaleID_Steig 
        HAVING COUNT(*) > 1);

Eine beispielhafte Auswahl solcher Steige:

SELECT Haltestelle_lang, globaleID_Steig, Name_Steig, lat_Steig, lon_Steig, gueltigAb, gueltigBis 
  FROM haltestellen where globaleID_Steig IN (
  SELECT globaleID_Steig 
    FROM haltestellen 
   WHERE globaleID_Steig IS NOT NULL 
   GROUP BY globaleID_Steig 
  HAVING COUNT(*) > 1);
Haltestelle_lang globaleID_Steig Name_Steig lat_Steig lon_Steig gueltigVon gueltigBis
Bad Herrenalb Kullenmühle de:08235:9711:1:1 >Halb 48.808778378628 8.44384199500043
Bad Herrenalb Kullenmühle de:08235:9711:1:1 zum LÖSCHEN 48.8093652743551 8.44433925324395
Wildberg, Bildungszentr. de:08235:7330:0:4 Stg 2
Wildberg, Bildungszentr. de:08235:7330:0:4 Stg 4
Bauschlott Sportplatz de:08236:2004:0:1 Richtung Bretten 48.9667126944966 8.72900365801215
Bauschlott Sportplatz de:08236:2004:0:1 Richtung PF 48.9667126944966 8.72900365801215
Jungingen Auf dem Hart de:08421:1173:0:1 Edith-Stein-Ring 48.4392051 9.9882978
Jungingen Auf dem Hart de:08421:1173:0:1 Steig A 48.4392051 9.9882978
Ulm Kuhberg Schulzentrum de:08421:1390:1:A Steig A 48.3837151131627 9.95544004044851
Ulm Kuhberg Schulzentrum de:08421:1390:1:A Steig A 48.3833822 9.9545574

Keine Gültigkeitsangaben für Steige

Siehe Deutung mehrfacher Steige mit gleicher globaleID_Steig. Wir vermuten, dass der Gültigkeitszeitraum für Steige nicht exportiert wurden und eventuell auch mittlerweile nicht mehr gültige Datensätze exportiert wurden.

Aufeinanderliegende Steig-Koordinaten

3256 Steig-Koordinaten sind mehreren Steigen zugeordnet. Hierin enthalten sind die vorgenannten 129 doppelten Steig-IDs. Um Reisenden präzise Wegbeschreibungen und realistische Wegezeiten ausgeben zu können, sollten die Lagen präziser erfasst werden. Dies erleichtert zudem den Abgleich mit anderen Datenquellen wie beispielsweise OpenStreetMap.

SELECT COUNT(*) 
  FROM (SELECT DISTINCT a.lat_Steig, a.lon_Steig 
          FROM haltestellen a, haltestellen b 
         WHERE a.globaleID_Steig!=b.globaleID_Steig 
           AND a.lat_Steig = b.lat_Steig 
           AND a.lon_Steig=b.lon_Steig);

Fehlende Vorgaben bzgl. Haltestellen-Name/Haltestellen-Name lang / Systembeschränkungen(?)

Die Inhalte der Angaben Haltestelle und Haltestelle_lang sind uneinheitlich erfasst. Für viele Datensätze ist Haltestelle_lang komplett leer. Für andere beinhaltet er den um den Ortsnamen ergänzten Haltestellen-Namen. Der Name der Haltestelle (Haltestelle) enthält häufig Abkürzungen, der Haltestellen_lang enthält den Namen jedoch so gut wie nie unabgekürzt. Das Format von Haltestelle_lang ist ebenfalls nicht einheitlich, mal <Ort> <Haltname> (ohne Komma), mal <Ort>, <Haltname> (mit Komma). Insgesamt scheinen Feld-Längenbegrenzungen in den genutzten Systemen Abkürzungen bis zur Unleserlichkeit zu erzwingen.

Beispiele:

SELECT Haltestelle, Haltestelle_lang 
  FROM haltestellen 
 WHERE (LENGTH(Haltestelle)-LENGTH(REPLACE(Haltestelle, '.','')) > 0
Haltestelle Haltestelle_lang
4.Industriestraße Talhaus, 4.Industriestraße
G-Hauptmann-Str. 32 Pfullingen G-Hauptmann-Str. 32
Winn. Stöckachschule
Schornd. N. Friedhof
Schornd. Oskar Frech
Schornd. R.-M.-Klinik
Bietigh. Agentur für

Halt-ID/Bereich-ID der Steig-ID weicht ab von Halt-ID/Bereich-ID

Für einige Halte entspricht die in der globaleID_Steig angegebenen Bereichs-ID nicht der des übergeordneten Bereichs. Für weitere Halte entspricht die in der globaleID_Steig angegebenen Halt-ID nicht der des übergeordneten Haltes.

SELECT 'Bereich-ID der Steig-ID weicht von Bereich-ID ab', COUNT(*) 
  FROM Haltestellen 
 WHERE NOT globaleID_Steig LIKE globaleID_Bereich||'%'   
 UNION 
SELECT 'Halt-ID der Steig-ID weicht von Halt-ID ab', COUNT(*) 
  FROM Haltestellen 
 WHERE NOT globaleID_Steig LIKE globaleID||'%';
Haltestelle Haltestelle_lang
Bereich-ID der Steig-ID weicht von Bereich-ID ab 434
Halt-ID der Steig-ID weicht von Halt-ID ab 34

Tippfehler in Landkreis-Schlüssel der gobaleID

In Baden-Württemberg wird als zweite Komponente der globaleID der 5-stellige Gemeindeschlüssel des Landkreises innerhalb dessen sich ein Halt befindet verwendet.
Dies ist jedoch aufgrund mutmaßlicher Tippfehler nicht der Fall:

SELECT landkreis, landkreis_schl, COUNT(*) FROM
 (SELECT landkreis, SUBSTR(globaleID,4,5) landkreis_schl 
    FROM Haltestellen 
   WHERE globaleID IS NOT NULL
   UNION ALL
  SELECT landkreis, SUBSTR(globaleID_Steig,4,5) landkreis_schl 
    FROM Haltestellen 
   WHERE globaleID_Steig IS NOT NULL
   UNION ALL
  SELECT landkreis, SUBSTR(globaleID_Bereich,4,5) landkreis_schl 
    FROM Haltestellen 
   WHERE globaleID_Bereich IS NOT NULL  
  )
  GROUP BY landkreis,landkreis_schl
  HAVING COUNT(*) < 50;
Landkreis Gemeindschlüssel aus globaleID(_Bereich/_Steig) Anzahl
Breisgau-Hochschwarzwald 00815 1
Calw 5:110 1
Enzkreis 00823 1
Enzkreis 08235 3
Enzkreis 36:28 2
Freiburg im Breisgau 03811 1
Freiburg im Breisgau 08315 2
Freudenstadt 08327 6
Freudenstadt 237:4 6
Göppingen 08116 1
Hohenlohekreis 08125 2
Karlsruhe (Land) 07334 1
Pforzheim 08236 2
Rhein-Neckar-Kreis 08222 22
Tuttlingen 08237 6
Tuttlingen 98327 1

Ersatzverkehre

Bei temporären Sperrungen von Strecken oder Haltestellen, z.B. im Rahmen von Bauarbeiten werden Ersatzverkehre eingerichtet. Halte dieser Ersatzverkehre sind nicht explizit als HalteTyp Ersatzhalt ausgezeichnet, sondern tragen im Namen_Bereich oder Name_Steig ein "Ersatzverkehr" oder "SEV" o.ä. Wir regen die Einführung eines expliziten Attributs an. Noch besser wäre zudem eine Referenz auf den ersetzten Halt/Steig.

SELECT Haltestelle, Name_Bereich, Name_Steig, globaleID_Steig, globaleID
  FROM haltestellen 
 WHERE (Haltestelle LIKE '%rsatz%' OR Haltestelle  LIKE '%SEV%' 
    OR Name_Bereich LIKE '%rsatz%' OR Name_Bereich LIKE '%SEV%' 
    OR Name_Steig   LIKE '%rsatz%' OR Name_Steig   LIKE '%SEV%')
Haltestelle Name_Bereich Name_Steig globaleID_Steig globaleID
Kirche (Ersatz-Hst.) Hst. ohne Bereich Alle Richtungen de:08425:3680:0:1 de:08425:3680
Bahnhof Bus Steig 1 (SEV) de:08425:3601:1:1 de:08425:3601
Bahnhof Baden-Baden SEV West SEV West de:08211:1847:1:11 de:08211:1847
Gausplatz Hst. ohne Bereich Ersatzhaltestelle Ri Museen de:08211:31937:0:3 de:08211:31937
Satzweg (Ersatzhalt) Hst. ohne Bereich Ri Baden-Baden de:08211:31848:0:91 de:08211:31848
Aldi-Kreisel (SEV) Hst. ohne Bereich Biberach de:08426:6810:0:2 de:08426:6810
Berufsschulzentrum (BSZ) Hst. ohne Bereich SEV-Halt de:08426:6086:0:10 de:08426:6086
Viehmarkt/Zeppelinring Danzigbrücke (Ersatzhaltestelle) de:08426:6132:0:2 de:08426:6132
Simmisgasse Ersatzhalte Ulmer/EKZ - Ri. Stadtmitte de:08426:6352:0:2 de:08426:6352
Lerchenweg (Ersatz-Hst.) Hst. ohne Bereich Ri. Seekirch/Biberach de:08426:6614:0:2 de:08426:6614
Böblingen Talstraße Hst. ohne Bereich Ersatzhaltestelle de:08115:4619:0:5 de:08115:4619

(Auszug)

Bedientes Verkehrsmittel

Für Steige werden in den Daten zwar die Attribute [Fuß/Fahrrad/Individualverkehr/Straßenbahn/ Schmalspurbahn/Eisenbahn/Fähren]_Verbindung angegeben. Diese scheinen jedoch nur unzulänglich gepflegt und zudem hinsichtlich ihrer Bedeutung uneinheitlich ausgelegt zu werden. Weder beschreiben sie zuverlässig das an diesem Steig bediente Verkehrsmittel (zumindest haben 1725 Steige mit der Angabe 'Bus' im Namen des Bereiches kein 'X' für Bus_Verbindung eingetragen), noch beschreiben Sie an einer Haltestelle mögliche Umstiege in ein anderes Verkehrsmittel. Auch das Kriterium für Fuß- und Fahrradverbindung lässt sich nicht nachvollziehen. Einzig das Attribut Individualverkehr_Verbindung ist durchgängig für alle Steige vom HalteTyp 'normal' gesetzt.
Wünschenswert wäre aus unserer Sicht insbesondere die Angabe des/der an einem Steig bedienten Verkehrsmittel, so dass diese nicht fehleranfällig aus den Namen des Bereichs oder Steigs geraten werden müssen.

Fazit

Die Haltestellen-Daten der NVBW weisen noch eine Reihe von Inkonsistenzen und Fehlern auf. Zur Dokumentation und dem Austausch mit der OpenData-Community regen wir die Einrichtung eines Issue-Trackers an.

Wünschenswert wäre, dass der Haltestellen-Datensatz aufgrund der kontinuierlich stattfindenden Qualitätsverbesserungen der Daten in kürzeren Abständen möglichst automatisiert veröffentlicht wird. Die Veröffentlichung sollte unter gleichbleibendem Pfad erfolgen, so das verarbeitende Prozesse automatisiert gestartet werden können.

Wir freuen uns sehr darüber, dass sich NVBW und das Land Baden-Württemberg auf den Weg gemacht hat, Daten im Verkehrsbereich als OpenData bereitzustellen. Dies ermöglicht es sowohl der OpenData-Community als auch der Verwaltung und Verkehrsunternehmen, die Qualität der jeweils 'eigenen' Daten zu evaluieren und zu verbessern.

Ausblick

Im nächsten Artikel vergleichen wir den NVBW-Haltestellen-Datensatz mit den in OpenStreetMap erfassten Haltestellen.