Riassumendo i valori dei poligoni vicini usando QGIS?


11

Spero che tu mi possa aiutare con il seguente problema: ho un livello vettoriale (poligono). Vorrei aggiungere un attributo al livello che - per ogni poligono - somma i valori di un campo specifico di tutti i suoi poligoni vicini.

Per fare un esempio più concreto: ho uno strato poligonale di distretti contenente informazioni sulla popolazione. Ora, per ogni distretto vorrei sapere quante persone vivono in tutti i suoi distretti vicini.

Dato che ho più di 300 distretti, non posso farlo a mano per ogni distretto.

Esiste un modo per farlo in modo più efficiente in QGIS?

Risposte:


8

Questo tipo di cose è fatto meglio con Spatialite e SQL.

Per prima cosa dovrai caricare i tuoi dati in un database Spatialite che può essere eseguito utilizzando il plug-in DBManager fornito con QGIS. Fai clic su Importa Layer/File button.

Con i tuoi dati in un database puoi quindi eseguire la seguente query usando il SQLpulsante. Dovrai solo cambiare i nomi delle colonne e delle tabelle in base ai tuoi dati.

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

Indica allo strumento di query la tua colonna ID id (id) e colonna geometrica (geomm), quindi fai clic su Carica.

Dovresti avere qualcosa del genere, una volta etichettato, ovviamente

inserisci qui la descrizione dell'immagine

La suddivisione della query

Stiamo unendo il livello su se stesso usando:

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

ma solo dove le geometrie si intersecano e gli ID non sono gli stessi, altrimenti finiamo con lo stesso record due volte per ogni poligono. Stiamo anche usando un LEFT OUTER JOINmodo da includere i record che non si uniscono, cioè che non hanno vicini.

Nella parte selezionata:

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

stiamo usando COALESCEper convertire il NULLS(nessun vicino) in un 0altrimenti rimarranno NULL.

Quindi abbiamo solo GROUP BY a1.idper ottenere un singolo record per ogni poligono.


Nathan, molte grazie per la tua risposta e utili spiegazioni. Ha funzionato anche per una spatialite totale e un principiante sql!
Alex,

+1 La sezione "scomposizione delle query" è ben fatta e molto utile.
whuber

@Alex roba buona. Non dimenticare di selezionare il pulsante Accetta.
Nathan W,

2

Un altro modo per farlo è in GRASS (usando la toolbox GRASS o direttamente in GRASS). Nell'esempio seguente, il livello EA è un livello vettoriale con paesi e nella tabella degli attributi una colonna con la popolazione per paese. Vedi questo post per una spiegazione più dettagliata.

Passaggio 1) Crea un nuovo livello con la tabella degli attributi collegata ai confini, con due colonne con ID dei poligoni che delimitano la linea di confine rispettivamente a sinistra e a destra

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

Passaggio 2) Eseguire un codice SQL per creare una tabella che colleghi gli ID paese con la somma della popolazione di tutti i paesi vicini:

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"

Passaggio 3) Unisciti alla nuova tabella tmp con la tabella degli attributi originale.

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

La tabella degli attributi del tuo livello vettoriale dovrebbe ora avere una colonna aggiuntiva con popolazione sommata di tutti i paesi vicini.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.