Wie kann die Leistung bei Verwendung von ArcGIS-Cursorn in Python mit großen Tabellen verbessert werden?

10

Ich habe eine ziemlich große Punkt-Feature-Class in einer Datei-Geodatabase (~ 4 000 000 Datensätze). Dies ist ein reguläres Punktraster mit einer Auflösung von 100 m.

Ich muss eine Art Verallgemeinerung auf dieser Ebene durchführen. Dazu erstelle ich ein neues Gitter, in dem jeder Punkt in der Mitte von 4 "alten" Punkten liegt:

 *     *     *     *
    o     o     o
 *     *     *     *
    o     o     o
 *     *     *     *

[*] = Punkt des ursprünglichen Gitters - [o] = Punkt des neuen Gitters

Der Attributwert jedes neuen Punktes wird basierend auf den gewichteten Werten seiner 4 Nachbarn im alten Raster berechnet. Ich schleife also alle Punkte meines neuen Gitters und für jeden von ihnen alle Punkte meines alten Gitters, um die Nachbarn zu finden (indem ich die Werte von X und Y in der Attributtabelle vergleiche). Sobald 4 Nachbarn gefunden wurden, verlassen wir die Schleife.

Hier gibt es keine methodische Komplexität, aber mein Problem ist, dass dieses Skript nach meinen ersten Tests wochenlang abgeschlossen sein wird ...

Sehen Sie eine Möglichkeit, es effizienter zu machen? Ein paar Ideen auf meinem Kopf:

  • Indizieren Sie die Felder X und Y => Ich habe das getan, aber keine signifikante Leistungsänderung festgestellt
  • Führen Sie eine räumliche Abfrage durch, um die Nachbarn zu finden, anstatt eine auf Attributen basierende. Würde das tatsächlich helfen? Welche räumliche Funktion in ArcGIS sollte die Aufgabe übernehmen? Ich bezweifle, dass sich beispielsweise das Puffern jedes neuen Punkts als effizienter erweisen wird
  • Transformieren Sie die Feature-Class in ein NumPy-Array. Würde das helfen? Ich habe bisher nicht viel mit NumPy gearbeitet und würde nicht gerne darauf eingehen, es sei denn, jemand sagt mir, dass dies wirklich dazu beitragen könnte, die Verarbeitungszeit zu verkürzen
  • Noch etwas?
Stéphane Henriod
quelle
Welche Version von Arcmap verwenden Sie?
Martin
Haben Sie über PostGIS nachgedacht? Ist das eine Option?
Chad Cooper
Entschuldigung, dass ich das vergessen habe: ArcGIS 10.1 // Python 2.7
Stéphane Henriod
Nein, PostGIS ist leider keine Option, meine Hände sind hier leider ziemlich gebunden ... Bestenfalls kann ich Oracle mit den SDE-Funktionen verwenden
Stéphane Henriod

Antworten:

13

Was wäre, wenn Sie die Punkte in ein numpy-Array einspeisen und einen scipy cKDTree verwenden würden, um nach Nachbarn zu suchen? Mit dieser Technik verarbeite ich LiDAR-Punktwolken mit einer großen Anzahl von Punkten (> 20 Millionen) in mehreren MINUTEN. Es ist die Dokumentation hier für kdtree und hier für numpy Konvertierung. Grundsätzlich lesen Sie das x, y in ein Array und iterieren über jeden Punkt im Array, um Indexe von Punkten innerhalb einer bestimmten Entfernung (Nachbarschaft) von jedem Punkt zu finden. Mit diesen Indizes können Sie dann andere Attribute berechnen.

Barbarossa
quelle
Diese Antwort ist besser als meine
Radouxju
Ich mag diese Idee, aber ich habe kein Scipy auf der Workstation, an der ich arbeite (und keine Administratorrechte). Wenn ich es schaffe, dieses Paket zu installieren, werde ich es versuchen
Stéphane Henriod
4

Ich bin bei Barbarossa ... bogenförmige Cursor sind wahnsinnig lahm, deshalb benutze ich sie nur, um eine Tabelle oder Feature-Class genau einmal zu durchlaufen. Wenn ich die Arbeit nicht in einem Zyklus erledigen kann, benutze ich den Cursor, um eine andere Art von Datenstruktur aufzufüllen und damit zu arbeiten.

Wenn Sie sich nicht mit Numpy herumschlagen möchten, erstellen Sie einfach ein einfaches Python- Wörterbuch, in dem Sie Ihre Koordinaten als einfachen Textschlüssel verwenden, und geben Sie die für die Berechnung erforderlichen Attribute als Wert des Wörterbuchelements in eine Liste ein .

In einem zweiten Schritt können Sie leicht die Werte abrufen, die Sie zur Berechnung eines Punktes benötigen, indem Sie sie einfach aus Ihrem Wörterbuch abrufen (was aufgrund des Wörterbuch-Hashindex der Elemente unglaublich schnell ist).

Jürgen Zornig
quelle
Ich mag deine Idee mit Wörterbüchern und habe sie gerade umgesetzt. Es funktioniert in der Tat viel besser ... bis ich die Ergebnisse tatsächlich mit einer row.insertRow () schreibe ... Irgendeine Idee, wie ich diesen Teil auch verbessern kann?
Stéphane Henriod
Ich hatte ein ähnliches Problem, bei dem ich 10.000 Punkte aus 14 Mio. auswählen musste. und dann löschen. arcpy.cursors konnten nur etwa 1 oder 2 Punkte pro Sekunde (!) löschen. Also habe ich das pyodbc-Modul installiert, um sie mit einer einzigen SQL DELETE-Anweisung in nur einer Sekunde zu löschen. UPDTATEing über SQL bringt Ihnen viele Verbesserungen, solange Sie nur Attribute ändern möchten ... dennoch müssen Sie zusätzliche Python-Module installieren ... aber es lohnt sich.
Jürgen Zornig
2

Für ein reguläres Raster sollte es weitaus effizienter sein, in einem Rasterformat zu arbeiten. Konvertieren Sie Ihr erstes Raster in ein Raster. Sie können mit einem bilinearen Interpolator mit derselben Auflösung neu abtasten, aber Ihr Ausgabebild in X und Y um 1/2 Pixel verschieben und wieder zu Punkten zurückkehren, wenn Sie noch Punkte benötigen.

BEARBEITEN: Für komplexe Entscheidungsregeln können Sie jedes der Felder, die Sie als neues Rasterband benötigen, konvertieren. Anschließend erstellen Sie vier Kopien dieser Bänder und verschieben Ihr Raster in die 4 Richtungen um 1/2 Pixel (+50, - 50), (+ 50, + 50), (-50, -50) und (-50, + 50). Dann können Sie die reguläre Kartenalgebra verwenden

Radouxju
quelle
Vielen Dank, ich habe tatsächlich an diese Lösung gedacht, bin mir aber nicht sicher, ob / wie ich die Berechnung des neuen Werts im Rasterformat implementieren kann. Lassen Sie mich erklären: Für jeden neuen Punkt (oder jede neue Rasterzelle) muss der Wert als solcher berechnet werden: Ich nehme den Wert jedes seiner Nachbarn. Jeder dieser Werte hat eine Wahrscheinlichkeit, dem neuen Punkt einen bestimmten Wert zu geben. Wenn beispielsweise ein Nachbar den Wert 202 hat, gibt er den Wert 3 (mit einem Gewicht von 1) oder den Wert 11 (mit einem Gewicht von 5). Wir fassen dann für alle 4 Nachbarn zusammen und finden den neuen Wert ... Nicht sicher, ob dies sehr klar ist ...
Stéphane Henriod
PS: Die Berechnung zum Ermitteln des neuen Werts kann in einigen Fällen auf zwei Attributen basieren, nicht nur auf einem, wodurch der Raster-Ansatz möglicherweise verworfen wird
Stéphane Henriod,
Für Ihre gewichtete Summe benötigen Sie nur zwei Raster: eines, bei dem Sie das Produkt aus Gewichten und Werten neu abtasten, das zweite, bei dem Sie nur die Gewichte neu abtasten. Wenn Sie die erste durch die zweite teilen, erhalten Sie Ihre gewichtete Summe.
Radouxju
1
@ StéphaneHenriod - Als Vorschlag können Sie die Frage bearbeiten, um diese zusätzlichen Spezifikationen hinzuzufügen. Angesichts der ersten Frage halte ich diese Antwort für sehr sinnvoll, aber mit diesen neuen Informationen sieht Barbarossas Antwort gut aus.
Nicksan
2

Vielen Dank an alle für Ihre Hilfe!

Ich habe endlich einen sehr nicht-pythonischen Weg gefunden, um dieses Problem zu lösen ... Was tatsächlich die meiste Rechenzeit in Anspruch nahm, war, die 4 Nachbarn jedes Punktes zu finden. Anstatt die X- und Y-Attribute zu verwenden (entweder mit einem Arcpy-Cursor oder in einer anderen Datenstruktur, z. B. einem Python-Ditionär), habe ich schließlich das ArcGIS-Tool Generate Near Table verwendet . Ich gehe davon aus, dass dies die räumlichen Indizes ausnutzt und die Leistungen offensichtlich viel höher sind, ohne dass ich den Index selbst implementieren muss.

Stéphane Henriod
quelle
0

Das Problem mit Cursorn ist, dass Sie sie nur auf eine Weise durchlaufen können und nicht zurückkehren können. Obwohl dies nicht empfohlen wird, können Sie die Feautres in eine Struktur einfügen, wenn Sie sie erneut besuchen möchten.

Wenn Sie Ihre Funktionen in einer einzigen Schleife verarbeiten konnten, empfehle ich, das Recycling zu aktivieren. Dies ist ein Parameter in Ihrer Funktion der Such-Feature-Class, mit dem Python den von alten Features zugewiesenen Speicher wiederverwenden und das Durchlaufen der Features in einem Cursor erheblich beschleunigen kann. Sie können Ihr Raster 80% schneller verarbeiten.

Das Problem ist, dass Sie das Recycling nicht aktivieren können, wenn Sie die von einem Cursor abgerufenen Features speichern möchten.

hnasr
quelle
Ich möchte dieses Thema "Cursor recyceln" untersuchen, kann jedoch keine Dokumentation in der ESRI-Hilfe finden. Hast du einen Link? Der Suchcursor hat keinen Recycling-Parameter. Select_by_Attribute hat keinen solchen Parameter. Ich sehe nichts in ENV.
Klewis
Ich schrieb vor einiger Zeit
hnasr
1
Ich glaube nicht, dass "Wiederverwenden von Cursorn" über ArcPy verfügbar ist, nur mit den wichtigsten Arcobjects.
Klewis