¿Resumiendo valores de polígonos vecinos usando QGIS?

11

Espero que me puedan ayudar con el siguiente problema: tengo una capa vectorial (polígono). Me gustaría agregar 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 hacer esto a mano para todos y cada uno de los distritos.

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

Alex
fuente

Respuestas:

8

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

Primero, deberá cargar sus datos en una base de datos de Spatialite, lo que puede hacer utilizando el complemento DBManager que se incluye con QGIS. Haz clic en Importar Layer/File button.

Con sus datos en una base de datos, puede ejecutar la siguiente consulta con el SQLbotón. Solo tendrá que cambiar los nombres de las columnas y tablas para adaptarlas 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), luego haga clic en cargar.

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

ingrese la descripción de la imagen aquí

El desglose de consultas

Estamos uniendo la capa sobre sí misma usando:

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

pero solo donde las geometrías se cruzan y los identificadores no son iguales, de lo contrario terminamos con el mismo registro dos veces para cada polígono. También estamos utilizando a LEFT OUTER JOINpara incluir los registros que no se unen, es decir, no tienen vecinos.

En la parte seleccionada:

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

estamos usando COALESCEpara convertir el NULLS(sin vecinos) en uno de lo 0contrario simplemente se quedan NULL.

Luego solo GROUP BY a1.idpara que obtengamos un solo registro para cada polígono.

Nathan W
fuente
Nathan, muchas gracias por tu respuesta y explicaciones útiles. ¡Funcionó incluso para un principiante espacial y sql total!
Alex
+1 La sección "desglose de consultas" está bien hecha y es muy útil.
whuber
@Alex buenas cosas. No olvides marcar el botón aceptar.
Nathan W
2

Otra forma de hacerlo es en GRASS (usando la caja de herramientas de GRASS o directamente en GRASS). En el siguiente ejemplo, 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. Vea esta publicación para una explicación más detallada.

Paso 1) Cree una nueva capa con una tabla de atributos vinculada a los límites, con dos columnas con ID de polígonos que bordean la línea de límite 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) Ejecute un SQL para crear una tabla que vincule los ID de país 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 ahora debería tener una columna adicional con la población sumada de todos los países vecinos.

Ecodiv
fuente
2

Gran respuesta de @Nathan . Intenté hacer esto usando pyqgis y bien proporcionado. Echa un vistazo a esta publicación para descargar el scirpt y ejecutarlo en QGIS. Una ventaja de este método sería que obtiene los resultados como parte de la tabla de atributos.

ingrese la descripción de la imagen aquí

pensamientos espaciales
fuente