11 votos

¿Sumar los valores de los polígonos vecinos utilizando QGIS?

Espero que me puedan ayudar con el siguiente problema: Tengo una capa vectorial (polígono). Me gustaría añadir un atributo a la capa que -para cada polígono- sume los valores de un campo específico de todos sus polígonos vecinos.

Para dar un ejemplo más concreto: Tengo una capa poligonal de distritos que contiene información sobre la población. Ahora, para cada distrito me gustaría saber cuántas personas viven en todos sus distritos vecinos.

Como tengo más de 300 distritos no puedo hacerlo a mano para todos y cada uno de ellos.

¿Hay alguna manera de hacer esto de manera más eficiente en QGIS?

8voto

Jauder Ho Puntos 3172

Este tipo de cosas se hacen mejor con Spatialite y SQL.

Primero tendrá que cargar sus datos en una base de datos de Spatialite, lo que puede hacerse utilizando el plugin DBManager que viene con QGIS. Haga clic en el botón Importar Layer/File button .

Con sus datos en una base de datos, puede ejecutar la siguiente consulta utilizando la función SQL botón. Sólo tendrá que cambiar los nombres de las columnas y las tablas para adaptarlos a sus datos.

SELECT COALESCE(SUM(a2.pop),0) as pop_neighbours, 
        a1.pop, 
        a1.name, 
        a1.id, 
        a1.geomm FROM areas a1
LEFT OUTER JOIN areas a2 ON NOT a1.id = a2.id 
                            AND intersects(a2.geomm, a1.geomm)
GROUP BY a1.id

Indique a la herramienta de consulta su columna de identificación única (id) y la columna de geometría (geomm), y luego simplemente haga clic en cargar.

Deberías tener algo así, una vez que lo etiquetes por supuesto

enter image description here

El desglose de la consulta

Vamos a unir la capa sobre sí misma utilizando:

LEFT OUTER JOIN areas a2 ON NOT a1.id = a2.id 
                            AND intersects(a2.geomm, a1.geomm)

pero sólo cuando las geometrías se cruzan y los ids no son los mismos, de lo contrario terminamos con el mismo registro dos veces para cada polígono. También utilizamos un LEFT OUTER JOIN para que incluyamos los registros que no se unen, es decir, que no tienen vecinos.

En la parte de selección:

SELECT COALESCE(SUM(a2.pop),0) as pop_neighbours, 
            a1.pop, 
            a1.name, 
            a1.id, 
            a1.geomm

estamos usando COALESCE para convertir el NULLS (sin vecinos) en un 0 si no, se quedan NULL .

Entonces sólo GROUP BY a1.id para que obtengamos un único registro para cada polígono.

0 votos

Nathan, muchas gracias por tu respuesta y tus útiles explicaciones. ¡Funcionó incluso para un principiante total de spatialite y sql!

0 votos

+1 La sección "desglose de la consulta" está bien hecha y es muy útil.

0 votos

@Alex buen material. No te olvides de marcar el botón de aceptar.

2voto

Raoul Puntos 1113

Gran respuesta de @Nathan . Intenté hacer esto usando pyqgis y shapely. Verifique este puesto para descargar el scirpt y ejecutarlo en QGIS. Una ventaja de este método sería que se obtienen los resultados como parte de la tabla de atributos.

enter image description here

2voto

paulr Puntos 1900

Otra forma de hacerlo es en GRASS (usando la caja de herramientas de GRASS o directamente en GRASS). En el ejemplo siguiente, la capa EA es una capa vectorial con países y en la tabla de atributos una columna con la población por país. Ver este puesto para una explicación más detallada.

Paso 1) Crear una nueva capa con una tabla de atributos vinculada a los límites, con dos columnas con los ID de los polígonos que bordean la línea de los límites a la izquierda y a la derecha respectivamente

v.category EA out=EAc layer=2 type=boundary option=add
v.db.addtable EAc layer=2 col="left integer,right integer"
v.to.db EAc option=sides col=left,right layer=2 type=boundary

Paso 2) Ejecutar un SQL para crear una tabla que relacione los ID de los países con la suma de la población de todos los países vecinos:

db.execute sql="CREATE TABLE tmp AS
SELECT ID, sum(pop) as population FROM (
SELECT DISTINCT EAc_2.left as ID, EAc.pop as pop
FROM EAc_2
LEFT JOIN EAc ON EAc_2.right = EAc.cat
WHERE EAc_2.left > -1 AND EAc_2.right > -1
UNION
SELECT DISTINCT EAc_2.right as ID, EAc.pop as pop
FROM EAc_2
LEFT JOIN EAc ON EAc_2.left = EAc.cat
WHERE EAc_2.left > -1 AND EAc_2.right > -1
) GROUP BY ID"

Paso 3) Unir la nueva tabla tmp con la tabla de atributos original.

v.db.join map=EA@ConsStat layer=1 column=cat otable=tmp ocolumn=ID

La tabla de atributos de su capa vectorial debería tener ahora una columna adicional con la suma de la población de todos los países vecinos.

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