Usando arcgis desktop 10.3.1 Tengo un script que usa un cursor de búsqueda para agregar valores a una lista y luego uso min () para encontrar el entero más pequeño. La variable se usa luego en un script. La clase de entidad tiene 200,000 filas y el script tarda mucho tiempo en completarse. ¿Hay alguna manera de hacer esto más rápido? Por el momento, creo que lo haría a mano en lugar de escribir un guión debido al tiempo que lleva.
import arcpy
fc = arcpy.env.workspace = arcpy.GetParameterAsText(0)
Xfield = "XKoordInt"
cursor = arcpy.SearchCursor(fc)
ListVal = []
for row in cursor:
ListVal.append(row.getValue(Xfield))
value = min(ListVal)-20
print value
expression = "(!XKoordInt!-{0})/20".format(value)
arcpy.CalculateField_management (fc, "Matrix_Z" ,expression, "PYTHON")
arcpy.Statistics_analysis
? desktop.arcgis.com/en/arcmap/10.3/tools/analysis-toolbox/…min_val = min([i[0] for i in arcpy.da.SearchCursor(fc,Xfield)])
Respuestas:
Puedo ver varias cosas que pueden estar causando que su script sea lento. Lo que probablemente sea muy lento es la
arcpy.CalculateField_management()
función. Debe usar un cursor, lo hará varias magnitudes más rápido. Además, dijo que está utilizando ArcGIS Desktop 10.3.1, pero está utilizando los antiguos cursores de estilo ArcGIS 10.0, que también son mucho más lentos.La operación min () incluso en una lista de 200K será bastante rápida. Puede verificar esto ejecutando este pequeño fragmento; sucede en un abrir y cerrar de ojos:
Vea si esto es más rápido:
EDITAR:
Realicé algunas pruebas de tiempo y, como sospechaba, la calculadora de campo tardó casi el doble de tiempo que el nuevo cursor de estilo. Curiosamente, el cursor de estilo antiguo era ~ 3 veces más lento que la calculadora de campo. Creé 200,000 puntos aleatorios y usé los mismos nombres de campo.
Se usó una función de decorador para cronometrar cada función (puede haber un poco de sobrecarga en la configuración y desmantelamiento de las funciones, por lo que tal vez el módulo timeit sería un poco más preciso para probar fragmentos).
Aquí están los resultados:
Y aquí está el código que usé (desglosé todo en funciones individuales para usar el
timeit
decorador):Y finalmente, esta es la impresión real de mi consola.
Edición 2: Acabo de publicar algunas pruebas actualizadas, encontré un pequeño defecto con mi
timeit
función.fuente
"XKoordInt"
. Vea mi edición, todo lo que tiene que hacer es omitir los valores nulos.range
. ArcGIS todavía usa Python 2.7, por lo que devuelve alist
. Pero en 3.x,range
es su propio tipo especial de objeto que puede tener optimizaciones. Sería una prueba más confiablemin(list(range(200000)))
, que aseguraría que está trabajando con una lista simple. También considere usar eltimeit
módulo para pruebas de rendimiento.Como señala @crmackey, la parte lenta probablemente se deba al método de cálculo del campo. Como alternativa a las otras soluciones adecuadas, y suponiendo que esté utilizando una geodatabase para almacenar sus datos, puede usar el comando Ordenar por sql para ordenar en orden ascendente antes de hacer el cursor de actualización.
En este caso, la cláusula where elimina los valores nulos antes de realizar la consulta, o puede usar el otro ejemplo que verifica Ninguno antes de actualizar.
fuente
min()
. Incluiré esto en mis pruebas de velocidad también para mostrar la ganancia de rendimiento.0.56
segundos, lo que no es una ganancia de rendimiento tan grande como esperaba.También puede usar numpy en casos como este, aunque requerirá más memoria.
Todavía obtendrá un cuello de botella cuando cargue los datos en una matriz numpy y luego vuelva a la fuente de datos nuevamente, pero descubrí que la diferencia de rendimiento es mejor (a favor de numpy) con fuentes de datos más grandes, especialmente si necesita múltiples estadísticas / cálculos .:
fuente
¿Por qué no ordenar la tabla de forma ascendente y luego usar un cursor de búsqueda para obtener el valor de la primera fila? http://pro.arcgis.com/en/pro-app/tool-reference/data-management/sort.htm
fuente
Lo envolvería
SearchCursor
en una expresión generadora (es decirmin()
) para la velocidad y la concisión. Luego incorpore el valor mínimo de la expresión del generador en unda
tipoUpdateCursor
. Algo como lo siguiente:fuente
SearchCursor
debería cerrarse cuando hayas terminado?En su bucle, tiene dos referencias de función que se vuelven a evaluar para cada iteración.
for row in cursor: ListVal.append(row.getValue(Xfield))
Debería ser más rápido (pero un poco más complejo) tener las referencias fuera del ciclo:
fuente
append()
método integrado dellist
tipo de datos. No creo que sea aquí donde está ocurriendo su cuello de botella, apostaría dinero, la función de campo de cálculo es la culpable. Esto se puede verificar cronometrando la calculadora de campo frente a un nuevo cursor de estilo.