Een geanimeerd cartogram maken (QGIS3)

Een cartogram is een type kaartvisualisatie waarin de vorm van elk object in verhouding is vervormd tot een variabele. Cartogrammen maken het gemakkelijk grote variaties in de gegevens te zien. De eenvoudigste methode om een cartogram te maken is door de grootte van elke regio op schaal te brengen, overeenkomstig een variabele. Deze methode behoudt de originele vorm van de polygoon en wijzigt alleen de grootte. Deze staan bekend als Niet-aaneensluitende isomorfische cartogrammen. In deze handleiding zullen we leren hoe expressies van QGIS te gebruiken om een cartogram te maken en Tijdbeheer te gebruiken om een animatie te maken die de objecten gradueel vervormt tot de doelgrootte.

Deze handleiding is geïnspireerd op Hans van der Kwast’s excellente handleiding voor een cartogram. De formule voor de hier gebruikte schaalfactor is afkomstig uit het originele paper Noncontiguous Area Cartograms door Judy M Olson.

You can also watch my YouTube video QGIS Expressions: Hidden Gems and Unexpected Possibilities which explains the concepts behind this tutorial.

Overzicht van de taak

We zullen een laag van de staten in de Verenigde Staten nemen en een geanimeerd cartogram maken door elke staat op grootte te brengen naar inwoners. De resulterende kaart zal het gebied van elke staat op grootte hebben gebracht, proportioneel ten opzichte van het aantal inwoners.

../../_images/output.gif

De gegevens ophalen

United States Census Bureau verschaft cartografische bestanden met grenzen, naast demografische gegevenssets. We zullen de gegevens downloaden en ze verwerken om een gegevenslaag te maken die geschikt is voor onze taak.

  1. Bezoek de pagina met gegevens Cartographic Boundary Files - Shapefile. Download het bestand cb_2018_us_state_20m.zip. Dat heeft de polygonen die we nodig hebben voor de visualisatie.

../../_images/data19.png
  1. De polygonen van de staten hebben geen demografische gegevens. Deze gegevens moeten afzonderlijk worden gedownload en afzonderlijk worden samengevoegd met de Shapefile om in een GIS te kunnen gebruiken. Bezoek de pagina State Population Totals and Components of Change: 2020-2023 en download de gegevensset Annual Population Estimates, Estimated Components of Resident Population Change, and Rates of the Components of Resident Population Change for the United States, States, District of Columbia, and Puerto Rico: April 1, 2020 to July 1, 2023 , die zal worden gedownload als NST-EST2023-ALLDATA.csv.

../../_images/data23.png
  1. Open QGIS. Zoek naar het bestand cb_2018_us_state_20m.zip in de QGIS Browser en vergroot het. Sleep het bestand cb_2018_us_state_20m.shp naar het kaartvenster en zet het daar neer.

../../_images/data33.png
  1. Een nieuwe laag cb_2018_us_state_20m zal worden toegevoegd aan het paneel Lagen. Vervolgens zullen we het CSV-bestand laden. Klik op de knop Databronnen beheren openen.

../../_images/data43.png
  1. Schakel naar de tab Tekengescheiden tekst. Klik op de knop naast Bestandsnaam en blader naar het gedownloade bestand NST-EST2023-ALLDATA.csv. Vergroot het gedeelte Geometrie definitie en selecteer Geen geometrie (alleen attributentabel). Klik op Toevoegen.

../../_images/data53.png
  1. Een nieuwe laag NST-EST2023-ALLDATA zal worden toegevoegd aan het paneel Lagen. Klik met rechts en selecteer Attributentabel openen. Deze tabel heeft de aantallen inwoners in de kolom POPESTIMATE2023. Elke staat heeft een unieke ID in de kolom STATE, die we zullen gebruiken om deze tabel samen te voegen met de polygoonlaag.

../../_images/data63.png
  1. Klik met rechts op de laag cb_2018_us_state_20m en selecteer Attributentabel openen. De ID’s voor de staten zijn opgenomen in de kolom GEOID. Hoewel de getallen hetzelfde zijn, zijn zij opgemaakt als 2-cijferige, met voorloopnullen aangevulde getallen. We hebben dezelfde soort opgemaakte getallen nodig om deze overeen te laten komen met de kolom STATE uit onze tabel met inwoners. Selecteer NST-EST2023-ALLDATA. Ga naar Processing ‣ Toolbox. Zoek en lokaliseer het algoritme Vector tabel ‣ Veld calculator. Dubbelklik erop om het te openen.

../../_images/data73.png
  1. In het dialoogvenster Veld calculator, selecteer NST-EST2023-ALLDATA als de Invoerlaag, voer GEOID in als de Veldnaam, en stel Type resultaatveld ` in als ``Tekst (string)`. We zullen nu de getallen uit het veld STATE nemen en de functie lpad() gebruiken om een 2-cijferige tekenreeks, aangevuld met voorloopnullen te maken. Voer de volgende expressie in en klik op Uitvoeren

lpad("STATE", 2, '0')
../../_images/data82.png
  1. Een nieuwe laag Berekend zal worden toegevoegd aan het paneel Lagen. Klik met rechts en selecteer Attributentabel openen. Merk op dat de nieuw gemaakte kolom GEOID de correct opgemaakte identificaties heeft. We kunnen nu dat veld gebruiken om deze tabel samen te voegen met de laag van de staten. Zoek en lokaliseer het algoritme Vector algemeen ‣ Attributen koppelen op veldwaarde. Dubbelklik erop om het te openen.

../../_images/data92.png
  1. In het dialoogvenster Attributen koppelen op veldwaarde, selecteer cb_2018_us_state_20m als de Invoerlaag. Selecteer GEOID als het Tabelveld. Voor Invoerlaag 2, selecteer onze tabel Berekend en voor Tabelveld 2, selecteer GEOID. De tabel heeft heel veel kolommen, maar we hebben alleen het aantal inwoners van het laatste jaar nodig. Klik op de knop voor Velden van laag 2 om te kopiëren en selecteer alleen het veld POPESTIMATE2023. Laat alle andere opties op hun standaardwaarde en klik op Uitvoeren.

../../_images/data102.png
  1. Een nieuwe laag Samengevoegde laag zal worden toegevoegd aan het paneel Lagen. Laten we, voordat we deze laag gebruiken voor ons cartogram, die opnieuw projecteren naar een geprojecteerd CRS. Zoek en lokaliseer het algoritme Vector algemeen ‣ Laag opnieuw projecteren. Dubbelklik erop om het te openen.

../../_images/data114.png
  1. In het dialoogvenster Laag opnieuw projecteren, selecteer Samengevoegde laag als de Invoerlaag. Klik, voor het Doel-CRS, op de knop CRS selecteren. Zoek naar het CRS North_America_Albers_Equal_Area_Conic en selecteer dat. Dit is onze uiteindelijke laag, dus zullen we die opslaan op schijf. Klik op de knop naast Opnieuw geprojecteerd en selecteer Opslaan als bestand….

../../_images/data123.png
  1. Voer als naam voor de laag in us_states_with_population.gpkg en selecteer Opslaan. Klik op Uitvoeren om het bestand GeoPackage met de opnieuw geprojecteerde gegevens te maken.

../../_images/data132.png

We zullen deze laag gebruiken in het volgende gedeelte. Voor het gemak kunt u direct een kopie van bovenstaande laag downloaden vanaf hieronder:

us_states_with_population.gpkg

Gegevensbron [USCENSUS]

Procedure

  1. Begin een nieuw project in QGIS. Lokaliseer het bestand us_states_with_population.gpkg in de Browser en vergroot het. Sleep de laag us_states_with_population in het lege kaartvenster en zet hem daar neer.

../../_images/140.png
  1. Een nieuwe laag us_states_with_population zal worden toegevoegd aan het paneel Lagen. Klik met rechts en selecteer Attributentabel openen. Voor ons cartogram willen we de dichtheid van de inwoners als de variabele gebruiken. We zullen de waarden voor de inwoners gebruiken in het veld POPESTIMATE2023. Sluit de attributentabel.

../../_images/227.png
  1. Zoek en lokaliseer het algoritme Vector tabel ‣ Veld calculator in de Toolbox van Processing. Dubbelklik erop om het te starten.

../../_images/319.png
  1. In het dialoogvenster Veld calculator, selecteer us_states_with_population als de Invoerlaag. Voer density in als de Veldnaam. Voer de volgende expressie in om de dichtheid te berekenen. Omdat de functie area(@geometry) het gebied berekent in de eenheid van het CRS (wat in meters is), passen we de conversiefactor toe om te converteren naar vierkante kilometers. Klik op Uitvoeren.

1000*1000* "POPESTIMATE2023" /
area(@geometry)
../../_images/48.png
  1. Klik op de knop naast Berekend en selecteer Opslaan als bestand…. Voer de naam van de laag in als us_states_population_density.gpkg en selecteer Opslaan. Klik op Uitvoeren.

../../_images/58.png
  1. Een nieuwe laag us_states_population_density zal worden toegevoegd aan het paneel Lagen. Klik met rechts en selecteer Attributentabel openen. We moeten een object Anker kiezen waartegen alle andere objecten op schaal zullen worden gebracht. Idealiter zou u het object kiezen met de hoogste waarde voor de variabele die u wilt gebruiken voor het cartogram. Dat zal ervoor zorgen dat er geen overlappende gebieden zijn. Dubbelklik op de kolomkop van density om de tabel op dichtheid te sorteren. U zult merken dat de hoogste waarde voor de dichtheid in onze gegevensset behoorlijk veel groter is in vergelijking tot de andere waarden en het behoort tot een redelijk kleine staat. Dat zal erin resulteren dat alle objecten op schaal zullen worden gebracht in hele kleine grootten. We kunnen het object kiezen met de op een na hoogste dichtheid, wat een behoorlijk groot gebied heeft en waarvan de dichtheid is te vergelijken met andere objecten.

../../_images/68.png
  1. In cartogrammen met gebieden bepaalt de schaalfactor hoeveel het gebied van het object wordt verkleind. We moeten het gebied van elk object verkleinen, zodat de dichtheid van de inwoners van het object hetzelfde is als de dichtheid van de inwoners van het anker-object. De formule voor de schaalfactor is de verhouding van de vierkantswortel van de waarde van het object ten opzichte van de vierkantswortel van de waarde van het anker-object. Open het algoritme Vector tabel ‣ Veld calculator uit de Toolbox van Processing. In het dialoogvenster Veld calculator, selecteer us_states_population_density als de Invoerlaag. Voer scale_factor in als de Veldnaam. Voer de volgende expressie in om de schaalfactor te berekenen. De expressie berekent de verhouding voor de vierkantswortel van de dichtheid van het object met de vierkantswortel van de dichtheid van de op een na grootste waarde voor de dichtheid. Klik op de knop naast Berekend en selecteer Opslaan als bestand…. Voer als naam voor de laag in us_states_scale_factor.gpkg en selecteer Opslaan. Klik op Uitvoeren.

sqrt("density")/array_get(array_agg(
   expression:=sqrt("density"),
   order_by:=sqrt("density")), -2)
../../_images/78.png
  1. Een nieuwe laag us_states_scale_factor zal worden toegevoegd aan het paneel Lagen. Klik met rechts en selecteer Attributentabel openen. Het veld scale_factor bevat nu de verhouding waarmee elk object op schaal moet worden gebracht om dezelfde dichtheid van inwoners te hebben als het anker-object=.

../../_images/88.png
  1. We hebben alleen de laag us_states_scale_factor nodig voor de uiteindelijke visualisatie. Selecteer de overblijvende lagen, klik met rechts en selecteer Laag verwijderen.

../../_images/98.png
  1. Selecteer de laag us_states_scale_factor en klik op de knop Paneel Laag opmaken openen in het paneel Lagen. Selecteer Standaard vulling en open de keuzeselectie voor Symboollaagtype. Stel het Symboollaagtype in op Rand: Doorgetrokken lijn en selecteer een Kleur van uw keuze. Deze symboollaag zal een verwijzing zijn voor onze kaart als we de grootten van de polygonen wijzigen.

../../_images/1012.png
  1. Klik op de knop Symboollaag toevoegen (+). Een nieuwe symboollaag Standaard vulling zal worden toegevoegd. Stel de Vulkleur in op dezelfde kleur als de lijnen en de Lijnkleur op een iets donkerder kleur.

../../_images/1115.png
  1. Open vervolgens de keuzeselectie voor Symboollaagtype en selecteer Geometrie-generator als het Symboollaagtype. Geometrie-generator stelt ons in staat de geometrie voor het renderen aan te passen met expressies. Klik op de knop Expressiebouwer.

../../_images/1213.png
  1. We zullen de functie scale() gebruiken die de opgegeven geometrie in grootte wijzigt met de opgegeven X- en Y-factoren voor het op schaal brengen. Voor ons cartogram, willen we elke polygoon opnieuw op grootte brengen in verhouding met zijn inwoneraantal voor het hoogste aantal inwoners. Voer de volgende expressie in om dit op schaal brengen toe te passen en klik op OK.

scale(
   @geometry,
   "scale_factor",
   "scale_factor",
   centroid(@geometry)
)
../../_images/1311.png
  1. U zult nu zien dat de polygonen van de staten nu op grootte zijn gebracht naar de verhouding van de inwoneraantallen van elke staat ten opzichte van het hoogste inwoneraantal. Veel grote staten met lage dichtheid van inwoners zijn nu veel kleiner dan hun originele grootte. Het zal u opvallen dat polygonen met onregelmatige vormen uit het centrum liggen na het op schaal brengen. Dat komt omdat het ankerpunt van het op schaal brengen het zwaartepunt is van de geometrie, wat vaak het representatieve punt voor de polygoon is. Laten we onze expressie aanpassen om dit op te lossen. Klik op de knop Expressiebouwer.

../../_images/1410.png
  1. De functie scale() kan een optionele parameter bevatten om het middelpunt van het op schaal brengen te specificeren. We zullen de functie pole_of_inaccessibility() gebruiken om een representatief ankerpunt te zoeken voor elke polygoon. Dat is soortgelijk aan een zwaartepunt, maar het ligt gegarandeerd binnen de polygoon, terwijl een zwaartepunt er buiten kan vallen voor bepaalde vormen. Werk de expressie bij zoals hieronder, die de pool van ontoegankelijkheid van de geometrie berekent met een kleine tolerantiewaarde, en klik op OK.

scale(
    @geometry,
    "scale_factor",
    "scale_factor",
    pole_of_inaccessibility(@geometry, 100)
)
../../_images/1510.png
  1. Nu zullen de op schaal gebrachte polygonen een veel betere plaatsing hebben. We zien echter ene ander probleem. Veel objecten op de laag zijn Multipolygonen, d.i. zij hebben meer dan een deel. Dergelijke objecten hebben 2 of meer delen die deel uitmaken van dezelfde geometrie. Met onze huidige expressie, worden beide op schaal gebracht met hetzelfde ankerpunt, dat wordt berekend uit de gecombineerde geometrie. Dit is niet ideaal. Bijvoorbeeld een groot object met meerdere eilanden zou zo op schaal moeten worden gebracht dat elk eiland op schaal wordt gebracht met zijn eigen middelpunt. We werken, om dit op te lossen, onze expressie door over elk deel van de geometrie te lopen en het op schaal te brengen met zijn eigen middelpunt. Klik op de knop Expressiebouwer.

../../_images/169.png
  1. Hier gebruiken we de functie array_foreach() om over elk deel van de geometrie te lopen en er op schaal gebrachte versies van te maken. Tenslotte combineert de functie collect_geometries() elk op schaal gebracht deel naar een enkele geometrie multipolygoon. Werk de expressie bij, zoals hieronder weergegeven, en klik op OK.

collect_geometries(
    array_foreach(generate_series(1, @geometry_part_count),
            scale(geometry_n(@geometry,@element),
                    "scale_factor",
                    "scale_factor",
pole_of_inaccessibility(geometry_n(@geometry,@element), 100)
            )
    )
)
../../_images/1710.png
  1. Het resultaat is het veel beter op schaal brengen van meerdelige objecten.

../../_images/188.png
  1. Ons cartogram is voltooid. Deze kaart geeft de concentratie weer van de inwoners voor de oostelijke helft van de VS en een opvallende afwezigheid van inwoners in de staten ten westen van de rivier Mississippi.

../../_images/197.png
  1. We kunnen een verbeterde visualisatie maken door een animatie die langzaam de originele rendering transformeert naar de uiteindelijke grootte. Klik op de knop Tijdbeheer met het pictogram van een klok op de werkbalk Kaartnavigatie. Selecteer de knop Geanimeerde navigatie voor tijd.

../../_images/207.png
  1. Het standaard Bereik animatie zal worden gevuld met een 24 uursvenster, met een verhoging van 1-uur. Dat is prima voor ons geval voor gebruik, omdat we dan 24 frames voor de animatie krijgen. U kunt dat aanpassen als u een tragere/snellere animatie wilt. Klik met rechts op de laag us_states_with_population en selecteer Eigenschappen.

../../_images/2112.png
  1. Selecteer de tab Tijdbeheer en schakel Dynamisch Tijdbeheer in. Deze laag zal worden bijgewerkt met een expressie dus dat hoeven we hier niet te configureren. Selecteer eenvoudigweg Alleen laag opnieuw tekenen zodat de laag wordt vernieuwd na elke tijdstap en gerenderd met de bijgewerkte waarden uit de expressie.

../../_images/228.png
  1. Laten we onze expressie van de Geometrie-generator bijwerken om de tijdstappen voor de animatie te gebruiken en gradueel de geometrie op schaal te brengen. Klik op de knop Paneel Laag opmaken openen in het paneel Lagen. Selecteer Geometrie-generator, gevolgd door de knop Expressiebouwer.

../../_images/236.png
  1. Hier willen we beginnen met een schaalfactor van 1 en eindigen met de uiteindelijke schaalfactor van voor het object in het veld scale_factor. We gebruiken de functie scale_linear() die de tijd van de huidige tijdstap neemt en berekent de schaalfactor met de begin- en eindtijden. Werk de expressie, bij zoals hieronder weergegeven, en klik op OK.

collect_geometries(
    array_foreach(generate_series(1, @geometry_part_count),
            scale(geometry_n(@geometry,@element),
                    scale_linear(
                            epoch(@map_start_time),
                            epoch(@animation_start_time),
                            epoch(@animation_end_time),
                            1,
                            "scale_factor"),
                    scale_linear(
                            epoch(@map_start_time),
                            epoch(@animation_start_time),
                            epoch(@animation_end_time),
                            1,
                            "scale_factor"),
pole_of_inaccessibility(geometry_n(@geometry,@element), 100)
            )
    )
)
../../_images/247.png
  1. Terug in het paneel Tijdbeheer, klik op de knop Afspelen om de animatie te bekijken. U zou de vorm van elke polygoon geleidelijk moeten zien worden geschaald na elk frame.

../../_images/257.png
  1. Als u tevreden bent met de configuratie, kunnen we de animatie exporteren. Klik op de knop Animatie exporteren.

../../_images/266.png
  1. In het dialoogvenster Animatie van kaart exporteren, klik op naast Map voor uitvoer en blader naar een map op uw computer. Behoud alle andere opties op hun standaard waarden en klik op Opslaan.

../../_images/277.png
  1. De individuele frames van de animatie zullen als afbeeldingen worden geëxporteerd. We kunnen een video of geanimeerde GIF maken met deze frames. Ik raad aan om de website ezgif.com te gebruiken die u in staat stelt gemakkelijk GIF’s te maken uit individuele afbeeldingen. Bezoek Ezgif Animated GIF Maker. Blader naar de geëxporteerde frames van de animatie en klik op Upload files!.

../../_images/287.png
  1. Configureer de opties voor de GIF door Delay time in te stellen op 5. Selecteer het effect crossfade frames en stel Fader delay en Fader count in op 2. Klik op Make a GIF!/

../../_images/296.png
  1. Klik op de knop save om de animatie als een GIF-bestand te downloaden.

../../_images/output.gif ../../_images/hawaii.gif ../../_images/alaska.gif

If you want to give feedback or share your experience with this tutorial, please comment below. (requires GitHub account)