Chapitre 12 Créer des cartes pour le web

12.1 Les cartes Leaflet

{leaflet} est une bibliothèque javascript de cartographie en ligne. R permet de produire des cartes en exploitant cette bibliothèque.

La limitation de {leaflet} est qu’il ne permet de visualiser que des données en projection WGS84.

Dans ce chapitre, nous utiliserons les packages suivants

# CRAN
library(htmltools)
library(htmlwidgets)
library(leaflet)
library(sf)
library(tidyverse)
# Github 
library(COGiter)    # remotes::install_github("MaelTheuliere/COGiter")
library(ggiraph)
# Gitlab-forge
library(mapfactory) # remotes::install_gitlab("dreal-pdl/csd/mapfactory", host = "gitlab-forge.din.developpement-durable.gouv.fr")

Les données utilisées sont celles issues de l’API de l’INSEE et préparées au chapitre 10, au niveau du paragraphe 10.4.1.

12.1.1 Carte choroplète

Ci-dessous un exemple avancé de carte choroplète avec {leaflet}.

  • Définition des données de départ :
pop_dep_geo <- pop_prepa_nat %>% 
  filter(TypeZone == "Départements") %>% 
  inner_join(COGiter::departements_metro_geo, ., by = c("DEP" = "CodeZone")) %>% 
  mutate(densite = PMUN / as.numeric(AREA) * 1000000) 

glimpse(pop_dep_geo)
Rows: 96
Columns: 11
$ DEP              <fct> 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 1…
$ AREA             [m^2] 5762900000 [m^2], 7361500000 [m^2], 7340000000 [m^2],…
$ geometry         <GEOMETRY [m]> POLYGON ((835167.2 6539004,..., POLYGON ((70…
$ TypeZone         <fct> Départements, Départements, Départements, Département…
$ Zone             <fct> "Ain", "Aisne", "Allier", "Alpes-de-Haute-Provence", …
$ TIME_PERIOD      <chr> "2023", "2023", "2023", "2023", "2023", "2023", "2023…
$ PCAP             <int> 15601, 11038, 8415, 4331, 4289, 14085, 8368, 5711, 39…
$ PMUN             <int> 679344, 523342, 333298, 168054, 143467, 1128418, 3342…
$ PTOT             <int> 694945, 534380, 341713, 172385, 147756, 1142503, 3425…
$ poids_pop_a_part <dbl> 2.244926, 2.065571, 2.462593, 2.512400, 2.902759, 1.2…
$ densite          <dbl> 117.88232, 71.09176, 45.40845, 24.26492, 25.85503, 26…
  • Transformation de la projection car leaflet ne connait que le WGS 84 :
pop_dep_geo <- st_transform(pop_dep_geo, crs=("+proj=longlat +datum=WGS84 +no_defs"))
  • Discrétisation de la variable d’intérêt :
bornes <- quantile(pop_dep_geo$densite, na.rm = TRUE)
  • Création d’une palette de couleurs associée :

{leaflet} intègre une fonction colorBin() qui permet d’associer à un vecteur de valeurs numériques un vecteur de couleurs en fonction d’une palette et d’un vecteur de bornes.

pal <- colorBin("YlOrRd", domain = pop_dep_geo$densite, bins = bornes)
  • Création d’étiquettes popover, à afficher en surbrillance au passage de la souris sur la carte :
popover <- sprintf("<strong>%s</strong><br/>%.1f habitants par km² en %s", 
                   pop_dep_geo$Zone, pop_dep_geo$densite, mil_pop) %>% 
  lapply(htmltools::HTML)
  • Réalisation de la carte :

La fonction addPolygons() permet de créer la carte choroplète.

La fonction addProviderTiles() permet de choisir un fond cartographique parmis les couches fournies par leaflet.

leaflet(pop_dep_geo) %>%
  addProviderTiles("GeoportailFrance.plan") %>% 
  addTiles() %>%
  addPolygons(data = pop_dep_geo,
              fillColor = ~pal(densite),
              weight = 2,
              opacity = 1,
              color = "white",
              dashArray = "3",
              fillOpacity = 0.7,
              highlight = highlightOptions(
                weight = 5,
                color = "#666",
                dashArray = "",
                fillOpacity = 0.7,
                bringToFront = TRUE),
              label = popover,
              labelOptions = labelOptions(
                style = list("font-weight" = "normal", padding = "3px 8px"),
                textsize = "15px",
                direction = "auto"))

12.1.2 Carte à ronds proportionnels

Pour réaliser des ronds proportionnels, il va faut partir des centroïdes de nos polygones. On cherche cette fois à représenter les populations 2015.

  • Création de la table en entrée :
dep_centr <- st_centroid(pop_dep_geo)
  • Discrétisation de la variable d’intérêt :
bornes <- quantile(dep_centr$PMUN / 1000, na.rm = TRUE)
  • Création d’une palette de couleurs associée :
pal <- colorBin("YlOrRd", domain = dep_centr$PMUN / 1000, bins = bornes)
  • Création d’un label ad-hoc à afficher en surbrillance au passage de la souris sur la carte :
popover <- sprintf("<strong>%s</strong><br/>%.1f milliers habitants en %s", 
                  dep_centr$Zone, dep_centr$PMUN / 1000, mil_pop) %>% 
  lapply(htmltools::HTML)
  • Création de la carte :
carte_rond_proportionnel <- leaflet(dep_centr) %>%
  addProviderTiles(providers$CartoDB.Positron) %>% 
  addCircles(data = dep_centr,
             fillColor = ~pal(PMUN / 1000),
             radius = ~2500*log(PMUN),
             weight = 2,
             opacity = 1,
             color = "gray",
             dashArray = "3",
             fillOpacity = 0.6,
             highlight = highlightOptions(
               weight = 5,
               color = "#666",
               dashArray = "",
               fillOpacity = 0.98,
               bringToFront = TRUE),
             label = popover,
             labelOptions = labelOptions(
               style = list("font-weight" = "normal", padding = "3px 8px"),
               textsize = "15px",
               direction = "auto")) %>% 
  addLegend("bottomright", pal = pal, values = ~PMUN,
            title = paste0("Nombre d'habitants en ", mil_pop, " - INSEE - RP"),
            opacity = 1)

carte_rond_proportionnel

12.2 Les cartes ggplot

Les cartes créées par {ggplot2}, comme tous les autres graphiques produits avec ggplot d’ailleurs, peuvent être rendues dynamiques grâce à {ggiraph} développé par David Gohel.

Ce package permet l’ajout d’info-bulles, des effets de survol et d’ajouter des actions JavaScript aux graphiques. L’interactivité est s’applique aux géométries ggplot, aux légendes et aux éléments de thème, grâce aux paramètres esthétiques suivants :

  • tooltip: info-bulles à afficher lorsque la souris se trouve sur les éléments ;
  • onclick: fonction JavaScript à exécuter lorsque les éléments sont cliqués ;
  • data_id: id à associer aux éléments (utilisé pour les actions de survol et de clic).

Les choses que vous devez savoir pour créer un graphique interactif :

  • Au lieu d’utiliser geom_sf(), utilisez geom_sf_interactive(), au lieu d’utiliser geom_sf_label(), utilisez geom_sf_label_interactive()… Fournissez au moins une des esthétiques tooltip, data_id and onclick pour créer des éléments interactifs.
  • Appelez la fonction girafe avec l’objet ggplot afin que le graphique soit traduit en un graphique web interactif.

Dans cet exemple, on réutilise les données issues de l’API de l’INSEE préparées au chapitre 10, au niveau du paragraphe 10.4.1.

On reprend notre carte ggplot normande en ronds proportionnels :

# On vérifie que la police Marianne est correctement installée.
verif_marianne_ok <- gouvdown::check_fonts_in_r(fonts = "Marianne")
if(!verif_marianne_ok) {
  systemfonts::register_font(name = "Marianne light", 
                             system.file("resources/fonts/marianne/truetype/Marianne-Light.ttf", 
                                         package = "gouvdown.fonts")) 
  systemfonts::register_font(name = "Marianne", 
                             system.file("resources/fonts/marianne/truetype/Marianne-Regular.ttf", 
                                         package = "gouvdown.fonts")) 
}
carte_ronds_prop_dyn <- ggplot(data = pop_epci_normands_geo) +
    geom_sf_interactive(aes(tooltip = Zone)) +
    geom_sf_interactive(data = st_point_on_surface(pop_epci_normands_geo), 
                        mapping = aes(size = PTOT, color = poids_pop_a_part, 
                                      tooltip = paste0(Zone, "\n", format_fr_nb(PTOT, dec = 0, big_mark = " "), " hab.\ndont ", 
                                                       format_fr_nb(poids_pop_a_part, dec = 1, big_mark = " "), " % comptés à part"))) +
    labs(
        title = "Population par EPCI en Normandie",
        subtitle = paste0("En ", mil_pop), x = "", y = "",
        size = "Nombre d'habitants",
        color = "Poids population\ncomptée à part (%)",
        caption = "Source : INSEE - RP"
    )  +
    theme_gouv_map(plot_title_size = 20, subtitle_size = 12) +
    scale_color_gouv_continuous(palette = "pal_gouv_i", reverse = TRUE) +
    scale_size_continuous(labels = function(x) format(x, big.mark = " ", scientific = FALSE))  +
    annotation_north_arrow(location = "bl", height = unit(0.7, "cm"), width = unit(0.7, "cm"))

girafe(ggobj = carte_ronds_prop_dyn)

12.3 Les cartes {mapfactory}

{mapfactory} s’appuie sur {ggiraph} pour rendre ses cartes dynamiques. Les arguments de la fonction creer_carte() en rapport avec l’interactivité sont :

interactive
TRUE si on veut une carte html interactive.

popover
Chaîne de texte désignant le contenu de l’info-bulles. Par défaut, L’étiquette qui s’affiche au survol contient nom du territoire : valeur de l'indicateur et suffixe, obtenu a partir de ".data$nom_ter : .data$valeur".
valeur est la colonne qui contient les valeurs de l’indicateur représenté sur la carte.

indicateur_popover
On renseigne ici un autre nom d’indicateur présent dans le jeu de données (sans quote), pour le mobiliser dans le popover. Utiliser .data$valeur_popover au niveau du parametre popover pour afficher les valeurs de cet indicateur, par exemple .data$nom_ter : .data$valeur_popover unites.

creer_carte(data = pop_prepa_nat, code_region = "52", indicateur = PMUN, espace = " ",
            interactive = TRUE, type_viz = "proportionnel", maillage = "Epci", 
            titre = "Population par EPCI en Pays de la Loire", 
            bas_de_page = paste0("Source RP - INSEE ", mil_pop))

12.4 Exporter une sortie html

La fonction saveWidget() permet d’exporter une sortie d’un HTML Widget en fichier HTML.

saveWidget(widget = girafe(ggobj = carte_ronds_prop_dyn), file = "part_pop_a_part_epci_normandie.html")

12.5 Exercice 5 : cartes DVF pour le web

Adapter la carte régionale à l’EPCI de l’exercice 4, pour le web :

  • au survol d’un EPCI, afficher son nom, le prix au m2 et son évolution 2014-2017,
  • au survol du rond d’un EPCI, afficher son nom, le nb de ventes 2017.
Scanning ttf files in /usr/local/lib/R/site-library/gouvdown.fonts/resources/fonts/marianne/truetype ...
Extracting .afm files from .ttf files...
/usr/local/lib/R/site-library/gouvdown.fonts/resources/fonts/marianne/truetype/Marianne-Bold.ttf => /usr/local/lib/R/site-library/extrafontdb/metrics/Marianne-Bold
/usr/local/lib/R/site-library/gouvdown.fonts/resources/fonts/marianne/truetype/Marianne-ExtraBold.ttf => /usr/local/lib/R/site-library/extrafontdb/metrics/Marianne-ExtraBold
/usr/local/lib/R/site-library/gouvdown.fonts/resources/fonts/marianne/truetype/Marianne-Light.ttf => /usr/local/lib/R/site-library/extrafontdb/metrics/Marianne-Light
/usr/local/lib/R/site-library/gouvdown.fonts/resources/fonts/marianne/truetype/Marianne-Regular.ttf => /usr/local/lib/R/site-library/extrafontdb/metrics/Marianne-Regular
Found FontName for 4 fonts.
Scanning afm files in /usr/local/lib/R/site-library/extrafontdb/metrics
Writing font table in /usr/local/lib/R/site-library/extrafontdb/fontmap/fonttable.csv
Writing Fontmap to /usr/local/lib/R/site-library/extrafontdb/fontmap/Fontmap...