Un cliente mi contatta per un problema GIS e mi chiede di risolverlo usando solo QGIS e vuole pure spiegato, passo passo, come farlo.
È un classico problema di relazione 1:m e determinazione di valori massimi (da un layer2) da associare al layer1 (vedi descrizione quesito, sotto).
Il vero problema da risolvere è l’ottimizzazione, in quanto i due layer hanno centinaia di migliaia di record, quindi è importate scegliere lo strumento o la strategia migliore per non stare ore a vedere la clessidra che gira.
La risoluzione del problema non è difficile e ci sono molti modi per farlo, ma il cliente aveva fretta, fretta che ha trasmesso anche a me e quindi ho subito optato per usare le espressioni di QGIS (alla luce della sua richiesta), ecco i passi:
- creo relazione (1:m) di progetto in QGIS;
- utilizzo una espressione (complessa) per calcolare i valori massimi di insiemi di record;
ma questa soluzione si rileva subito molto lenta, in quanto entrano in gioco, oltre alla relazione di progetto, anche funzioni di aggregazioni e array; dopo 20 minuti, QGIS aveva processato solo il 15 % dei dati.
Nel frattempo, decido di caricare i due layer in un database SpatiaLite, costruisco una query e in meno di un secondo ho l’output, PAZZESCO!!!
Il cliente non è contento della soluzione con SQL perché desidera una soluzione usando solo QGIS, allora nasce l’esigenza di studiare meglio i dati e ottimizzare i processi: decido di dividere, l’unico processo creato nel primo tentativo con l’espressione, in sotto processi e questo risolve il problema, e in circa 4 minuti sono riuscito a risolvere il problema usando solo QGIS, e il cliente è contento.
DESCRIZIONE QUESITO
Due layer, uno poligonale e uno puntuale.
I due layer hanno un attributo che li lega in una relazione 1:m; ovvero, ogni poligono ha associato, tramite attributo, enne punti; ogni punto contiene due campi con valori numerici.
Il problema da risolvere è il seguente: aggiungere, al layer poligonale, i valori massimi dei due campi presenti nel layer puntuale che corrispondono nella relazione 1:m. (ovvero, ogni poligono ha associati enne punti, associare al poligono il valore massimo di alcuni attributi del layer puntuale)


SOLUZIONI TESTATE
- Tramite espressioni di QGIS, tipo questa di sotto:
array_max(
relation_aggregate(
relation:='rel',
aggregate:='array_agg',
expression:="nomeAttributo"))
Ma processo estremamente lento.
- Soluzione tramite SpatiaLite e query:
SELECT e.progr, max(f.campo1) AS campo1_max, max(f.campo2) AS campo2_max
FROM "edificato" e join "punti" f ON field1layer1=field2layer2
group by 1
output in meno di un secondo!!!
- Soluzione separando i processi in QGIS
Ovvero, aggrego e trovo massimo degli attributi usando solo il layer figlio, il processo è molto più veloce:

successivamente basta fare una semplice JOIN tabellare e quindi evitare di lavorare con la relazione 1:m!!!
- Soluzione usando il Plugin Group Stats
Il plugin permette di trovare, a partire da un layer, le statistiche di base, quindi valore max, min ecc…; ma lo fa per singolo campo, quindi occorre ripeterlo, per il caso in esame, due volte e poi unire i due risultati ed infine fare la join tabellare.
NOTE FINALI: Le espressioni di QGIS sono molto potenti e risolvono molti problemi, ma se il numero di record sono molti (oltre 300k record), usassimo funzioni di aggregazione e array, e nel mezzo mettessimo anche una relazione di progetto, i tempi di elaborazioni tendono a infinito, quindi è consigliabile scindere il quesito in più step e poi ricomporre il tutto.
Oppure, l’approccio migliore in questi casi è usare database relazionali e una query ben studiata!!!
RIFERIMENTI
- QGIS : https://www.qgis.org/it/site/
- SpatiaLite : https://www.gaia-gis.it/fossil/libspatialite/index
- Espressioni di QGIS : https://hfcqgis.opendatasicilia.it/
- Plugin Group Stats : https://plugins.qgis.org/plugins/GroupStats/
I MIEI CANALI – ISCRIVITI
- Telegram : https://t.me/pigrecoinfinito
- YouTube : https://www.youtube.com/c/TotòFiandaca
Se il blog post Ti è piaciuto cliccate su ‘Mi piace’, grazie!!!
if you liked the blog post click on ‘Like’, thank you !!!