Cartes web
WebMap (dans cartograpy.mapper) couvre les usages interactifs à partir d’un GeoDataFrame. Trois moteurs au choix : Folium/Leaflet par défaut (jeu de fonctionnalités complet), ou deux moteurs GPU (deck.gl) pour les gros volumes : lonboard et kepler.gl.
Créer une carte
from cartograpy.mapper import WebMap
wm = WebMap(location=(5.35, -4.0), zoom_start=7, tiles="OpenStreetMap")tiles(str, défautOpenStreetMap) : Fond de carte :"OpenStreetMap","CartoDB positron","Stamen Terrain", etc. (tout fond supporté par Folium).
WebMap nécessite folium, lonboard et keplergl, qui ne sont pas dans les dépendances cœur de cartograpy : pip install cartograpy[webmap] installe les trois d’un coup (avec rio-tiler, requis par add_cog/add_raster, et pyarrow, requis par lonboard). Sous Python 3.13+, keplergl n’est pas installé (aucun wheel publié) : le moteur kepler.gl y est indisponible. Un moteur non installé lève une ImportError explicite à la construction de WebMap(engine=...).
Millions d’entités : lonboard et kepler.gl
Folium/Leaflet ralentit nettement au-delà de quelques dizaines de milliers d’entités (rendu DOM/SVG côté navigateur). Pour de gros volumes vectoriels, engine="lonboard" délègue le rendu au GPU via deck.gl/GeoArrow :
wm = WebMap(engine="lonboard")
wm.add_layer(gros_gdf) # des millions de points/polygones, rendu GPU
wm.add_basemap("positron") # style lonboard.basemap.CartoStyle
wm.save("carte_gpu.html")engine="kepler.gl" (aussi deck.gl) apporte en plus une interface intégrée type « studio » (filtres, styles, détection automatique des colonnes temporelles) :
wm = WebMap(engine="kepler.gl")
wm.add_layer(gros_gdf, name="Points")
wm.save("carte_kepler.html")Les deux moteurs GPU ne couvrent que add_layer/add_geojson/fit_bounds (add_basemap en plus pour lonboard) : les contrôles Leaflet (mesure, dessin, légende statique, plein écran…), add_heatmap, add_cluster, split() et time_slider() restent spécifiques à engine="folium" et lèvent un NotImplementedError explicite sur les deux autres moteurs.
Ajouter une couche vectorielle
wm.add_layer(regions_gdf, column="densite", cmap="YlOrRd",
tooltip_columns=["nom", "densite"], name="Densité")Sans column, la couche est affichée avec un style uni plutôt qu’une choroplèthe :
wm.add_layer(routes_gdf, name="Routes")add_layer reprojette automatiquement en EPSG:4326 si la couche est dans un autre CRS : Folium/Leaflet n’acceptent que WGS 84.
Marqueurs, clusters et chaleur (folium)
wm.add_marker((5.35, -4.0), popup="Abidjan", tooltip="Cliquez pour plus d'infos")
wm.add_cluster(ecoles_gdf, popup_columns=["nom"]) # marqueurs groupés
wm.add_heatmap(incidents_gdf, weight_column="gravite") # carte de chaleurFonds de carte, WMS et raster (add_cog)
wm.add_basemap("CartoDB positron", name="Carto")
wm.add_xyz("https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png", attr="OpenTopoMap")
wm.add_wms("https://ahocevar.com/geoserver/wms", layers="topp:states")
# Raster local ou COG distant, lu via rio-tiler (jamais de téléchargement complet)
wm.add_cog("https://.../landcover.tif", cmap="terrain")
wm.add_raster("data/elevation.tif", cmap="viridis", vmin=0, vmax=1500)add_cog/add_raster lisent un aperçu décimé (max_size, défaut 1024 px) directement depuis le fichier via rio-tiler : même sur une scène Sentinel de plusieurs centaines de Mo hébergée à distance, seul cet aperçu est transféré. cmap accepte les noms de rio_tiler.colormap.cmap.list() (palettes matplotlib + ColorBrewer).
Légende, colorbar et contrôles (folium)
wm.add_legend({"Faible": "green", "Élevé": "red"}, title="Densité")
wm.add_colorbar(0, 100, cmap="YlOrRd", caption="Densité (hab/km²)")
wm.add_layer_control() # bouton d'activation/désactivation des couches
wm.add_measure_control() # outil de mesure distance/surface
wm.add_draw_control() # dessin/édition
wm.add_fullscreen() # bouton plein écran
wm.fit_bounds(regions_gdf) # zoome automatiquement sur l'emprise d'une coucheComparaison côte à côte et animation temporelle (folium)
wm.split(left=occupation_2015, right=occupation_2025,
left_name="2015", right_name="2025")wm.time_slider(detections_gdf, time_column="date")time_slider attend une ligne par (entité, date) : voir Reference mapper pour le détail des paramètres.
Toutes les méthodes se chaînent
wm = (
WebMap(location=(5.35, -4.0), zoom_start=7)
.add_layer(regions_gdf, column="densite", name="Densité")
.add_marker((5.35, -4.0), popup="Abidjan")
.add_layer_control()
)Afficher et exporter
wm.show() # affichage automatique dans un notebook Jupyter/Marimo
wm.save("carte.html") # export HTML autonomeLimites face à Map
Map |
WebMap (folium) |
WebMap (lonboard/kepler.gl) |
|
|---|---|---|---|
| Rendu | statique (PNG, PDF, export papier) | interactif (HTML, zoom/pan navigateur) | interactif, rendu GPU |
| Légende, échelle, flèche du Nord | oui, gérées en détail | légende/colorbar statiques ; pas d’échelle/flèche du Nord | non (kepler.gl a sa propre UI) |
| Volumes de données | adapté aux gros jeux de données | à limiter : de gros GeoJSON ralentissent le navigateur | adapté aux gros volumes (millions d’entités) |
| Distribution | image/PDF à insérer dans un document | fichier HTML autonome, partageable tel quel | fichier HTML autonome (plus volumineux) |
Pour de gros volumes sur engine="folium" (plusieurs dizaines de milliers d’entités), simplifiez la géométrie avant add_layer (VectorTools(gdf).simplify_geometry(tolerance=...)), ou passez à engine="lonboard"/"kepler.gl" plutôt que de forcer Leaflet.
Aller plus loin
- Cartes statiques : l’équivalent pour l’export image/PDF
- Reference mapper : signatures complètes