Más

¿Cómo usar iteradores en ModelBuilder para crear una nueva función?

¿Cómo usar iteradores en ModelBuilder para crear una nueva función?


Estoy intentando utilizar ModelBuilder para automatizar el proceso de trazar parcelas de tierra relacionadas con arrendamientos de minerales.

La clase de entidad de arrendamiento existente contiene información relacionada con la información del documento de referencia, como el volumen y la página.

Estoy usando una base de datos poblada con información relacionada con nuevos arrendamientos, que contiene el ID del arrendamiento y el volumen y la página de la escritura de referencia.

Muchos de los nuevos arrendamientos que trazo se refieren a polígonos que ya han sido trazados y se refieren al mismo volumen y página de la escritura.

Lo que me gustaría hacer es crear un modelo que seleccione entidades de la clase de entidad de arrendamiento existente en función de los atributos VOLUME y PAGE en mi base de datos, copiar / pegar esa entidad en una clase de entidad separada (capa de edición desde la que se cargan las entidades el conjunto de datos de arrendamiento) y rellenar los campos de la función recién copiada con el ID de arrendamiento de mi base de datos.

Creo que la selección de filas iterativas podría ser el mejor primer paso, pero no estoy seguro de a dónde ir desde allí.

Este es el proyecto ModelBuilder más complicado en el que he trabajado, por lo que cualquier información o sugerencia sería de gran ayuda.


La solución es Python usando un cursor y un diccionario para realizar la búsqueda coincidente y luego generar el resultado con un cursor de inserción en una clase de entidad vacía que tiene el mismo tipo de entidad y estructura de datos que el arrendamiento mineral original con el campo adicional ID de arrendamiento. de la mesa. El código para realizar la búsqueda es increíblemente rápido de esta manera.

Aquí hay un código que solo necesita adaptarse a sus datos (espacio de trabajo, clase de entidad de entrada, tabla relacionada, clase de entidad de salida y nombres de campo de VOLUME, PAGE y LEASEID). Supuse que sus datos tienen una relación de muchos a muchos, donde muchas parcelas pueden tener el mismo VOLUMEN y PÁGINA y muchos LeaseID pueden tener el mismo VOLUMEN y PÁGINA, de esa manera funcionará incluso si se trata de una relación más simple entre dos fuentes de datos. La salida incluirá todas las características de Mineral Lease, incluidas aquellas que no tienen LeaseID coincidente de su tabla, y todas las características coincidentes se duplicarán para crear tantas características como sea necesario para mantener cada LeaseID asociado.

Supuse que deseaba generar todas las características de arrendamiento coincidentes en una sola clase de característica, pero si realmente deseaba crear clases de características separadas para cada conjunto de valores de Volumen y Página, entonces eso podría hacerse con algunas modificaciones menores de código, lo cual podría proveer. También podría modificar fácilmente el código para eliminar el conjunto de características de Mineral Lease que no tienen LeaseIDs coincidentes para que se creen si realmente no las desea.

Probé este código en mis propios datos usando una clase de entidad con más de 100,000 características y una tabla relacionada de muchos a muchos con más de 130,000 características y produjo casi 2,074,000 características que coincidían en los dos campos relacionados que usé. Solo tomó 12 minutos y 17 segundos crear tantas características (una tasa de aproximadamente 10,000 características cada 3 segundos). El uso de un iterador de ModelBuilder y consultas de selección repetidas habría llevado horas o días para hacer lo mismo. Mi código ni siquiera requiere que se indexen los campos relacionados involucrados (pero no se atreve a hacer su enfoque en ModelBuilder sin primero indexar los campos relacionados). Si los valores únicos de mis dos campos hubieran resultado en una relación Uno a Uno o Muchos a Uno entre las dos fuentes de datos, entonces el código habría terminado en aproximadamente 2 minutos.

Abra Python Idle desde su carpeta de programa de ArcGIS en el grupo Python 2.7, abra un archivo nuevo, pegue este código en el archivo nuevo y luego guarde el documento con el nombre que desee con la extensión .py. Luego, modifique las entradas y los nombres de los campos para que coincidan con sus datos y ejecute el código.

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): seconds_elapsed = (end_datetime - start_datetime) .total_seconds () return hms_string (seconds_elapsed) # End timedif start_time = datetime.datetime.now () print "Script start: {}". format (start_time) import arcpy from arcpy import env print "Importaciones cargadas. Tiempo transcurrido: {}". formato (timedif (datetime.datetime.now () , start_time)) # --- Variables que necesita personalizar para que coincidan con sus datos --- # Personalice la ruta del espacio de trabajo para que se ajuste a sus datos, por ejemplo, un espacio de trabajo de geodatabase = r "C:  Users  CRID  Documents  ArcGIS  YourGeodatabase.gdb "env.workspace = espacio de trabajo # Personalízalo para que coincida con el nombre de tu clase de entidad (se supone que está en el espacio de trabajo) inputFC =" MineralLeasesFC "inputFCFull = workspace + '' + inputFC print inputFCFull # Personalízalo para que coincida tabla de ID de arrendamiento (asume que está en el espacio de trabajo) relatedTable = "LeaseIDsTable" relatedTableFull = espacio de trabajo + '' + relatedTable print relatedTableFull # Personalice este para que sea el nombre de FC de salida que desee (asume la salida al espacio de trabajo) outputFC = "MineralLeasesWithIDs" outputFCFull = espacio de trabajo + '' + outputFC print outputFCFull # Personalízalo para que sea el nombre de los nombres de campo para VOLUME, PAGE y LEASEID inVolumeFld = "VOLUME" inPageFld = "PAGE" relatedVolumeFld = "VOLUME" relatedPageFld = "PAGE" leaseIDFld = "LEASEID" print "Variables cargadas. Tiempo transcurrido: {} ". Formato (timedif (datetime.datetime.now (), start_time)) # --- Código que no debería necesitar modificar --- # Compruebe si la salida ya existe y elimínela si lo hace si arcpy.Exists (outputFCFull): arcpy.Delete_management (outputFCFull, "FeatureClass") imprimir "Eliminado {}. Tiempo transcurrido: {} ". Formato (outputFC, timedif (datetime.datetime.now (), start_time)) # Crea la clase de entidad de salida basada en la entrada arcpy.CreateFeatureclass_management (workspace, outputFC," POLYGON ", inputFCFull," SAME_AS_TEMPLATE "," SAME_AS_TEMPLATE ", inputFCFull) imprimir" Creado {}. Tiempo transcurrido: {} ". Formato (outputFC, timedif (datetime.datetime.now (), start_time)) # obtenga la información del campo para el campo LeaseID y agréguela a los campos de salida = arcpy.ListFields (relatedTable) para el campo en campos: if field.name.upper () == leaseIDFld.upper (): fldType = field.type fldPrecision = field.precision fldScale = field.scale fldLength = field.length fldAliasName = field.aliasName # Agregar un campo para el LeaseID arcpy.AddField_management (outputFCFull, leaseIDFld, fldType, fldPrecision, fldScale, fldLength, fldAliasName) print "Agregado {} Field. Tiempo transcurrido: {} ". Formato (leaseIDFld, timedif (datetime.datetime.now (), start_time)) # Configure la lista de campos relatedTable relatedFieldsList = [relatedVolumeFld, relatedPageFld, leaseIDFld] # Cree un diccionario a partir de un da SearchCursor del tabla relacionada relatedDict = {} con arcpy.da.SearchCursor (relatedTableFull, relatedFieldsList) como searchRows: para searchRow en searchRows: keyValue = '{}; {}'. format (searchRow [0], searchRow [1]) si no es keyValue in relatedDict: relatedDict [keyValue] = [searchRow [2]] else: relatedDict [keyValue] .append (searchRow [2]) del searchRows, searchRow print "Cargado relatedDict de {}. Tiempo transcurrido: {} ". Formato (relatedTable, timedif (datetime.datetime.now (), start_time)) # Cree una lista de campos para los campos editables de entrada y salida inputFieldsList = [inVolumeFld, inPageFld] outputFieldsList = [] campos = arcpy.ListFields (inputFCFull) para campo en campos: if field.editable y field.type! = 'Geometry': inputFieldsList.append (field.name) outputFieldsList.append (field.name) elif field.type == 'Geometry ': inputFieldsList.append ("SHAPE @") outputFieldsList.append ("SHAPE @") outputFieldsList.append (leaseIDFld) print "Lista de campos creada para {}. Tiempo transcurrido: {} ". Formato (inputFC, timedif (datetime.datetime.now (), start_time)) # Construya un diccionario a partir de un da SearchCursor inputDict = {} con arcpy.da.SearchCursor (inputFCFull, inputFieldsList) como searchRows: para searchRow en searchRows: keyValue = '{}; {}'. formato (searchRow [0], searchRow [1]) si no es keyValue en inputDict: inputDict [keyValue] = [list (searchRow [2:])] else: inputDict [keyValue] .append (list (searchRow [2:])) del searchRows, searchRow print "Cargado inputDict desde {}. Tiempo transcurrido: {} ". Formato (inputFC, timedif (datetime.datetime.now (), start_time)) contador = 0 cursor = arcpy.da.InsertCursor (outputFCFull, outputFieldsList) para clave en inputDict: filas = inputDict [clave] if clave en relatedDict: para fila en filas: para arrendamiento en relatedDict [clave]: contador + = 1 si contador% 10000 == 0: print "Tiene un arrendamiento. Contador = {}. Tiempo transcurrido: {} ". Formato (contador, timedif (datetime.datetime.now (), start_time)) relatedRow = lista (fila) relatedRow.append (arrendamiento) cursor.insertRow (relatedRow) else: para fila en filas: contador + = 1 si el contador% 10000 == 0: print "No tiene arrendamiento. Contador = {}. Tiempo transcurrido: {} ". Formato (contador, timedif (datetime.datetime.now (), start_time)) row.append (None) cursor.insertRow (row) del cursor, inputDict, relatedDict print" Inserted {} Registros. Tiempo transcurrido: {} ". Formato (contador, timedif (datetime.datetime.now (), start_time)) imprimir" Script terminado: {} ". Formato (datetime.datetime.now ())

Ver el vídeo: Iteradores en ArcGIS: automatizar procesos con Modelbuilder