Dessiner des cartes comme des peintures

Peindre des cartes : le contexte

Sur la Slack Grrr, une Slack d’entraide francophone sur R, Thomas Vroylandt nous a montré les cartes ci-dessous en demandant si c’était possible de les faire avec {ggplot2} :

EDIT : Ces cartes viennent à l’origine du site web visionscarto.net avec des oeuvres d’Agnès Stienne

Romain Lesur a rappelé cette belle librairie R disponible sur Github : ggpomological.

J’ai trouvé ces cartes très jolies. Comme j’aime dessiner des cartes - je dessinais d’ailleurs des cartes régionales françaises pour préparer un tutoriel - j’ai décidé de prendre quelques minutes pour installer la bibliothèque et changer l’apparence de mes cartes.

Librairies nécessaires

À ce jour (2018-04-18):

  • Vous avez besoin de la version en développement de {ggplot2} pour dessiner des cartes avec geom_sf.
  • Le package {ggpomological} est seulement sur github.
  • Vous aurez aussi besoin de ma version très légèrement modifiée de {ggsn} (“font-family” branch) si vous voulez ajouter votre propre police dans scalebar. EDIT: La librairie {ggsn} a été mise à jour

Pour un look “pomologique” authentique, vous devrez installer {magick} et une police de caractère de type “écriture manuelle”. Garrick Aden-Buie en propose quelques-unes sur Google Fonts :

J’aime aussi celles-ci :

Je vous laisse trouver par vous-même la meilleure manière d’ajouter une nouvelle police à votre OS et comment la rendre disponible dans R. Vous aurez probablement besoin de extrafont::font_import().

# devtools::install_github("tidyverse/ggplot2")
library(ggplot2)
# devtools::install_github("gadenbuie/ggpomological")
library(ggpomological)
library(scales)
library(readr)
library(sf)
library(dplyr)
library(grid)
# devtools::install_github("statnmap/ggsn", ref="font-family")
library(ggsn)
library(units)
library(extrafont)
# extrafont::font_import()

Peindre une première carte

Récupérons des données, une carte, évidemment ! Je travaille actuellement sur une carte des régions françaises avec la répartition de la population par classes d’âge.
Vous pouvez télécharger les données sur mon dépôt Github ‘Blog tips’.

# extraWD <- "."
if (!file.exists(file.path(extraWD, "Region_L93.rds"))) {
  githubURL <- "https://github.com/statnmap/blog_tips/raw/master/2018-04-18-draw-maps-like-paintings/Region_L93.rds"
  download.file(githubURL, file.path(extraWD, "Region_L93.rds"))
}
Region_L93 <- read_rds(file.path(extraWD, "Region_L93.rds"))

On représente le nombre de personnes qui avaient moins de 20 ans en 2015 par région.

ggplot() +
  geom_sf(data = Region_L93,
          aes(fill = Age_0.19.ans), alpha = 0.75, colour = NA
  ) +
  geom_sf(data = Region_L93,
          aes(colour = Age_0.19.ans), alpha = 1, fill = NA
  ) +
  scale_fill_gradient(
    "Youngs (< 20y)",
    low = muted(ggpomological:::pomological_palette[2], l = 90, c = 70),
    high = ggpomological:::pomological_palette[2]
  ) +
  scale_colour_gradient(
    low = muted(ggpomological:::pomological_palette[2], l = 90, c = 70),
    high = ggpomological:::pomological_palette[2],
    guide = FALSE
  ) +
  theme_pomological_fancy(base_family = "Homemade Apple")

Changer la famille de polices dans le thème {ggplot2}.

Si vous avez téléchargé la police “NanumPenScript”, nous pouvons continuer. Nous changeons les valeurs représentées en nombre par km², ce qui est plus pertinent pour des comparaisons entre régions. Nous modifions un peu la palette de couleurs, ajoutons le titre et la source.

Region_Prop_L93 <- Region_L93 %>%
  mutate(area_km2 = st_area(.) %>% set_units(km^2) %>% drop_units()) %>%
  mutate(Prop_20_km2 = `Age_0.19.ans` / area_km2)

ggplot() +
  geom_sf(data = Region_Prop_L93,
          aes(fill = Prop_20_km2), alpha = 0.9, colour = NA
  ) +
  geom_sf(data = Region_Prop_L93,
          aes(colour = Prop_20_km2), alpha = 1, fill = NA
  ) +
  scale_fill_gradient(
    "Youngs / km²",
    low = muted(ggpomological:::pomological_palette[2], l = 100, c = 70),
    high = muted(ggpomological:::pomological_palette[2], l = 50, c = 70),
    trans = "log"
  ) +
  scale_colour_gradient(
    low = muted(ggpomological:::pomological_palette[2], l = 80, c = 70),
    high = muted(ggpomological:::pomological_palette[2], l = 50, c = 70),
    guide = FALSE
  ) +
  theme_pomological_fancy(base_family = "Nanum Pen") +
  labs(
    title = "Number of people aged below 20 by km² in 2015",
    caption = "source: http://www.ecosante.fr/"
  )

Ajouter toutes les informations nécessaires sur la carte

Ajoutons quelques coordonnées de villes. On crée une couche spatiale avec son système de coordonnées.
Ajoutons le nord et la barre d’échelle. Je ne sais pas quand nous avons arrêté d’ajouter le Nord et la barre d’échelle sur les cartes, mais j’ai appris à ne jamais les oublier. {ggsn} nous aide à le faire avec {ggplot2}. Nous devrions également ajouter des informations sur la projection affichée.
Bon à savoir : Pour ajouter du geom_text sur une carte avec des données {sf}, il peut être nécessaire que les coordonnées du texte soient dans le même système de coordonnées que la projection de la figure. Nous allons donc projeter la couche “Régions” en Lambert93 (EPSG : 2154).

# Add cities and project in Lambert93
cities_L93 <- tibble(
  city = c("Paris", "Rennes", "Lille", "Strasbourg", "Brest", "Bordeaux",
    "Montpellier", "Nice", "lyon"),
  lat = c(48.857256, 48.110867, 50.625291, 48.576816, 48.384679, 44.843019,
          43.609519, 43.694233, 45.749206),
  long = c(2.344655, -1.678327, 3.057288, 7.754883, -4.498229, -0.581680,
           3.877594, 7.245262, 4.847652)
) %>%
  st_as_sf(coords = c("long", "lat")) %>%
  st_set_crs(4326) %>%
  st_transform(2154) %>% 
  bind_cols(st_coordinates(.) %>% as.data.frame())

# Plot
ggplot(Region_Prop_L93) +
  geom_sf(data = Region_Prop_L93,
          aes(fill = Prop_20_km2), alpha = 0.9, colour = NA
  ) +
  geom_sf(data = Region_Prop_L93,
          aes(colour = Prop_20_km2), alpha = 1, fill = NA
  ) +
  geom_sf(data = cities_L93, colour = "grey30") +
  geom_text(
    data = cities_L93, aes(X, Y, label = city), nudge_y = 20000,
    family = "Nanum Pen", colour = "grey20", size = 6
  ) +
  scale_fill_gradient("Youngs / km²",
    low = muted(ggpomological:::pomological_palette[2], l = 100, c = 70),
    high = muted(ggpomological:::pomological_palette[2],l = 50, c = 70),
    trans = "log"
  ) +
  scale_colour_gradient(
    low = muted(ggpomological:::pomological_palette[2],l = 80, c = 70),
    high = muted(ggpomological:::pomological_palette[2],l = 50, c = 70),
    guide = FALSE
  ) +
  theme_pomological_fancy(base_family = "Nanum Pen") +
  labs(
    title = "Number of people aged below 20 by km² in 2015",
    caption = "source: http://www.ecosante.fr/\nproj: Lambert93, epsg: 2154 aut.: S. Rochette, ThinkR."
  ) +
  xlab("") + ylab("") +
  north(Region_Prop_L93, symbol = 4, scale = 0.1) +
  scalebar(Region_Prop_L93, location = "bottomleft", dist = 200, dd2km = FALSE,
           model = "WGS84", box.fill = c("grey30", "white"), 
           box.color = "grey30", st.color = "grey30", family = "Nanum Pen"
  ) +
  theme(text = element_text(family = "Nanum Pen")) +
  coord_sf(crs = 2154)

Une autre carte avec des données catégorielles

La librairie {ggpomological} a d’abord été conçue pour les données catégorielles. On va utiliser sa palette de couleurs avec les régions. Comme il y a plus de régions que de couleurs dans de la palette, nous allons en répéter quelques-unes.

# palette
cols <- rep(ggpomological:::pomological_palette,
  length.out = length(Region_Prop_L93$NOM_REG))

ggplot(Region_Prop_L93) +
  geom_sf(
    data = Region_Prop_L93,
    aes(fill = NOM_REG),
    alpha = 0.9, colour = NA
  ) +
  geom_sf(
    data = Region_Prop_L93,
    aes(colour = NOM_REG),
    alpha = 1, fill = NA
  ) +
  geom_sf(data = cities_L93, colour = "grey30") +
  geom_text(
    data = cities_L93, aes(X, Y, label = city),
    nudge_y = 20000, family = "Nanum Pen",
    colour = "grey20", size = 6
  ) +
  scale_fill_manual(
    "Regions",
    values = muted(cols, l = 60, c = 70)
  ) +
  scale_colour_manual(
    values = muted(cols, l = 40, c = 70),
    guide = FALSE
  ) +
  theme_pomological_fancy(base_family = "Nanum Pen") +
  labs(
    title = "French regions",
    caption = "source: https://www.ign.fr/\nproj: Lambert93, epsg: 2154 aut.: S. Rochette, ThinkR."
  ) +
  xlab("") + ylab("") +
  north(Region_Prop_L93, symbol = 4, scale = 0.1) +
  scalebar(
    Region_Prop_L93,
    location = "bottomleft", dist = 200,
    dd2km = FALSE, model = "WGS84",
    box.fill = c("grey30", "white"), box.color = "grey30",
    st.color = "grey30", family = "Nanum Pen"
  ) +
  theme(text = element_text(family = "Nanum Pen")) +
  coord_sf(crs = 2154)

EDIT : La librairie {ggsn} a été mise à jour suite à mes propositions. Il est maintenant possible d’afficher échelle et Nord sur une carte projetée avec {ggplot2}. J’ai donc tout projeté en Lambert93.

Le script R de cet article est disponible sur mon dépôt Github ‘blog tips’

comments powered by Disqus