Denna väldigt användbara funktion är inte speciellt enkel att förstå sig på. När man tittar i den officiella dokumentationen så finns där mycket av den information man behöver, men det är lite svårt att förstå hur man skall använda funktionen.
Kortfattat förstår jag funktionen som att man ”kliver ur” uttrycket och går till ett annat lager med geometrier och attribut där.
Uttryck görs ju datadefinierat en gång för varje objekt i ett lager (normalt). Aggregate funktionen körs mot varje sådant objekt och kan från aggregate-funktionen refereras till som @parent.
Funktionen har tre obligatoriska parametrar.
- Lager – en textsträng som refererar till ett lager med namn.
- Aggregering – hur skall data aggregeras?
- Uttryck – skapar den aggregering som efterfrågas.
Aggregering och uttryck är två sidor av samma mynt och det är kombinationen av dessa som avgör resultatet. Om man exempelvis vill ”summera” värden så skall uttrycket innehålla ett fältnamn i det aggregerade lagret.
Många av aggregeringarna är kopplade till attribut i lagret. Antal, högsta och lägsta värde, medel, standardavvikelse, min-max, etc. Det finns även textaggregeringar som slår samman texter som löpande text, eller som värden i en lista (array). Det finns även aggregeringar som samlar geometrier i lagret.
Utöver dessa tre obligatoriska parametrar så finns det ett antal valfria också. Dessa klär på funktionalitet med uttrycket och gör det riktigt kraftfullt i många sammanhang.
- Filter – ett uttryck som begränsar vilka objekt i aggregeringslagret som skall ingå i aggregeringen.
- Concatenator – om man använder ”concatenator” som aggregering så kan man här ange en textsträng som aggregeringssymbol.
- Order by – ange en sorteringsordning för dessa aggregerade data.
Filter är det som gör aggregate() till en riktigt kraftfull funktion. Här kan man ställa villkor för aggregeringen, exempelvis kopplat mot värden i attributen, eller geometrin i ”@parent” objektet.
Ett exempel:
Här har jag ett lager med kommuner (ak_riks) som polygoner, och ett tillfälligt punktlager utan attribut. Nu vill jag att det för varje punkt skall skrivas ut vilken kommun de ligger i.
Uttrycket för etiketterna består av en enda aggregate() funktion.
aggregate( 'ak_riks', -- aggregerat lagernamn 'max', -- aggregeringsfunktion "KOMMUNNAMN", -- fältnamn som skall aggregeras intersects( -- hämta namn från polygon som överlappar @parent punkten $geometri, -- kommunpolygon geometri(@parent) -- punkt i det tillfälliga lagret ) )
Filtret med intersects() strulade lite för mig, tills jag såg till att mitt punktlager hade samma koordinatsystem som polygonlagret. Varför detta skall vara nödvändigt vet jag inte, det kan vara en bugg. Men om man inte får ett resultat så kan en anledning vara att lagren har olika koordinatsystem.
När jag sedan redigerar mitt punktlager och flyttar en punkt, så kommer den att byta namn efter vilken polygon den befinner sig i.
Nu är det ju inte bara som etiketter man kan använda aggregate(). Man kan även använda det som ”förvalt” värde i attributformulär när man skapar data.
Här har jag skapat ett linjelager som använder ett uttryck med aggregate() som ”default”. När jag sedan skapar nya linjer, eller redigerar befintliga linjer, så kommer värdet i fältet ”kommuner” att uppdateras med namnen på de kommuner som linjen går igenom.
I det här fallet är aggregeringen ”concatenate” och det är angivet att dessa skall särskiljas med ”, ”.
Det går också att använda aggregate() när man skapar stilar tillsammans med geometrigeneratorer.
Här har jag två polygonlager. Ett med fyrkantiga ytor med bokstavsnamn, och ett polygonlager som överlappar dessa, men som helt saknar attribut.
Cirkeln hämtar sin etikett från de fyrkanter som den överlappar. Precis som i tidigare exempel med ”concatinate”.
Lagret med fyrkanter är stilsatt med två geometrigeneratorer som är identiska, förutom att i den ena används difference() och i den andra intersects().
Den delen av geometrin som ”överlappar” stilsätts på ett sätt, och den delen som ligger utanför stilsätts på ett annat sätt.
Detta är inte en perfekt funktion, för om jag lägger till ytterligare ett objekt som också överlappar samma fyrkanter, så fungerade inte uttrycket riktigt som tänkt till att börja med.
Efter felsökning och redigering av geometrierna så började det helt plötsligt att fungera som förväntat. Inget ändrat i uttrycken, det bara funkade…
Irriterande!
Nåja. Det är en komplicerad funktion och lätt att något blir fel, så det får man väl ha överseende med. Det går att bygga betydligt mera avancerade uttryck. I dokumentationen (länk) så ges ett exempel där varje region får en etikett med namnet på den flygplats som ligger högst över havet.
Dessutom så testas om det finns flera flygplatser på samma nivå och i så fall skrivs samtliga dessa ut som en lista.
För mig har aggregate() funktionen blivit lite lättare att förstå i och med att jag skrivit detta inlägg, och jag hoppas att även du tycker att det är lite lättare att använda funktionen, samt vad den kan användas till i QGIS.
1000 tak for en meget pædagogisk gennemgang.
Hej Klas & tack för en jättebra blogg. Har jag förstått rätt om jag tolkar din text så, att det här problemet (https://gis.stackexchange.com/questions/114630/summarize-the-total-area-of-land-use-polygons-within-map-sheets-how) går att lösa med aggregate()?
Japp, det borde vara möjligt.
Tackar för snabbt svar :-). Jag ska börja testa om jag får det att funka.
Jag har en gammal surdeg kring uppmätning av mittpunkter-centroider i förhållande till givna gränslinjer-polygoner på 2d-kartor (oftast rasterbaserade tyvärr) med respektive innehåll och projektioner.
Utifrån egna efterforskningar och inläggen i detta ämne finner jag inget ställe på nätet där man kan konsumera den här typen av data. Så därför återstår att själv producera QGIS-versioner av detta vilket jag behöver metodisk och teknisk hjälp med då det uppenbarligen inte finns mycket färdigt att hämta på ”lagerhyllorna”. Det man kan finna är koordinaterna för Sveriges mittpunkt efter år 1809 (den nuvarande riksgränsen) med några platsalternativ för hur man vill definiera begreppet mittpunkt (i Hälsingland och i Medelpad). Vi behöver inte ge oss in i den frågan tycker jag – det beror ju på utgångsparametrarna.
Som exempel och förlaga skulle man ju kunna göra ”QGIS-versionen av Sveriges mittpunkt” utifrån sin egen kartografiska definition på mittpunkt och ett givet kartunderlag med sitt objektinnehåll och kartprojektion-koordinatsystem. Därefter kan ju alla mittpunkterna (plural beoende av definitionerna för t ex landmassor och deras positioner) för t ex Kalmar län vara en bra övning då man definitionsmäsigt har att ta hänsyn till havets öar, dess skärgårdar och därmed förstås hela Öland. Det här med sjö- respektive havsvatten kräver sina förberedelser och ger förstås fler en ett svar på frågan om var mittpunkten är belägen.