Résumer les valeurs des polygones voisins à l'aide de QGIS?

11

J'espère que vous pourrez m'aider avec le problème suivant: J'ai une couche vectorielle (polygone). Je voudrais ajouter un attribut à la couche qui - pour chaque polygone - additionne les valeurs d'un champ spécifique de tous ses polygones voisins.

Pour donner un exemple plus concret: j'ai une couche polygonale de districts contenant des informations sur la population. Maintenant, pour chaque district, je voudrais savoir combien de personnes vivent dans tous les districts voisins.

Comme j'ai plus de 300 districts, je ne peux pas le faire à la main pour chaque district.

Existe-t-il un moyen de le faire plus efficacement dans QGIS?

Alex
la source

Réponses:

8

Ce genre de chose est mieux fait avec Spatialite et SQL.

Vous devez d'abord charger vos données dans une base de données Spatialite, ce qui peut être fait à l'aide du plug-in DBManager fourni avec QGIS. Cliquez sur Importer Layer/File button.

Avec vos données dans une base de données, vous pouvez ensuite exécuter la requête suivante à l'aide du SQLbouton. Il vous suffira de modifier les noms des colonnes et des tableaux en fonction de vos données.

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

Indiquez à l'outil de requête votre colonne d'identifiant unique (id) et votre colonne de géométrie (geomm), puis cliquez simplement sur charger.

Vous devriez avoir quelque chose comme ça, une fois que vous l'avez étiqueté bien sûr

entrez la description de l'image ici

La répartition des requêtes

Nous joignons la couche sur elle-même en utilisant:

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

mais seulement là où les géométries se croisent et les identifiants ne sont pas les mêmes, sinon on se retrouve avec le même enregistrement deux fois pour chaque polygone. Nous utilisons également un LEFT OUTER JOINafin d'inclure les enregistrements qui ne se joignent pas, c'est-à-dire qui n'ont pas de voisins.

Dans la partie sélectionnée:

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

nous utilisons COALESCEpour convertir le NULLS(pas de voisins) en 0sinon ils restent juste NULL.

Ensuite, nous avons juste GROUP BY a1.idpour que nous obtenions un seul enregistrement pour chaque polygone.

Nathan W
la source
Nathan, merci beaucoup pour votre réponse et vos explications utiles. Cela a fonctionné même pour un débutant en spatialite et sql total!
Alex
+1 La section "ventilation des requêtes" est joliment réalisée et très utile.
whuber
@Alex bonnes choses. N'oubliez pas de cocher le bouton Accepter.
Nathan W
2

Une autre façon de le faire est dans GRASS (en utilisant la boîte à outils GRASS ou directement dans GRASS). Dans l'exemple ci-dessous, la couche EA est une couche vectorielle avec des pays et dans le tableau des attributs une colonne avec la population par pays. Voir cet article pour une explication plus détaillée.

Étape 1) Créez une nouvelle couche avec une table d'attributs liée aux limites, avec deux colonnes avec des ID de polygones bordant respectivement la ligne de délimitation à gauche et à droite

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

Étape 2) Exécutez un SQL pour créer une table qui relie les ID de pays à la somme de la population de tous les pays voisins:

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"

Étape 3) Joignez la nouvelle table tmp à la table d'attributs d'origine.

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

La table attributaire de votre couche vectorielle devrait maintenant avoir une colonne supplémentaire avec la population sommée de tous les pays voisins.

Ecodiv
la source
2

Grande réponse de @Nathan . J'ai essayé de le faire en utilisant pyqgis et galbé. Consultez cet article pour télécharger le scirpt et l'exécuter dans QGIS. Un avantage de cette méthode est que vous obtenez les résultats dans le cadre de la table attributaire.

entrez la description de l'image ici

pensées spatiales
la source