Photo by Sigmund on Unsplash

Comment traiter des données géospatiales en 2022

Par Zachary Deziel, le 15 septembre 2022

Anagraph offre des services en traitement et visualisation de données géospatiales. Si la partie cartographie web est la pointe visible de l’iceberg de nos travaux, la partie traitement et ingénierie de données est celle sur laquelle nous apportons une plus value majeure pour les grandes et moyennes organisations que nous accompagnons.

Nous allons partager ici la manière dont Anagraph développe, maintient et déploie des pipelines de données rapidement pour intégrer des données à nos projets avec un minimum d’effort.

La base des ETLs

Depuis l’ère de MapInfo, ArcGIS, et les premières versions de QGIS, les traitements de données géospatiales étaient réservés à des spécialistes en géomatique. De manière classique, les données sont stockées localement ou sur un FTP et les traitements sont réalisés manuellement ou automatisés avec des outils graphiques; model builder, FME, et autres. Le GIS classique suit le patron d’extraction-transformation-load (ETL). Cependant, il y a des difficultés énormes pour maintenir un catalogue de données et les pipelines de traitement dans cet écosystème. Les transformations sont difficilement reproductibles, scalables, et testables.

Nouveau paradigme : de l’ETL vers l’ELT

PostGIS et certains entrepôts de données (BigQuery et Snowflake) sont en train de révolutionner la manière dont les données géospatiales sont traitées. Le SpatialSQL permet de développer et d’exécuter des traitements simplement en écrivant quelques lignes de code. Rien de nouveau pour ceux familiers avec PostGIS. Par contre, il manque toujours un morceau pour transformer les entrepôts comme simple outil de stockage et de traitement manuel à des véritables machines d’exécution de pipelines de données.

Cet outil est data build tools (dbt).

dbt est peut-être l’outil le plus adopté par les équipes de données à l’extérieur du monde géospatial. Par contre, son adoption dans la communauté géospatial est relativement lente. dbt change complètement le paradigme des ETLs traditionnels en renversant les deux dernières étapes. Le chargement des données va donc maintenant précéder leurs traitements!

Sans faire une introduction complète, les éléments-clés de dbt méritent d’être présentés. Vous pouvez en apprendre plus sur dbt en visitant leur documentation.

dbt crée des pipelines de données directement à partir de requêtes SQL. Après avoir configuré votre projet dbt, vous pouvez écrire un modèle qui est en fait une simple requête.

Utilisation de dbt pour les données de statistiques Canada

{{ config(
    materialized = 'table',
    indexes=[
      {'columns': ['id', 'adidu']},
      {'columns': ['geom'], 'type': 'gist'},
    ],
    tags="aire_diffusion_2021"
)}}

select ogc_fid id, dauid adidu, dguid, landarea, pruid, st_transform(wkb_geometry, 3857) geom
from aire_diffusion_2021

À l’exécution du projet dbt, une nouvelle table se trouvera dans la base de données définie du projet. Assez simple, voire sans intérêt avec le cas d’un simple modèle, le processus devient toutefois intéressant lorsque les modèles ont des dépendances entre elles.

Dans l’exemple de Statistiques Canada, les données attributaires et les limites administratives ne sont pas fournies ensemble. De même, les données attributaires ont une modélisation loin d’être standard qui rend son utilisation complexe voire impossible sans faire des traitements relativement avancés. dbt permet d’établir clairement les chaînes de traitement et de joindre les deux sources de données ensemble.

Voici le modèle pour transformer les données attributaires du recensement:

{{ config(
    materialized = 'table',
    indexes=[
      {'columns': ['adidu']},
    ]
)}}

with adidu_attr as (
    select "nom_gÉo" adidu, "id_caractÉristique" id_caracteristic, c1_chiffre_total val from population_ad_2021
),
     jsonb_magic as (
         select adidu, jsonb_object_agg(id_caracteristic, val) jsonb_attr
         from adidu_attr
         group by adidu
     )
select adidu,
       jsonb_attr ->> '1' population_2021,
       jsonb_attr ->> '2' population_2016,
       jsonb_attr ->> '3' population_variation_2021_2016,
       jsonb_attr ->> '4' total_logements_prives,
       jsonb_attr ->> '5' logements_prives_occupes,
       jsonb_attr ->> '6' densite_population_2021,
       jsonb_attr ->> '7' superficie_terre
from jsonb_magic

Finalement, il est possible de joindre les limites administratives avec les données attributaires. Remarquez l’utilisation du mot-clé ref de dbt. Au moment de l’exécution, dbt remplace les références par le nom de table tout en assurant la généalogie des données.

{{ config(
    materialized = 'table',
    indexes=[
      {'columns': ['id']},
      {'columns': ['geom'], 'type': 'gist'},
    ]
)}}

select id, ad.adidu da_adidu, ad.geom, ad.landarea, pruid, pop_attr.*
from {{ref('aire_diffusion_2021_3857')}} ad
left join {{ref('population_aire_diffusion_raw')}} pop_attr on ad.adidu=pop_attr.adidu

De plus, dbt permet d’observer l’ensemble des caractéristiques définies des données et cette généalogie avec ces fonctions de documentation. Par exemple, on peut observer la généalogie directement sur la page web générée de notre projet:

dbt lineage graph model for the population of the StatCan 2021 census data
dbt lineage graph model for the population of the StatCan 2021 census data

Les caractéristiques définies dans les fichiers de définition se font directement ajouter à la documentation du projet dbt.

version: 2

models:
  - name: aire_diffusion_population_2021_3857
    description: Integrating Census Profile, 2021
    docs:
      show: true
    columns:
      - name: 'id'
        description: Refers to Id of each dissemination block
        tests:
          - not_null
      - name: 'adidu'
        description: Refers to Id of each dissemination block
        tests:
          - not_null
      - name: 'da_adidu'
        description: Refers to Id of each dissemination block
        tests:
          - not_null
      - name: 'population_2016'
        description: Refers to Canadian Demographic Data for 2016
      - name: 'population_2021'
        description: Refers to Canadian Demographic Data for 2016
      - name: 'population_variation_2021_2016'
        description: Refers to The rate of change in population dispersion during the years 2016 to 2021 (percentage)
        tests:
          - not_null
      - name: 'total_logements_prives'
        description: Refers to a separate set of living quarters with a private entrance
      - name: 'logements_prives_occupes'
        description: Refers to a private dwelling in which a person or a group of persons is permanently residing
      - name: 'densite_population_2021'
        description: Refers to density of population living per square kilometer
      - name: 'superficie_terre'
        description: Refers to the number of square kilometres of land in a given geographic area
        tests:
          - not_null
      - name: 'landarea'
        description: Refers to the number of square kilometres of land in a given geographic area
        tests:
          - not_null
      - name: 'geom'
        description: Refers to EPSG:3857 (a Spherical Mercator projection coordinate system)
        tests:
      - name: 'pruid'
GIF showing the dbt documentation generated with the references to construct the graph lineage and the YAML schema file.
GIF showing the dbt documentation generated with the references to construct the graph lineage and the YAML schema file.

Potentiellement le bienfait le plus important de dbt est la simplicité de définir des tests automatisés. Il existe deux types de tests: (1) des tests de schémas et (2) des tests de données. Les tests de schémas sont définis dans la configuration du modèle; dans le schema.yml ou la section config au sein d’un modèle. Les tests de données ont besoin qu’une requête soit exécutée sur une table. dbt ont établi un standard où un test passe si la requête retourne aucune rangée et échoue sinon. Habituellement, rajouter un having à une requête est suffisant pour s’y adapter.

Il existe beaucoup d’autres éléments assez innovants de l’outil comme des macros pour créer des index automatiquement, des tests génériques faits sur mesure, des modèles en python, et d’autres! Par exemple, nous avons un nombre grandissant de macros pour tester des géométries de PostGIS:


{% test is_valid(model, column_name) %}

SELECT *
FROM {{ model }}
WHERE (NOT st_isvalid( {{ column_name }}))

{% endtest %}

Conclusion

Dans un écosystème d’outils et de données géospatiales éclatés tout en étant fortement lié, il est facile de perdre le contrôle de la gestion de nos données. Nous croyons qu’il y a des solutions matures qui permettent de gérer des volumes de données massives simplement tout en évitant l’emprisonnement technologique.

L’équipe d’Anagraph est présente pour accompagner les organisations dans leur transition numérique.

Restez à l’affût pour des informations concernant la publication de notre outil d’importation de données.