Hace un tiempo, escribí una función rápida de Python para convertir una tabla de atributos en un diccionario de Python, donde la clave se toma de un campo de ID único especificado por el usuario (generalmente el campo OID). Además, de forma predeterminada, todos los campos se copian en el diccionario, pero he incluido un parámetro que permite especificar solo un subconjunto.
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
Esto funciona muy bien para conjuntos de datos relativamente pequeños, pero solo lo ejecuté en una tabla que contiene aproximadamente 750,000 filas y 15 campos, alrededor de 100 MB en una geodatabase de archivos. En estos, la función funciona mucho más lentamente de lo que esperaba: alrededor de 5-6 minutos (y esto es después de copiar la tabla en el in_memory
espacio de trabajo). Realmente me gustaría encontrar una manera de acelerar la conversión al diccionario, u obtener una idea de una mejor estrategia para manipular grandes cantidades de datos de atributos utilizando Python.
UpdateCursors no funcionará bien para mí, porque cuando cambia una fila, tiene el potencial de provocar cambios en varias otras. Recorrerlos y procesarlos uno por uno es demasiado engorroso para lo que necesito.
fuente
subdict = {}
través dedel subdict
produce un tiempo de procesamiento de aproximadamente 10 segundos.subdict[field] = row[cursor_fields.index(field)]
son más rápidas que las llamadassubdict[field] = row.getValue(field)
. En el último escenario, estaría realizando un paso ... ¡aunque la diferencia en el rendimiento entre indexar dos listas (cursor_fields
yrow
) y usar un solo proceso de ESRI puede no ser mucho mejor e incluso podría ser peor!Respuestas:
Creo que el problema es probablemente sus dos líneas donde va sobre los campos y agrega cada campo individualmente a su
subdict
diccionario.Su
row
objeto ya es una tupla en el mismo orden que sus campos, aproveche eso y use lazip
función.Esto atravesó una clase de entidad de geodatabase de archivos de campo de registro de 218k en 8 segundos en 8 segundos en mi sistema.
Editar: Intenté una prueba más rigurosa. Los registros de 518k en una conexión SDE remota con 16 campos, incluidos OBJECTID y Shape, se ejecutan a 32 bits. 11 segundos :)
fuente
key_field
el primer campo para poder confiar en el usorow[0]
para hacer referencia al valor dekey_field
. También tuve que cambiar tu variabledict
aattdict
. dict es una palabra clave, y sin esa palabra clave que no podía usardict(zip())
arcpy.da
está destinado a habilitar.