Loading [MathJax]/extensions/TeX/mathchoice.js

4 votos

problema de rendimiento con PyQGIS: manipulación de atributos

He seleccionado una capa vectorial con atributos pendiente y área. Quiero combinar todas las características con pendiente 0 a 5, 5 a 10, ... , 85 a 90. Las características originales deben ser descartadas, y se deben crear nuevas características para cada categoría de pendiente (que consiste en la geometría combinada, y el atributo de área combinada).

Soy bastante nuevo en la programación en python, y aunque el script que he creado a continuación parece hacer lo que espero (?), tiene problemas de rendimiento. Comienza razonablemente rápido, pero luego se ralentiza a una velocidad dolorosamente lenta.

Me pregunto cuál es la razón de este comportamiento, y qué podría hacer mejor (y por qué).

import math
layer = iface.activeLayer()
for slope_cat_nr in range(1, 19):
    print "Slope Category: ", slope_cat_nr*5
    slope_max = 5*slope_cat_nr
    slope_min = slope_max - 5
    if slope_min == 0:
        slope_min = -0.001
    newGeom = QgsGeometry.fromWkt('GEOMETRYCOLLECTION()')
    anzF = layer.featureCount()
    onePercentAnz = math.ceil(anzF / 100)
    print "Nr. of Features: ", anzF
    progress = 0
    fIds = []
    for f in layer.getFeatures():
        if (progress % onePercentAnz) == 0:
            print (100*progress / anzF),
        progress += 1
        if f['slope'] > slope_min and f['slope'] <= slope_max:
            newGeom = newGeom.combine(f.geometry())
            fIds.append(f.id())
    newFeature = QgsFeature(layer.pendingFields())
    newFeature.setAttribute('slope', slope_max)
    newFeature.setAttribute('area', newGeom.area())
    print "New Area: ", newGeom.area()
    newFeature.setGeometry(newGeom);
    layer.dataProvider().addFeatures([newFeature])
    layer.dataProvider().deleteFeatures(fIds)

2voto

Mat Puntos 196

El código se ve bien, pero espero que el rendimiento empeore con el tiempo.

Cada vez que se pasa por el bucle interno, se combina la geometría de la característica actual con la unión de todas las geometrías de las características anteriores que coinciden.

Al principio tendrás una geometría simple. Cada vez que se da una vuelta al bucle, la geometría se vuelve más compleja, por lo que cada vez que se da una vuelta al bucle se tarda un poco más.

El tiempo que tarda en ejecutarse combine() dependerá de la complejidad de la geometría, por lo que el bucle se ralentizará con el tiempo.

+1 a la sugerencia de ArMoraer de usar Shapely/Fiona. Te sugiero que mires unión en cascada y ver si eso es más rápido.. no lo he probado yo, pero hay un ejemplo de código en esta respuesta que puedes probar

2voto

hyty Puntos 91

Se inicia newGeom como GEOMETRYCOLLECTION, pero en el bucle se combinan las geometrías. combine es la operación de unión geométrica y, como tal, tiene un trabajo mucho mayor que simplemente añadir una geometría a una colección. Debe comprobar la relación topológica en un nivel bajo, y si los objetos son disjuntos los agrega a geometrías MultiPolygon.

Si interpreto bien tu código, lo que quieres hacer es agregar geometrías a las colecciones. Esto es lo que addPartGeometry() lo hace. Agrega objetos a GeometryCollection de Polygon.

Como no tengo a mano un conjunto de datos útil para comprobar el rendimiento, le sugiero que sustituya

newGeom = newGeom.combine(f.geometry())

con

newGeom.addPartGeometry(f.geometry())

y comparar el tiempo de ejecución.

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