Lokalisierung der am nächsten gelegenen Einrichtung mit einer Quelle-Ziel-Matrix (QGIS3)

Im vorhergehenden Tutorial Einfache Netzwerkvisualisierung und Routing (QGIS3) lernten wir, wie man ein Netzwerk erstellt und die kürzeste Verbindung zwischen 2 Punkten bestimmt. Wir können diese Technik auf viele verschiedene Arten netzwerkbasierter Analysen anwenden. Eine Anwendung ist die Berechnung einer Quelle-Ziel-Matrix oder QZ Matrix. Angenommen wir haben eine Menge an Quell-Punkten und eine Menge an Ziel-Punkten, dann können wir für jedes Quelle-Ziel Paar die kürzeste oder schnellste Verbindung ermitteln. So eine Analyse ist sinnvoll, um die nächstgelegene Einrichtung zu jedem gegeben Punkt zu finden. Eine Logistikfirma kann diese Analyse z.B. nutzen, um das am nächsten gelegende Lager zu ihren Kunden zu bestimmen und so die Lieferrouten optimieren. Wir verenden hier den Distanzmatrix Algorithmus aus dem QGIS Network Analysis Toolbox (QNEAT3) plugin um die am nächsten liegende Gesundheitseinrichtung zu jeder Adresse in der Stadt zu bestimmen.

Bemerkung

Dieses Tutorial zeigt, wie man eigene Netzwerkdaten zur Erstellung einer Quelle-Ziel-Matrix verwenden kann. Wenn man keine eigene Netzwerkdaten hat, kann das ORS Tools Plugin verwenden. Die Analyse erfolgt dann mit Daten von OpenStreetMap ORS Tools ‣ Matrix ‣ Matrix from Layers. Unter Einzugsgebietsanalyse mit dem Openrouteservice (QGIS3) findet man weitere Informationen zur Verwendung des ORS Tools plugin.

Überblick über die Aufgabe

Wir werden 2 Layer für Washington DC verwenden - einen Layer mit Punkten für Adressen und einen anderen Layer mit Punkten für psychosoziale Einrichtungen. Wir werden dann die Einrichtung mit dem kürzesten Weg zu jeder Adresse ermitteln.

Weitere Fähigkeiten, die wir erlernen

  • Gewinnung einer geschichteten Zufallsstichprobe aus einem Punktlayer

  • Nutzung von virtuellen Layer, um eine SQL-Abfrage auf einem QGIS-Layer auszuführen

  • Nutzung der Python-Konsole um ein pygis Skript auszuführen

Beschaffung der Daten

Die Regierung des Distrikts Columbia stellt hunderte Datensätze frei zur Verfügung: Open Data Catalog.

Wir laden die folgenden Datenlayer als shape-Dateien herunter.

Der Einfachheit halber können wir eine Kopie der Datensätze unter folgenden links herunterladen:

Street_Centerlines.zip

Address_Points.zip

Adult_Mental_Health_Providers.zip

Datenquelle: [DCOPENDATA]

Einrichtung

Wir gehen zu Erweiterungen ‣ Erweiterungen verwalten und installieren. Wir suchen nach der Erweiterung QNEAT3, installieren sie und klicken dann auf Schließen.

../../_images/setup11.png

Arbeitsablauf

  1. Suche die heruntergeladene Datei Street_Centerlines.zip im Browser Bereich und erweitere sie. Ziehe die Datei Street_Centerlines.shp in den Arbeitsbereich. Füge genauso den Layer Adult_Mental_Health_Providers.shp aus der Datei Adult_Mental_Health_Providers.zip in den Arbeitsbereich ein.

../../_images/1101.png
  1. Als nächstes gehen wir zur Datei Address_Points.zip, erweitern sie und fügen den Layer Address_Points.shp hinzu. wir sehen eine große Menge an Punkten über die ganze Stadt verteilt. Jeder Punkt repräsentiert eine gültige Adresse. Wir werden zufällig 1 Punkt je Stadtviertel als Quellpunkt auswählen. Diese Technick wird geschichtete Zufallsstichprobe genannt. Gehe zu Verarbeitung ‣ Werkzeugkiste.

../../_images/249.png
  1. Suche nach dem Algorithmus Vektorauswahl ‣ Zufällige Auswahl in Untermengen.

../../_images/334.png
  1. Wir wählen Address_Points als Eingabelayer. Jeder Adresspunkt enthält ein Attribut WARD_2012, in dem die Nummer des Stadtviertels hinterlegt ist zu dem die Adresse gehört. Wir möchten nur 1 Punkt je Stadtviertel verwenden. Wir verwenden daher WARD_2012 im Kennungsfeld und setzen Anzahl/Prozentsatz gewählter Objekte auf 1.

../../_images/418.png
  1. Ein neuer Layer Extrahiert (zufällig geschichtet) wird im Layer Bereich angezeigt.

../../_images/518.png
  1. Wir schalten die Sichtbarkeit des Layers Address_Points aus. Klicke mit der rechten Maustaste auf den Layer Extracted (random stratified) und wähle Layer umbenennen.

../../_images/618.png
  1. Wir nennen den Layer mit origin_points. Analog benennen wir den Layer Adult_Mental_Health_Providers mit den psychosozialen Einrichtungen als destination_points. Die Benennung macht die Identifizierung der Layer bei der folgenden Verarbeitung einfacher. Gehe zu Verarbeitung ‣ Werkzeugkiste.

../../_images/717.png
  1. Wir gehen zum Algorithmus QNEAT3 ‣ Distance matrices ‣ OD Matrix from Layers as Table (m:n). Falls der Algoritmus nicht in den Verarbeitungswerkzeugen auftaucht, prüfen wir ob das QNEAT3 Plugin installiert ist.

../../_images/817.png
  1. Der Algorithmus ermittelt die Distanzen zwischen dem Quell- und dem Ziellayer entlang eines Netzwerkes. Wir wählen Street_Centerlines als Network layer, origin_points als From-Points layer und OBJECTID als Unique Point ID field. Analog setzen wir destination_points als To-Points Layer und OBJECTID als Unique Point ID field. Wir stellen Optimization Criterion auf Shortest Path.

../../_images/917.png
  1. Da im Straßennetzwerk viele Einbahnstraßen enthalten sind, müssen wir die Fahrrichtung unter Advanced parameters vorgeben. Unter Einfache Netzwerkvisualisierung und Routing (QGIS3) findet man weitere Details zu den Attributen im Datensatz. Wir wählen DIRECTIONA als Direction field. Gebe One Way (Digitizing direction) als Value for forward direction und One way (Against digitizing direction) als the Value for backward direction ein. Die anderen Werte lassen wir auf den Standardeinstellungen und klicken auf Run.

../../_images/1017.png
  1. Ein neue Tabelle Output OD Matrix wird nun im Layer Bereich angezeigt. Klicke mit der rechten Maustaste darauf und wähle Attributtabelle öffnen. Die Tabelle enthält 117 Zeilen. Wir hatten 9 Startpunkte und 13 Zielpunkte, die Ausgabe enthält daher 9x13 = 117 Quelle-Ziel-Paare. Das Attribut total_cost enthält die Distanz in Meter von jedem Start- zu jedem Zielpunkt.

../../_images/1121.png
  1. Im Rahmen dieses Tutorials interessiert uns nur der Zielpunkt mit der kürzesten Entfernung. Wir erstellen eine SQL-Abfrage zur Selektion des geringsten total_cost aller Ziele. Gehe zu Datenbank ‣ DB-Verwaltung...

../../_images/1218.png
  1. Im Dialogfenster DB-Verwaltung wählen wir Virtuelle Layer ‣ Projektlayer ‣ Output OD Matrix aus dem Verzeichnis auf der linken Seite. Unter Virtual layers findet man weitere Informationen zu Virtuellen Layern. Klicke auf den Knopf SQL Fenster.

../../_images/1317.png
  1. Wir geben die folgende Abfrage ein und klicken auf Ausführen. Das Resultat wird im Bereich unter der Abfrage angezeigt. Wie erwartet erhalten wir 9 Zeilen als Ergebnis, die kürzeste Verbindung für jeden Startpunkt. Setze den Haken bei Spalte mit eindeutigen Werten und wähle als Eintrag origin_id. Gebe nearest_destinations als Layername (präfix) ein. Klicke auf Laden.

select origin_id, destination_id, min(total_cost) as shortest_distance
from 'Output OD Matrix' group by origin_id
../../_images/1416.png
  1. Der neue virtuelle Layer nearest_destinations wird nun im Layer Bereich angezeigt. Die Tabelle enthält das Ergebnis unserer Analyse, die am nächsten gelegene psychosoziale Einrichtung zu jedem der 9 Startpunkte. Wir werden jetzt einige verschiedene Möglichkeiten der Visualisierung und Validierung der Ergebnisse durchgehen. Gehe zu Verarbeitung ‣ Werkzeugkiste. Suche den Algorithmus Attribute nach Feldwert und klicke doppelt darauf, um ihn zu starten.

../../_images/1515.png
  1. Wir wählen origin_points als Eingabelayer und OBJECTID als Tabellenspalte. Als Eingabelayer 2 wählen wir nearest_destinations und origin_id als Tabellenfeld 2. Klicke nun auf den Knopf neben Layer 2 zu kopierende Felder und wähle destination_id und shortest_distance. Klicke auf Starte.

../../_images/1614.png
  1. Im Layer Bereich wird nun ein neuer Zusammengefasster Layer angezeigt. Dieser Layer enthält ein Attribut mit der ID des am nächsten gelegenen Ziels für jeden Startpunkt. Wir können nun eine Nabe-Speichen-Darstellung für diesen Layer erzeugen. Wir suchen den Algorithmus Vektoranalysealysis ‣ Durch Linien verbinden (Verbindungslinien) und starten ihn.

../../_images/1715.png
  1. Wir wählen destination_points als Nabenlayer und OBJECTID als Nabenerkennungsfeld. Unter Speichenlayer tragen wir Zusammengefasster Layer` ein und als :guilabel:`Speichenerkennungsfeld` verwenden wir ``destination_id. Klicke auf Starte.

../../_images/1813.png
  1. Nach Fertigstellung der Berechnung wird ein neuer Layer Knotenlinien im Layer Bereich angezeigt. Dieser Layer stellt die Verbindung jedes Startpunktes mit dem am nächsten gelegenen Ziel dar.

../../_images/1912.png
  1. Das zum Startpunkt gehörende Ziel wurde aufgrund der entlang des Straßennetzwerkes kürzesten Verbindung gefunden. Die verwendete Visualisierung stellt dagegen die Luftlinienverbindung zwischen den Punkten dar. Daher wäre es sinnvoller, den tatsächlichen Pfad zwischen jedem Start- und Zielpunkt zu visualisieren. Mit unserer aktuellen Distanzmatrix gibt es keinen einfachen Weg so eine Darstellung zu erzeugen. Statt dessen werden wir die Visualisierung mit Hilfe eines Pythonskripts erzeugen. Zuerst werden wir den Algorithmus Kürzester Weg für 1 Quelle-Ziel-Paar starten. Starte dazu den Algorithmus QNEAT3 ‣ Routing ‣ Shortest path (point to point).

../../_images/209.png
  1. Im Dialogfenster Shortest Path (Point to Point) wählen wir Street_Centerlines als Network Layer. Wir lassen Optimization Criterion bei Shortest Path. Als nächstes lesen wir einen Start- und Zielpunkt aus. Dazu können wir auf den Knopf neben Start point klicken und dann auf einen Startpunkt im Arbeitsbereich klicken. Analog wählen wir den dazu gehörenden Endpunkt für End point. Wir erweitern den Bereich Fortgeschrittene Parameter und wählen DIRECTIONA als Direction field. Wir geben One Way (Digitizing direction) als Value for forward direction und One way (Against digitizing direction) als Value for backward direction ein. Die anderen Einstellung belassen wir so und klicken auf Starte.

../../_images/2115.png
  1. Ein neuer Layer Shortest Path Layer wird nun im Layer Bereich angezeigt. Wir sehen, dass die Verbindungslinien zwischen den Punkten keine gerade Linie ist sondern dem Straßennetzwerk folgt. Wir haben den Algorithmus für 1 Wertepaar gestartet, um die Parameter zu identifizieren, die wir im Skript nutzen werden. Wir wählen die beiden Layer Knotenlinien und Shortest Path layer, klicken mit rechten Maustaste darauf und wählen Layer löschen. Klicke auf den Knopf Historie im Bereich Verarbeitungswerkzeuge.

../../_images/2212.png
  1. Klicke auf den oben stehenden Algortihmus. Im unteren Bereich des Fensters sehen wir das vollständige Kommando. Wir kopieren das Kommando und klicken auf Schließen.

../../_images/2312.png
  1. Gehe zu Erweiterungen ‣ Python-Konsole.

../../_images/2410.png
  1. Klicke auf den Knopf Editor anzeigen in der Python-Konsole.

../../_images/257.png
  1. Kopiere das folgende Skript in das Editor-Fenster. Das Skript nutzt die Parameter aus der Prozessierungshistorie, die wir uns vorher angesehen hatten. Klicke auf den Knopf Skript ausführen, um das Skript zu starten.

../../_images/267.png
origin_layer =  QgsProject.instance().mapLayersByName('origin_points')[0]
destination_layer =  QgsProject.instance().mapLayersByName('destination_points')[0]
matrix =  QgsProject.instance().mapLayersByName('nearest_destinations')[0]

for f in matrix.getFeatures():
    origin_expr = QgsExpression('OBJECTID={}'.format(f['origin_id']))
    destination_expr = QgsExpression('OBJECTID={}'.format(f['destination_id']))
    origin_feature = origin_layer.getFeatures(QgsFeatureRequest(origin_expr))
    origin_coords =  [(f.geometry().asPoint().x(), f.geometry().asPoint().y())
        for f in origin_feature]
    destination_feature = destination_layer.getFeatures(QgsFeatureRequest(destination_expr))
    destination_coords =  [(f.geometry().asPoint().x(), f.geometry().asPoint().y())
        for f in destination_feature]
    params = {
        'INPUT':'Street_Centerlines',
        'START_POINT':'{},{}'.format(origin_coords[0][0], origin_coords[0][1]),
        'END_POINT':'{},{}'.format(destination_coords[0][0], destination_coords[0][1]),
        'STRATEGY':0,
        'ENTRY_COST_CALCULATION_METHOD':0,
        'DIRECTION_FIELD':'DIRECTIONA',
        'VALUE_FORWARD':'One Way (Digitizing direction)\n',
        'VALUE_BACKWARD':'One way (Against digitizing direction)\n',
        'VALUE_BOTH':'',
        'DEFAULT_DIRECTION':2,
        'SPEED_FIELD':None,
        'DEFAULT_SPEED':5,
        'TOLERANCE':0,
        'OUTPUT':'memory:'}
    print('Executing analysis')
    processing.runAndLoadResults("qneat3:shortestpathpointtopoint", params)
  1. Das Skript benötigt für die Abarbeitung einige Minuten. Nach der Fertigstellung sehen wir 9 neue Layer mit dem Namen Shortest Path layer. Wir führen diese Layer zu einem Layer zusammen. Gehe zum Algorithmus Vektoren allgemein ‣ Vektorlayer zusammenführen und starte ihn.

../../_images/277.png
  1. Wähle alle 9 Layer Shortest Path layer als Eingabelayer und klicke auf Starte.

../../_images/286.png
  1. Ein neuer Layer Zusammengeführt mit den kürzesten Verbindungen zwischen Start- und Zielpunkten wird erstellt.

../../_images/296.png
comments powered by Disqus