Introduction à la cartographie avec Python

La cartographie est un excellent moyen de diffuser de la connaissance sur les données, y compris à des publics peu familiers de la statistique. Ce chapitre permet de découvrir le défi de la cartographie et la manière dont on peut utiliser Python pour construire des cartes.

Visualisation
Exercice
Auteur·rice

Lino Galiana

Date de publication

2024-12-27

Pour essayer les exemples présents dans ce tutoriel :
View on GitHub Onyxia Onyxia Open In Colab
Compétences à l’issue de ce chapitre

1 Introduction

La cartographie est l’une des plus anciennes représentations d’informations sous forme graphique. Longtemps cantonnée aux domaines militaires et administratifs ou à la synthèse d’informations pour la navigation, la cartographie est, au moins depuis le XIXe siècle, une des formes privilégiées de représentation de l’information. Il s’agit de l’époque où la carte par aplat de couleur, dite carte choroplèthe, a commencé à devenir une représentation de données géographiques traditionnelle.

D’après Chen et al. (2008), la première représentation de ce type a été proposée par Charles Dupin en 1826 Figure 1.1 pour représenter les niveaux d’instruction sur le territoire français. L’émergence des cartes choroplèthes est en effet indissociable de l’organisation du pouvoir sous forme d’entités politiques supposées unitaires. Par exemple, les cartes du monde représentent souvent des aplats de couleurs à partir des nations, les cartes nationales à partir d’échelons administratifs (régions, départements, communes, mais aussi Etats ou landers).

Figure 1.1: La première carte choroplèthes par Dupin (1826)

On peut voir l’émergence pendant le XIXe siècle de la carte choroplèthe comme un moment important de la cartographie, un glissement de l’usage militaire vers l’usage politique. Il ne s’agissait plus exclusivement de représenter le territoire physique mais aussi la réalité socioéconomique, dans des bornes administratives connues de tous.

Avec la prolifération de données géolocalisées et l’usage accru de données pour la décision, il est devenu crucial pour les data scientists de savoir faire une carte rapidement. Ce chapitre, complément de celui sur les données spatiales, propose quelques exercices pour apprendre les enjeux de la représentation de données sous forme cartographique avec Python.

Note

Produire de belles cartes demande du temps mais aussi du bon sens. Comme toute représentation graphique, il est important de réfléchir au message à faire passer et aux moyens appropriés. La sémiologie cartographique, une discipline scientifique qui s’intéresse aux messages transmis par les cartes, propose certaines règles pour éviter de transmettre des messages faussés, volontairement ou involontairement.

Certaines peuvent être retrouvées à travers des conseils pratiques dans ce guide de sémiologie cartographique de l’Insee. Celles-ci sont reprises dans ce guide.

Cette présentation de Nicolas Lambert revient, à partir de nombreux exemples, sur quelques principes de la dataviz cartographique.

Ce chapitre présentera d’abord quelques fonctionnalités basiques de Geopandas pour la construction de cartes figées. Pour contextualiser l’information présentée, nous utiliserons des contours officiels produits par l’IGN. Nous proposerons ensuite des cartes avec une contextualisation accrue et plusieurs niveaux d’information ce qui permettra d’illustrer l’intérêt de l’utilisation de librairies réactives, s’appuyant sur JavaScript, comme Folium.

1.1 Données utilisées

Au cours de ce chapitre, nous allons utiliser plusieurs jeux de données pour illustrer différents types de cartes:

  • Des comptages de population ;
  • Les limites départementales de la France métropolitaine ;
  • Les limites communales du Finistère ;
  • Le couvert forestier du département des Landes ;
  • La localisation des stations Velib ;

1.2 Installations préalables

Avant de pouvoir commencer, il est nécessaire d’installer quelques packages au préalable:

# Sur colab
1!pip install pandas fiona shapely pyproj rtree geopandas
1
Ces librairies sont utiles pour l’analyse géospatiale (cf. chapitre dédié)

Nous allons principalement avoir besoin de Pandas et GeoPandas pour ce chapitre

import pandas as pd
import geopandas as gpd

2 Premières cartes pour connaître l’emprise spatiale de ses données

Nous allons utiliser cartiflette qui facilite la récupération des fonds de carte administratifs de l’IGN. Ce package est un projet interministériel visant à offrir une interface simple par le biais de Python pour récupérer des découpages officiels de l’IGN.

En premier lieu, nous allons récupérer les limites des départements:

from cartiflette import carti_download

departements = carti_download(
    values="France",
    crs=4326,
    borders="DEPARTEMENT",
    vectorfile_format="geojson",
    filter_by="FRANCE_ENTIERE_DROM_RAPPROCHES",
    source="EXPRESS-COG-CARTO-TERRITOIRE",
    year=2022,
)

Ces données rapprochent les DROM de la France hexagonale comme c’est expliqué dans l’un des tutoriels de cartiflette et comme l’exercice 1 permettra de le vérifier.

L’exercice 1 vise à s’assurer que nous avons bien récupéré les contours voulus en représentant simplement. Ceci devrait être le premier réflexe de tout geodata scientist.

Exercice 1: représentation des contours avec les méthodes de GeoPandas
  1. Utiliser la méthode plot sur le jeu de données departements pour vérifier l’emprise spatiale. Les coordonnées affichées vous évoquent quelle projection ? Vérifier avec la méthode crs.
  2. Reprojeter les données en Lambert 93 (EPSG: 2154) et faire la même carte.
  3. En utilisant les options matplotlib adéquates, représenter une carte avec les contours noirs, le fond blanc et sans axes.
  4. Faire la même carte pour les communes du Finistère

La carte des départements, sans modifier aucune option, ressemble à celle-ci

Les coordonnées affichées nous suggèrent du WGS84, ce qu’on peut vérifier avec la méthode CRS:

<Geographic 2D CRS: EPSG:4326>
Name: WGS 84
Axis Info [ellipsoidal]:
- Lat[north]: Geodetic latitude (degree)
- Lon[east]: Geodetic longitude (degree)
Area of Use:
- name: World.
- bounds: (-180.0, -90.0, 180.0, 90.0)
Datum: World Geodetic System 1984 ensemble
- Ellipsoid: WGS 84
- Prime Meridian: Greenwich

Si on fait la conversion en Lambert 93 (système légal pour l’hexagone), on obtient une emprise différente mais qui est censée être plus véridique pour la métropole (par pour les DROM rapprochés puisque, par exemple, la Guyane est en principe beaucoup plus grande).

Et bien sûr on retrouve facilement les cartes ratées du chapitre sur GeoPandas, par exemple si on applique une transformation prévue pour l’Amérique du Nord:

departements.to_crs(5070).plot()

Si on fait une carte un petit peu plus esthétique, cela nous donne:

Et la même pour le Finistère:

Ces cartes sont simples et pourtant elles font déjà appel à des connaissances implicites. Elles demandent déjà une connaissance du territoire. Quand nous commencerons à coloriser certains départements, savoir lesquels ont des valeurs extrêmes implique de bien connaître sa géographie française. De même, cela apparaît certes évident, mais rien ne dit dans notre carte du Finistère que ce département est bordé par l’océan. Un lecteur Français le verra comme une évidence mais ce n’est pas forcément le cas d’un lecteur étranger qui, bien sûr, ne connait pas le détail de notre géographie.

Pour cela, nous avons des parades grâce aux cartes réactives qui permettent:

  • D’afficher des informations contextuelles quand on passe la souris ou clique sur un élément de la carte.
  • D’afficher un fond de carte offrant des informations contextuelles comme les axes de transport, les localités ou les frontières naturelles.

Pour ceci, nous allons garder uniquement les données correspondant à une réelle emprise spatiale, ce qui exclut notre zoom de l’Ile de France et les DROM

1departements_no_duplicates = departements.drop_duplicates(subset="INSEE_DEP")
departements_hexagone = departements_no_duplicates.loc[
    ~departements["INSEE_DEP"].str.startswith("97")
2]
1
On retire le zoom sur l’Île de France
2
On ne garde que la France hexagonale

On obtient bien l’hexagone:

departements_hexagone.plot()

Pour le prochain exerice, nous allons avoir besoin de quelques variables supplémentaires. En premier lieu le centre géométrique de la France qui nous permettra de placer le centre de notre carte.

minx, miny, maxx, maxy = departements_hexagone.total_bounds
center = [(miny + maxy) / 2, (minx + maxx) / 2]

Nous allons aussi avoir besoin d’un dictionnaire pour renseigner à Folium des informations sur les paramètres de notre carte:

style_function = lambda x: {
1    "fillColor": "white",
    "color": "black",
    "weight": 1.5,
    "fillOpacity": 0.0,
}
1
En fait cela permettra d’avoir une couche transparente en combinant avec le paramètre fillOpacity à 0%.

style_function est une fonction anonyme qui sera utilisée dans l’exercice.

Une information qui s’affiche lorsqu’on passe la souris s’appelle un tooltip en langage de développement web.

import folium

tooltip = folium.GeoJsonTooltip(
    fields=["LIBELLE_DEPARTEMENT", "INSEE_DEP", "POPULATION"],
    aliases=["Département:", "Numéro:", "Population:"],
    localize=True,
)

Pour le prochain exercice, il faudra utiliser le GeoDataFrame dans la projection Mercator. En effet, Folium attend des données dans cette projection car cette librairie se base sur les fonds de carte de navigation, qui sont adaptés à cette représentation. En principe, on utilise plutôt Folium pour des représentations locales, où la déformation des surfaces induite par la projection Mercator n’est pas problématique. Pour le prochain exercice, où nous représenterons la France dans son ensemble, nous faisons donc un usage quelque peu détourné de la librairie. Mais la France étant encore assez lointaine du pôle nord, la déformation reste un prix à payer faible par rapport aux gains de l’interactivité.

Exercice 2: faire une première carte réactive avec Folium
  1. Créer la couche de fond en utilisant l’objet center et le niveau zoom_start égal à 5
  2. Mettre à jour celle-ci en utilisant notre departements_hexagone et les paramètres style_function et tooltip

Voici la couche de fond de la question 1:

Make this Notebook Trusted to load map: File -> Trust Notebook

Et une fois mise en forme, cela nous donne la carte:

Make this Notebook Trusted to load map: File -> Trust Notebook