Cartographier des données linguistiques avec Python – 5

Un précédent article a montré comment créer une carte à partir de données issues d’un fichier CSV, un format couramment utilisé pour les données de recherche, en linguistique ou dans d’autres domaines. Toutefois, s’agissant de données géographiques, rencontrer des données au format GeoJSON qui est spécifiquement conçu pour cet usage, n’aurait rien d’étonnant.

Voici comment produire une carte HTML en Python, avec cette fois un ou plusieurs fichier(s) d’entrée au format GeoJSON.

Prérequis

Cet article présentera les étapes de création d’une carte HTML, en partant d’un fichier au format GeoJSON (.json ou .geojson). Tout ne sera pas expliqué en détail, puisque les quatre articles consacrés à la cartographie de données linguistiques déjà publiés sur ce carnet comportent une certaine quantité d’informations :

Le code (Python 3) sera disponible sous forme de notebook Jupyter et fera appel à la librairie folium, qui sera donc à installer et importer.

Construction du code Python

Le notebook Jupyter présenté dans cet article est mis à disposition sur Gitlab. Les deux exemples de fichier d’entrée (japo1237.json et hmon1336.json) ainsi que le fichier HTML de la carte obtenue sont également téléchargeables.
La carte peut être consultée sur cette page sans télécharger le code source.

L’objectif sera d’obtenir une carte semblable à celle-ci (voir en ligne) :

Il y a plusieurs façons d’ajouter des données à une carte à partir d’un fichier GeoJSON. Comme j’ai déjà détaillé comment procéder avec un fichier d’entrée en CSV, la production de la carte à partir d’un GeoJSON se fera de manière similaire. Les étapes à suivre seront les mêmes :

  1. Déclaration et paramétrage du fond de carte.
  2. Création d’une couche de données pour y placer les points.
  3. Lecture du fichier d’entrée pour ajout des points à la couche de données (avec paramétrage des points).
  4. Ajout de la couche de données à la carte.
  5. Enregistrement de la carte dans un fichier HTML.

C’est lors de la prise en compte du fichier d’entrée que le traitement va devenir spécifique : seule l’étape 3 de la liste ci-dessus sera montrée en détail dans cet article. Comme pour les articles précédents, la variable correspondant à la carte est nommée ma_carte.

Fichiers d’entrée

Le fichier source est cette fois au format GeoJSON, dont l’extension est .geojson ou .json. Deux séries de points seront représentées ici, il y a donc deux fichiers d’entrée (japo1237.json1 et hmon1336.json2), dont les chemins d’accès ont été respectivement associés aux variables japo_source et hmon_source.

Les données de ces fichiers, issues de la plateforme Glottolog3, correspondent à la représentation de l’implantation des langues japoniques et hmong-mien4. Il s’agit des données qui sont aussi à la base des cartes précédentes (à voir en ligne ici, ici et ici), mais qui avaient été traitées à partir d’un fichier CSV.

Il est à noter que Glottolog met à disposition les données géographiques au format GeoJSON, et que les fichiers CSV utilisés précédemment ont en fait été produits à partir du GeoJSON proposé sur Glottolog.

Ajout des points à la carte

À ce stade, une carte (ma_carte) et deux couches de données (japo1237 et hmon1336) ont été déclarées, en plus des chemins d’accès des fichiers pris en entrée.

Il y a différentes façons d’intégrer les données d’un fichier GeoJSON à une carte générée par folium, celle qui est montrée dans le notebook (via la fonction ajouter_points()) est proche de ce qui avait était fait lorsque le fichier d’entrée est au format CSV. En premier lieu, l’ouverture du fichier source et la lecture de ses données se fait avec la fonction folium.GeoJson(chemin_du_fichier). Dans l’exemple, le chemin d’accès du fichier GeoJSON est un argument d’ajouter_points() appelé source. On l’associe à une variable, que j’ai arbitrairement nommée geo_source :

geo_source = folium.GeoJson(source)

Le fichier GeoJson peut maintenant être parcouru comme un dictionnaire, via son attribut .data. Ici, pour chacun des deux fichiers d’entrée, geo_source.data contient : type, properties et features. Voici pourquoi :

Premières lignes du fichier japo1237.json (télécharger).

Le contenu de type et properties est entièrement visible sur l’image. C’est bien features qui contient les données à récupérer pour pouvoir placer les points sur la carte : il s’agit d’une liste de dictionnaires dont chaque élément comprend les informations relatives à un point.

Détail d’un élément de la liste features du fichier japo1237.json (télécharger).

La déclaration des points peut alors se faire en mettant en place une boucle parcourant geo_source.data['features']. Chaque point correspond à une instance d’objet folium.CircleMarker(), comme expliqué ici. La structure du code est la suivante5 :

    for feature in geo_source.data['features']:
        if feature['geometry']['type'] == 'Point':
            folium.CircleMarker(
                # paramètres du point
            ).add_to(couche_donnees)

Je ne détaillerai pas les paramètres de folium.CircleMarker(), ce sont les mêmes qu’avec un fichier source en CSV. Il y a toutefois un détail auquel faire attention lors de la récupération des coordonnées géographiques. Dans les fichiers GeoJSON utilisés comme exemples6, on peut récupérer ces coordonnées de deux façons :

  1. Avec la valeur de feature['properties']['language']['longitude'] et de feature['properties']['language']['latitude'].
  2. Avec la valeur de feature['geometry']['coordinates'].

Si comme dans le notebook, vous choisissez la seconde solution, n’oubliez pas que le paramètre location de folium.CircleMarker() prend pour valeur une liste comprenant la latitude et la longitude, dans cet ordre. Or ici feature['geometry']['coordinates'] correspond à une liste où les coordonnées sont dans l’ordre inverse. Il est donc important d’inverser l’ordre de la liste :

location=list(reversed(feature['geometry']['coordinates']))

Les points seront alors placés correctement.

Si vous avez téléchargé le notebook et exécuté son code sans le modifier, vous avez normalement obtenu un fichier carte_hmong-mien_japonic.html, contenant cette carte (code source).

Pourquoi ne pas ajouter directement le GeoJSON à la carte ?

Dans cet article qui détaille comment tracer un polygone sur une carte, j’expliquais qu’il était possible d’ajouter directement une couche GeoJSON à la carte en instanciant un objet folium.GeoJson().

C’est tout à fait possible de le faire à partir d’un fichier. Par exemple, pour le fichier japo1237.json et avec les noms de variables utilisés dans le notebook :

folium.GeoJson(japo_source, name='Langues japoniques').add_to(ma_carte)

Vous obtiendrez une carte ressemblant à ceci :

Import des données de japo1237.json.

Si cette solution vous semble plus pertinente pour votre projet, il n’y a pas de problème à l’utiliser.

Alors pourquoi avoir procédé autrement ? Il est, à ma connaissance, plus compliqué de contrôler l’aspect des marqueurs en important les données de cette façon (si je ne fais pas erreur les marqueurs bleus sur l’image ci-dessus sont les marqueurs par défaut de Leaflet, la librairie JavaScript à la base de folium).

Ne pas importer le fichier directement mais plutôt parcourir les données d’un objet folium.GeoJson()7 avec une boucle pour instancier des folium.CircleMarker() sur une couche de données permet de paramétrer assez facilement l’apparence des marqueurs, et ne constitue pas un grand changement par rapport à ce qui a été expliqué dans les articles précédents : si vous avez suivi les explications de l’article pour créer une carte à partir d’un fichier CSV et que vous voulez maintenant utiliser les données d’un fichier source en GeoJSON, vous pouvez même récupérer une partie de votre code.

Citer ce billet : “Cartographier des données linguistiques avec Python – 5”, par Alexander Delaporte. Publié sur Tekipaki le 25/03/2021. Lien : https://tekipaki.hypotheses.org/1421.
  1. Disponible sur Gitlab. []
  2. Disponible sur Gitlab. []
  3. Glottolog 4.3 par Hammarström, Harald & Forkel, Robert & Haspelmath, Martin & Bank, Sebastian sous licence Creative Commons Attribution 4.0 International License []
  4. Il n’y a pas de raison particulière à regrouper ces familles de langues dans une même carte. C’est assez pratique pour l’exemple, parce que les points sont relativement proches les uns des autres. []
  5. if feature['geometry']['type'] == 'Point' n’est pas indispensable mais il est plus prudent d’ajouter cette condition pour les fichiers d’entrée dont on ne connaît pas intégralement le contenu. []
  6. japo1237.json (lien) et hmon1336.json (lien). []
  7. Grâce à son attribut .data. []

Auteur/autrice : Alexander Delaporte

Ingénieur d'études au Centre de recherches linguistiques sur l'Asie Orientale et chercheur associé BnF 2019-2021

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.