12 votos

Métodos más rápidos para la modificación de tablas de atributos con Python?

Hace un tiempo, escribí una rápida función de Python para la conversión de una tabla de atributos para un diccionario de python, donde la clave es tomado de un usuario especificado por el campo IDENTIFICADOR exclusivo (normalmente el OID de campo). Además, por defecto, todos los campos se copian en el diccionario, pero he incluido un parámetro que sólo permiten un subconjunto específico.

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 los relativamente pequeños conjuntos de datos, pero sólo me encontré en una tabla que contiene alrededor de 750,000 filas y 15 campos -- alrededor de 100MB en una geodatabase de archivos. En estos, la función se ejecuta mucho más lento de lo que yo habría esperado: alrededor de 5 a 6 minutos (y esto es después de copiar la tabla a de la in_memory de área de trabajo). Realmente me gustaría encontrar una manera de acelerar la conversión de diccionario, o de obtener alguna información sobre la mejor estrategia para la manipulación de grandes cantidades de datos de atributo usando Python.

UpdateCursors no funciona bien para mí, porque cuando uno de los cambios de fila, que tiene el potencial de desencadenar cambios en varios otros. Bucle a través de su tratamiento y transformación de una en una es demasiado engorroso para lo que yo necesito.

16voto

Sork Puntos 26

Creo que el problema es probable que sus dos líneas donde usted va a través de los campos y anexando cada campo de forma individual a su subdict diccionario.

for field in valid_fields:
    subdict[field] = row[cursor_fields.index(field)]

Su row objeto es ya una tupla en el mismo orden que los campos, tomar ventaja de eso y el uso de la zip función.

def make_attribute_dict(fc, key_field, attr_list=['*']):
    attdict = {}
    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]
    #Ensure that key_field is always the first field in the field list
    cursor_fields = [key_field] + list(set(valid_fields) - set([key_field]))
    with arcpy.da.SearchCursor(fc, cursor_fields) as cursor:
        for row in cursor:
            attdict[row[0]] = dict(zip(cursor.fields,row))
    return attdict

Este resoplando a través de un 218k la cifra récord de 16 campo archivo de clase de entidad de geodatabase en 8 segundos en mi sistema.

Edit: se Trató de una prueba más rigurosa. 518k registros de más de un remoto conexión de SDE con 16 campos como el de la OBJECTID y la Forma de correr en 32 bits. 11 segundos :)

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X