Vor einiger Zeit habe ich eine schnelle Python-Funktion zum Konvertieren einer Attributtabelle in ein Python-Wörterbuch geschrieben, bei der der Schlüssel einem benutzerdefinierten eindeutigen ID-Feld entnommen wird (normalerweise dem OID-Feld). Außerdem werden standardmäßig alle Felder in das Wörterbuch kopiert, aber ich habe einen Parameter eingefügt, mit dem nur eine Teilmenge angegeben werden kann.
def make_attribute_dict(fc, key_field, attr_list=['*']):
dict = {}
fc_field_objects = arcpy.ListFields(fc)
fc_fields = [field.name for field in fc_field_objects if field.type != 'Geometry']
if attr_list == ['*']:
valid_fields = fc_fields
else:
valid_fields = [field for field in attr_list if field in fc_fields]
if key_field not in valid_fields:
cursor_fields = valid_fields + [key_field]
else:
cursor_fields = valid_fields
with arcpy.da.SearchCursor(fc, cursor_fields) as cursor:
for row in cursor:
key = row[cursor_fields.index(key_field)]
subdict = {}
for field in valid_fields:
subdict[field] = row[cursor_fields.index(field)]
dict[key] = subdict
del subdict
return dict
Dies funktioniert hervorragend für relativ kleine Datasets, aber ich habe es gerade für eine Tabelle ausgeführt, die ungefähr 750.000 Zeilen und 15 Felder enthält - ungefähr 100 MB in einer File-Geodatabase. Auf diesen läuft die Funktion viel langsamer als ich erwartet hätte: ungefähr 5-6 Minuten (und dies ist nach dem Kopieren der Tabelle in den in_memory
Arbeitsbereich). Ich möchte wirklich einen Weg finden, um die Konvertierung in ein Wörterbuch zu beschleunigen, oder einen Einblick in eine bessere Strategie für die Bearbeitung großer Mengen von Attributdaten mit Python erhalten.
UpdateCursors funktioniert bei mir nicht gut, da bei Änderungen an einer Zeile möglicherweise Änderungen an mehreren anderen Zeilen ausgelöst werden. Es ist zu umständlich, sie nacheinander durchzugehen und zu verarbeiten, als dass ich das benötige.
quelle
subdict = {}
bis auskommentiert,del subdict
ergibt eine Verarbeitungszeit von etwa 10 Sekunden.subdict[field] = row[cursor_fields.index(field)]
schneller ist als das Anrufensubdict[field] = row.getValue(field)
. Im letzteren Szenario würden Sie einen Schritt ausführen ... obwohl der Unterschied in der Leistung zwischen der Indizierung von zwei Listen (cursor_fields
undrow
) und der Verwendung eines einzelnen ESRI-Prozesses möglicherweise nicht viel besser und möglicherweise sogar noch schlechter ist!Antworten:
Ich denke, das Problem ist wahrscheinlich Ihre zwei Zeilen, in denen Sie über die Felder gehen und jedes Feld einzeln an Ihr
subdict
Wörterbuch anhängen .Ihr
row
Objekt ist bereits ein Tupel in der gleichen Reihenfolge wie Ihre Felder, nutzen Sie dies und nutzen Sie diezip
Funktion.Dadurch wurde eine Geodatabase-Feature-Class mit 218.000 Einträgen und 16 Feldern in 8 Sekunden auf meinem System durchsucht.
Bearbeiten: Versuchte einen strengeren Test. 518k-Datensätze über eine Remote-SDE-Verbindung mit 16 Feldern, einschließlich OBJECTID und Shape, werden mit 32-Bit ausgeführt. 11 Sekunden :)
quelle
key_field
das erste Feld erstellt habe, damit ich mich darauf verlassen kannrow[0]
, den Wert von zu referenzierenkey_field
. Ich musste auch Ihre Variabledict
auf ändernattdict
. dict ist ein Schlüsselwort, und ohne dieses Schlüsselwort könnte ich es nicht verwendendict(zip())
arcpy.da
die es ermöglichen soll.