Mehr

Wie verwende ich Iteratoren in ModelBuilder, um neue Funktionen zu erstellen?

Wie verwende ich Iteratoren in ModelBuilder, um neue Funktionen zu erstellen?


Ich versuche, ModelBuilder zu verwenden, um den Prozess des Plottens von Landparzellen zu automatisieren, die mit Mineralpachtverträgen zusammenhängen.

Die vorhandene Lease-Feature-Class enthält Informationen zu Referenzdokumentinformationen, z. B. Volumen und Seite.

Ich verwende eine Datenbank, die mit Informationen zu neuen Mietverträgen gefüllt ist, die die Mietvertrags-ID sowie das Volumen und die Seite der Referenzurkunde enthalten.

Viele der neuen Mietverträge, die ich zeichne, beziehen sich auf Polygone, die bereits geplottet wurden, und beziehen sich auf dasselbe Volumen und dieselbe Seite.

Ich möchte ein Modell erstellen, das Features aus der vorhandenen Leasing-Feature-Class basierend auf den VOLUME- und PAGE-Attributen in meiner Datenbank auswählt, dieses Feature kopiert/einfügt in eine separate Feature-Class (Bearbeitungs-Layer, in den Features geladen werden) das Leasing-Dataset) und füllen Sie die Felder des neu kopierten Features mit der Leasing-ID aus meiner Datenbank aus.

Ich glaube, dass eine wiederholte Zeilenauswahl der beste erste Schritt sein könnte, aber ich bin mir nicht sicher, wo ich weitergehen soll.

Dies ist das komplizierteste ModelBuilder-Projekt, an dem ich gearbeitet habe, daher wären alle Informationen oder Vorschläge eine große Hilfe.


Die Lösung ist Python, das einen Cursor und ein Wörterbuch verwendet, um die übereinstimmende Suche durchzuführen und das Ergebnis dann mit einem Einfügecursor in eine leere Feature-Class auszugeben, die denselben Feature-Typ und dieselbe Datenstruktur wie die ursprüngliche Mineralpacht mit dem zusätzlichen Feld Pacht-ID hat vom Tisch. Der Code für die Suche ist auf diese Weise unglaublich schnell.

Der folgende Code muss nur an Ihre Daten angepasst werden (Workspace, Eingabe-Feature-Class, zugehörige Tabelle, Ausgabe-Feature-Class und Feldnamen von VOLUME, PAGE und LEASEID). Ich ging davon aus, dass Ihre Daten eine Viele-zu-Viele-Beziehung haben, bei der viele Pakete das gleiche VOLUME und die gleiche SEITE haben und viele LeaseIDs das gleiche VOLUMEN und die gleiche Seite haben können zwei Datenquellen. Die Ausgabe enthält alle Mineral-Lease-Features, einschließlich derer, die keine übereinstimmende LeaseID aus Ihrer Tabelle haben, und alle übereinstimmenden Features werden dupliziert, um so viele Features zu erstellen, wie für jede zugehörige LeaseID erforderlich sind.

Ich ging davon aus, dass Sie alle übereinstimmenden Lease-Features in einer einzigen Feature-Class ausgeben wollten, aber wenn Sie tatsächlich separate Feature-Classes für jeden Satz von Volume- und Seitenwerten erstellen möchten, dann könnte dies mit einigen geringfügigen Codeänderungen erfolgen, die ich könnte I zur Verfügung stellen. Ich könnte den Code auch leicht ändern, um den Satz von Mineral Lease-Funktionen, die keine übereinstimmenden LeaseIDs haben, von der Erstellung zu entfernen, wenn Sie sie nicht wirklich möchten.

Ich habe diesen Code mit meinen eigenen Daten mit einer Feature-Class mit über 100.000 Features und einer Viele-zu-Viele-Verknüpfungstabelle mit über 130.000 Features getestet und fast 2.074.000 Features erzeugt, die in den beiden von mir verwendeten Beziehungsfeldern übereinstimmten. Es dauerte nur 12 Minuten und 17 Sekunden, um so viele Funktionen zu erstellen (eine Rate von etwa 10.000 Funktionen alle 3 Sekunden). Die Verwendung eines ModelBuilder-Iterators und wiederholter Auswahlabfragen hätte Stunden oder Tage gedauert, um dasselbe zu tun. Mein Code erfordert nicht einmal, dass die beteiligten Bezugsfelder indiziert werden (aber Sie wagen Ihren Ansatz in ModelBuilder nicht, ohne zuerst die Bezugsfelder zu indizieren). Wenn die eindeutigen Werte meiner beiden Felder stattdessen zu einer Eins-zu-Eins- oder Viele-zu-Eins-Beziehung zwischen den beiden Datenquellen geführt hätten, wäre der Code in etwa 2 Minuten fertig.

Öffnen Sie Python Idle aus Ihrem ArcGIS-Programmordner in der Python 2.7-Gruppe, öffnen Sie eine neue Datei, fügen Sie diesen Code in die neue Datei ein und speichern Sie dann das Dokument unter dem gewünschten Namen mit der Erweiterung .py. Ändern Sie dann die Eingaben und Feldnamen entsprechend Ihren Daten und führen Sie den Code aus.

import datetime def hms_string(sec_elapsed): h = int(sec_elapsed / (60 * 60)) m = int((sec_elapsed % (60 * 60)) / 60) s = sec_elapsed % 60. return "{}:{:> 02}:{:>05.2f}".format(h, m, s) # End hms_string def timedif(end_datetime, start_datetime): Sekunden_elapsed = (end_datetime - start_datetime).total_seconds() return hms_string(seconds_elapsed) # End timedif start_time = datetime.datetime.now() print "Skriptstart: {}".format(start_time) import arcpy from arcpy import env print "Importe geladen. Verstrichene Zeit: {}".format(timedif(datetime.datetime.now() , start_time)) # ---Variablen, die Sie an Ihre Daten anpassen müssen --- # Passen Sie den Workspace-Pfad an Ihre Daten an, zum Beispiel ein Geodatabase-Workspace = r"C:UsersCRIDDocumentsArcGIS YourGeodatabase.gdb" env.workspace = workspace # Passen Sie dies an Ihren Feature-Class-Namen an (vorausgesetzt, dieser befindet sich im Arbeitsbereich) inputFC = "MineralLeasesFC" inputFCFull = workspace + '' + inputFC print inputFCFull # Passen Sie dies an Ihre Lease-ID-Tabelle (angenommen, diese befindet sich im Arbeitsbereich) relatedTable = "LeaseIDsTable" relatedTableFull = workspace + '' + relatedTable print relatedTableFull # Passen Sie dies an den gewünschten Ausgabe-FC-Namen an (vorausgesetzt, Ausgabe in den Arbeitsbereich) outputFC = "MineralLeasesWithIDs" outputFCFull = workspace + '' + outputFC print outputFCFull # Passen Sie dies als Name der Feldnamen für VOLUME, PAGE und LEASEID an inVolumeFld = "VOLUME" inPageFld = "PAGE" relatedVolumeFld = "VOLUME" relatedPageFld = "PAGE" leaseIDFld = "LEASEID" print "Variablen geladen. Verstrichene Zeit: {}".format(timedif(datetime.datetime.now(), start_time)) # ---Code, den Sie nicht ändern müssen--- # Überprüfen Sie, ob die Ausgabe bereits vorhanden ist, und löschen Sie sie, wenn sie tut if arcpy.Exists(outputFCFull): arcpy.Delete_management(outputFCFull, "FeatureClass") print "Deleted {}. Verstrichene Zeit: {}".format(outputFC, timedif(datetime.datetime.now(), start_time)) # Ausgabe-Feature-Class basierend auf der Eingabe erstellen arcpy.CreateFeatureclass_management(workspace, outputFC, "POLYGON", inputFCFull, "SAME_AS_TEMPLATEL ", "SAME_AS_TEMPLATE", inputFCFull) print "Erstellt {}. Verstrichene Zeit: {}".format(outputFC, timedif(datetime.datetime.now(), start_time)) # Feldinformationen für das LeaseID-Feld abrufen und zu den Ausgabefeldern hinzufügen = arcpy.ListFields(relatedTable) for field in Felder: if field.name.upper() == leaseIDFld.upper(): fldType = field.type fldPrecision = field.precision fldScale = field.scale fldLength = field.length fldAliasName = field.aliasName # Feld für die LeaseID hinzufügen arcpy.AddField_management(outputFCFull, leaseIDFld, fldType, fldPrecision, fldScale, fldLength, fldAliasName) print "Feld {} hinzugefügt. Verstrichene Zeit: {}".format(leaseIDFld, timedif(datetime.datetime.now(), start_time)) # Richten Sie die RelatedTable-Feldliste ein relatedFieldsList = [relatedVolumeFld, relatedPageFld, leaseIDFld] # Erstellen Sie ein Wörterbuch aus einem da SearchCursor aus dem related table relatedDict = {} with arcpy.da.SearchCursor(relatedTableFull, relatedFieldsList) as searchRows: für searchRow in searchRows: keyValue = '{};{}'.format(searchRow[0], searchRow[1]) if not keyValue in relatedDict: relatedDict[keyValue] = [searchRow[2]] else: relatedDict[keyValue].append(searchRow[2]) del searchRows, searchRow print "relatedDict von {} geladen. Verstrichene Zeit: {}".format(relatedTable, timedif(datetime.datetime.now(), start_time)) # Erstellen Sie eine Feldliste für die bearbeitbaren Felder der Eingabe- und Ausgabefelder inputFieldsList = [inVolumeFld, inPageFld] outputFieldsList = [] Felder = arcpy.ListFields(inputFCFull) für Feld in Feldern: if field.editable und field.type != 'Geometry': inputFieldsList.append(field.name) outputFieldsList.append(field.name) elif field.type == 'Geometry ': inputFieldsList.append("[email protected]") outputFieldsList.append("[email protected]") outputFieldsList.append(leaseIDFld) print "Feldliste erstellt für {}. Verstrichene Zeit: {}".format(inputFC, timedif(datetime.datetime.now(), start_time)) # Erstellen Sie ein Wörterbuch aus einem da SearchCursor inputDict = {} mit arcpy.da.SearchCursor(inputFCFull, inputFieldsList) als searchRows: für searchRow in searchRows: keyValue = '{};{}'.format(searchRow[0], searchRow[1]) falls nicht keyValue in inputDict: inputDict[keyValue] = [list(searchRow[2:])] sonst: inputDict[keyValue].append(list(searchRow[2:])) del searchRows, searchRow print "InputDict von {} geladen. Verstrichene Zeit: {}".format(inputFC, timedif(datetime.datetime.now(), start_time)) counter = 0 cursor = arcpy.da.InsertCursor(outputFCFull, outputFieldsList) für Schlüssel in inputDict: rows = inputDict[key] if key in relatedDict: for row in rows: for lease in relatedDict[key]: counter += 1 if counter % 10000 == 0: print "Hat einen Mietvertrag. Zähler = {}. Verstrichene Zeit: {}".format(counter, timedif(datetime.datetime.now(), start_time)) relatedRow = list(row) relatedRow.append(lease) cursor.insertRow(relatedRow) else: für Zeile in Zeilen: counter += 1 wenn Zähler % 10000 == 0: print "Hat kein Lease. Zähler = {}. Verstrichene Zeit: {}".format(counter, timedif(datetime.datetime.now(), start_time)) row.append(None) cursor.insertRow(row) del cursor, inputDict, relatedDict print "Inserted {} Records. Verstrichene Zeit: {}".format(counter, timedif(datetime.datetime.now(), start_time)) print "Skript beendet: {}".format(datetime.datetime.now())