¿Cómo mejorar el rendimiento al usar cursores ArcGIS en Python con tablas grandes?

10

Tengo una clase de entidad de punto bastante grande en una geodatabase de archivos (~ 4 000 000 de registros). Esta es una cuadrícula regular de puntos con una resolución de 100 m.

Necesito realizar una especie de generalización en esta capa. Para esto, creo una nueva cuadrícula donde cada punto se encuentra en el medio de 4 puntos "antiguos":

 *     *     *     *
    o     o     o
 *     *     *     *
    o     o     o
 *     *     *     *

[*] = punto de la cuadrícula original - [o] = punto de la nueva cuadrícula

El valor del atributo de cada nuevo punto se calcula en función de los valores ponderados de sus 4 vecinos en la cuadrícula anterior. Por lo tanto, hago un bucle en todos los puntos de mi nueva cuadrícula y, para cada uno de ellos, hago un bucle en todos los puntos de mi antigua cuadrícula, para encontrar los vecinos (comparando los valores de X e Y en la tabla de atributos). Una vez que se han encontrado 4 vecinos, nos salimos del círculo.

No hay complejidad metodológica aquí, pero mi problema es que, en base a mis primeras pruebas, este script durará semanas para completarse ...

¿Ves alguna posibilidad de hacerlo más eficiente? Algunas ideas en la parte superior de mi cabeza:

  • Indice los campos X e Y => Lo hice pero no noté ningún cambio significativo en el rendimiento
  • Haga una consulta espacial para encontrar los vecinos en lugar de una basada en atributos. ¿Eso realmente ayudaría? ¿Qué función espacial en ArcGIS debería hacer el trabajo? Dudo que, por ejemplo, amortiguar cada nuevo punto resulte más eficiente
  • Transforme la clase de entidad en una matriz NumPy. ¿Eso ayudaría? No he trabajado mucho con NumPy hasta ahora y no me gustaría sumergirme en él a menos que alguien me diga que realmente podría ayudar a reducir el tiempo de procesamiento
  • ¿Algo más?
Stéphane Henriod
fuente
¿Qué versión de Arcmap estás usando?
Martin
¿Has considerado PostGIS? ¿Es esa una opción?
Chad Cooper
Lamento
haberlo
No, por desgracia, PostGIS no es una opción, desafortunadamente mis manos están bastante atadas aquí ... En el mejor de los casos, puedo usar Oracle con las funciones SDE
Stéphane Henriod

Respuestas:

13

¿Qué pasa si alimentaste los puntos en una matriz numpy y usaste un árbol de cKDTree para buscar vecinos? Proceso nubes de puntos LiDAR con grandes cantidades de puntos (> 20 millones) en varios MINUTOS usando esta técnica. Hay documentación aquí para kdtree y aquí para la conversión numpy. Básicamente, lee las x, y en una matriz e itera sobre cada punto de la matriz para encontrar índices de puntos dentro de una cierta distancia (vecindad) de cada punto. Puede usar estos índices para luego calcular otros atributos.

Barbarroja
fuente
esta respuesta es mejor que la mía
radouxju
Me gusta esta idea, pero no tengo scipy en la estación de trabajo en la que estoy trabajando (y no tengo derechos de administrador). Si logro instalar este paquete, lo intentaré
Stéphane Henriod
4

Estoy con Barbarroja ... los cursores arcpy son increíblemente aburridos, así que solo los uso para atravesar una tabla o clase de entidad exactamente una vez. Si no puedo hacer el trabajo en un ciclo, uso el cursor para llenar otro tipo de estructura de datos y trabajar con eso.

Si no desea molestarse con numpy, simplemente haga un diccionario de python simple donde use sus coordenadas como una simple clave de texto y complete los atributos que necesita para el cálculo en una lista como el valor del elemento del diccionario.

En un segundo paso, puede obtener fácilmente los valores que necesita para calcular un punto simplemente obteniéndolos de su diccionario (que es increíblemente rápido, debido a que el diccionario tiene un índice de elementos).

Jürgen Zornig
fuente
De hecho, me gusta tu idea con los diccionarios y la acabo de implementar. De hecho, funciona mucho mejor ... hasta que realmente escribo los resultados con una fila. InsertRow () ... ¿Alguna idea de cómo puedo mejorar esta parte también?
Stéphane Henriod
Tuve un problema similar en el que tuve que seleccionar unos 10.000 puntos de 14 millones. y luego bórralo. arcpy.cursors donde solo puede eliminar aproximadamente 1 o 2 puntos por segundo (!). así que instalé el módulo pyodbc para eliminarlos con una sola instrucción DELETE de SQL en solo un segundo. ACTUALIZAR sobre SQL le brindará muchas mejoras, siempre que solo desee modificar los atributos ... sin embargo, tendrá que instalar módulos adicionales de Python ... pero vale la pena.
Jürgen Zornig
2

Para una grilla regular, debería ser mucho más eficiente trabajar en un formato ráster. Convierta su primera cuadrícula en un ráster, puede volver a muestrear a la misma resolución utilizando un interpolador bilineal pero cambiando su imagen de salida en 1/2 píxel en X e Y, y de nuevo a los puntos si aún necesita tener puntos.

EDITAR: para reglas de decisiones complejas, puede convertir cada uno de los campos que necesita como una nueva banda ráster, luego hace cuatro copias de esas bandas y cambia su ráster en las 4 direcciones en 1/2 píxel (+50, - 50), (+ 50, + 50), (-50, -50) y (-50, + 50). Entonces puedes usar álgebra de mapas regular

radouxju
fuente
Gracias. He pensado realmente en esta solución, pero no estoy seguro de si puedo implementar el cálculo del nuevo valor si está en formato ráster. Permítanme explicar: para cada nuevo punto (o nueva celda de trama) necesito calcular su valor como tal: tomo el valor de cada uno de sus vecinos. Cada uno de esos valores tiene una probabilidad de dar un valor particular al nuevo punto. Por ejemplo, si un vecino tiene el valor 202, le dará el valor 3 (con un peso de 1) o el valor 11 (con un peso de 5). Luego
sumamos
PD: el cálculo para encontrar el nuevo valor puede, en algunos casos, basarse en 2 atributos, no solo en uno, lo que podría descartar el enfoque Raster
Stéphane Henriod
para su suma ponderada, solo necesita dos rásteres: uno donde remuestrea el producto de los pesos y los valores, el segundo donde solo remuestrea los pesos. Si divide el primero por el segundo, obtiene su suma ponderada.
radouxju
1
@ StéphaneHenriod: como sugerencia, puede considerar editar la pregunta para agregar estas especificaciones adicionales. Dada la pregunta inicial, creo que esta respuesta tiene mucho sentido, pero con esta nueva información, la respuesta de Barbarroja se ve bien.
nicksan
2

Gracias a todos por su ayuda!

Finalmente encontré una forma muy no pitónica de resolver este problema ... Lo que en realidad tomaba más tiempo de computación era encontrar los 4 vecinos de cada punto. En lugar de usar los atributos X e Y (ya sea con un cursor arcpy o dentro de otra estructura de datos, como un python ditionary), terminé usando la herramienta ArcGIS Generar tabla cercana . Supongo que esto aprovecha los índices espaciales y los rendimientos son obviamente mucho más altos, sin que yo tenga que implementar el índice yo mismo.

Stéphane Henriod
fuente
0

El problema con los cursores es que puedes recorrerlos de una sola manera y no puedes retroceder. Aunque no se recomienda, puede completar las características en una estructura si planea volver a visitarlas.

Si pudo procesar sus funciones en un solo ciclo, le sugiero que habilite el reciclaje. Es un parámetro en la función de clase de función de búsqueda que permite a Python reutilizar la memoria asignada por las funciones antiguas y hacer que recorrer las funciones en un cursor sea mucho más rápido. Puede procesar su cuadrícula un 80% más rápido.

El problema es que no puede habilitar el reciclaje si planea almacenar características recuperadas de un cursor.

hnasr
fuente
Quiero explorar este tema del "cursor de reciclaje" pero no puedo encontrar ninguna documentación en la Ayuda de ESRI. ¿Tienes un enlace? El cursor de búsqueda no tiene un parámetro de reciclaje. Select_by_Attribute no tiene dicho parámetro. No veo nada en ENV.
klewis
Escribí un artículo hace un tiempo husseinnasser.com/2009/08/when-to-use-recycling-cursor.html?m=1
hnasr
1
No creo que "reutilizar cursores" esté disponible a través de ArcPy, solo con los Corebjects centrales.
klewis