Premiers pas en cartographie avec R

Cartographie
Fond de carte
Auteur·rice
Affiliation

Bénédicte Garnier

Ined

Date de publication

26 août 2024

Résumé

Le package mapsf permet de générer des cartes simplement. Toutefois, il convient de choisir le type de carte adaptés aux données à représenter et parfois adapter le fond de carte. Nous présentons ici des statistiques sur les arrondissements de Paris.

Adaptation de la fiche Mapsf de Coralie Cottet (2023).

Les étapes pour représenter des indicateurs simples sur une fond de carte

Importer dans R - le fond de carte des arrondissements de Paris (données géométriques) - le tableau des indicateurs à représenter (données attributaires)
Utiliser le package mapsf - choisir le type de carte adapté aux données à représenter. - habiller la carte (titre, légende, ..) - exporter la carte produite au format désiré (vectoriel ou image)

Packages Fonctions
sf st_read ,st_union
mapsfr mf_map
mapsfr mf_theme
mapsfr mf_label
mapsfr mf_title

Si nécessaire, installation des packages avec la commande install.packages("mapsf","sf","dplyr")

Appel des packages

Linking to GEOS 3.12.1, GDAL 3.8.4, PROJ 9.3.1; sf_use_s2() is TRUE

Attachement du package : 'dplyr'
Les objets suivants sont masqués depuis 'package:stats':

    filter, lag
Les objets suivants sont masqués depuis 'package:base':

    intersect, setdiff, setequal, union

Les données

Les données géométriques

Les formats les plus courants en cartographie automatique sont :

  • GeoJSON, basé sur JSON (JavaScript Object Notation) qui permet de stocker des données géographiques sous forme de caractères.
  • Shapefile, plus ancien, développé par Esri. c’est un ensemble de fichiers qui stockent des informations sur les entités géographiques et leurs attributs.

Le fond de carte utilisé ici correspond aux limites des arrondissements de Paris, il est au format GeoJSON. On va lui ajouter les voies d’eau (Seine et canaux). On importe ces 2 couches à partir du site opendata.paris.fr.

arrondissements <- st_read(dsn = "https://opendata.paris.fr/explore/dataset/arrondissements/download/?format=geojson&timezone=Europe/Berlin&lang=fr")
Reading layer `OGRGeoJSON' from data source 
  `https://opendata.paris.fr/explore/dataset/arrondissements/download/?format=geojson&timezone=Europe/Berlin&lang=fr' 
  using driver `GeoJSON'
Simple feature collection with 20 features and 9 fields
Geometry type: POLYGON
Dimension:     XY
Bounding box:  xmin: 2.224078 ymin: 48.81558 xmax: 2.469761 ymax: 48.90216
Geodetic CRS:  WGS 84
cours_deau<-st_read(dsn="https://opendata.paris.fr/api/explore/v2.1/catalog/datasets/plan-de-voirie-voies-deau/exports/geojson?lang=fr&timezone=Europe%2FBerlin")
Reading layer `OGRGeoJSON' from data source 
  `https://opendata.paris.fr/api/explore/v2.1/catalog/datasets/plan-de-voirie-voies-deau/exports/geojson?lang=fr&timezone=Europe%2FBerlin' 
  using driver `GeoJSON'
Simple feature collection with 58 features and 25 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 2.224081 ymin: 48.81924 xmax: 2.450555 ymax: 48.90207
Geodetic CRS:  WGS 84

Affichage des contours des arrondissements et des cours d’eau à Paris

On superpose 3 couches différentes : les polygones représentant les contours des arrondissements, les numéro des arrondissements et les cours d’eau.

mf_theme("candy")
# Arrondissements
mf_map(x = arrondissements, border = "black") 

# plot labels
mf_label(
  x = arrondissements,
  var = "c_ar",
  col = "black",
  cex = 0.8,
)

# Ajout des cours d'eau
mf_map(x=cours_deau,lwd=2,border="lightblue",col="lightblue",add=TRUE)

mf_title("Les arrondissements de Paris")

Les indicateurs à représenter et le choix du type de carte

Le tableau suivant contient les identifiants des arrondissements de Paris, les bords politiques des élus aux élections municipales de 2020 et les effectifs des populations de ces arrondissements.
Sources :
- Le parisien du 29-06-2020
- Insee - Chiffres détaillés, Comparateur de territoires - Mise en ligne le 27/06/2024.

Codgeo Libelle Municipalités Population en 2021
75101 Paris 1er Arrondissement PS, EELV 15919
75102 Paris 2e Arrondissement PS, EELV 21119
75103 Paris 3e Arrondissement PS, EELV 32793
75104 Paris 4e Arrondissement PS, EELV 28324
75105 Paris 5e Arrondissement LR, LREM 56841
75106 Paris 6e Arrondissement LR 40209
75107 Paris 7e Arrondissement LR 47947
75108 Paris 8e Arrondissement LR 35123
75109 Paris 9e Arrondissement LREM 58951
75110 Paris 10e Arrondissement PS, EELV 83543
75111 Paris 11e Arrondissement PS, EELV 142583
75112 Paris 12e Arrondissement PS, EELV 140954
75113 Paris 13e Arrondissement PS, EELV 178350
75114 Paris 14e Arrondissement PS, EELV 136368
75115 Paris 15e Arrondissement LR 227746
75116 Paris 16e Arrondissement LR 162061
75117 Paris 17e Arrondissement LR 164413
75118 Paris 18e Arrondissement PS, EELV 188446
75119 Paris 19e Arrondissement PS, EELV 181616
75120 Paris 20e Arrondissement PS, EELV 189805

Les 4 premiers arrondissements ont été regroupés en une seule entité dans le cadre des élections municipales (étiquette PS, EELV). Nous verrons plus loin comment modifier le fond de carte pour représenter cette information sur une carte.

Identifier le type de donnée à représenter car cela va conditionner le type de carte à utiliser

cf T. Giraud

cf T. Giraud

Nous disposons donc d’une variable de stock : la population des arrondissements, d’une variable qualitative nominale : le bord politique de la mairie et nous pourrons calculer une variable quantitative absolue : la densité de population de chaque arrondissement car nous avons la superficie de chaque arrondissement (st_area) dans le data frame correspondant au fond de carte.

Générer des cartes adaptées aux données

La population par arrondissements

#Tri de la table des arrondissements selon leur numéro
arrondissements2 = arrondissements %>% arrange(c_arinsee)

#Ajout des valeurs des populations de chaque arrondissements dans une nouvelle colonne nommée "population"
arrondissements2$population <- c(15919, 21119, 32793, 28324, 56841, 40209, 47947, 35123, 58951, 83543, 142583, 140954, 178350, 136368, 227746, 162061, 164413, 188446, 181616, 189805) 
#La valeur 15919 correspond à la population dans le 1er arrondissement.

On affiche une carte en symboles proportionnels car c’est la méthode à utiliser pour visualiser des variables de stocks. La surface des cercles représente l’effectif de la population pour chaque arrondissement.

La fonction map_sf() sert à indiquer la variable à représenter (var=population), et le type de carte (type=prop).

On habille la carte en y ajoutant une légende et un titre

mf_map(x = arrondissements2)
mf_map(
  x = arrondissements2,
  var = "population" ,
  type = "prop",  
  leg_title = "Effectif de la population\ en 2021",
  col="#C24168",
  add= TRUE,
  inches=0.2)

mf_title("La population des arrondissements de Paris")

La densité de population de chaque arrondissement

# calcul de la densité de population par arrondissements  
arrondissements2$densite <- 1e6 * arrondissements2$population / as.numeric(st_area(arrondissements2))

On va ici générer une carte choroplèthe (ou en aplat de couleur) car c’est la méthode à utiliser pour visualiser des ratios (variables quantitatives relatives).

On utilise la méthode des quantiles pour discrétiser la variable densite, et on applique une palette de couleurs séquentielles avec dégradé pour représenter l’ordre entre les valeurs.

mf_map(
  x = arrondissements2,
# variable à représenter: densité de population  
var = "densite",
# type de carte  
type = "choro",
# méthode de dsicrétisation
  breaks = "quantile",
# palette de rouges  
pal = "Reds",
  lwd = 1,
  leg_title = "Densité de population\n(habitants par km2)", 
  leg_val_rnd = 0
)

mf_title("Les densités de population des arrondissements de Paris")

Nota Bene : Les 12e et 16e arrondissements sont très eu denses car sont composés des bois de Vincenne et de Boulogne.

Le “bord politique” des mairies

Pour les élections municipales de 2020, les 4 premiers arrondissements de la ville ont été fusionnés dans une zone appelée Centre, et le choix de la localisation de mairie s’est porté sur le 3ème arrondissement. Nous devons créer un nouveau fond de carte où on fusionne les 4 polygones correspondants à ces 4 arrondissements avec la fonction st_union.

# Louvre  
poly1 = arrondissements2[arrondissements2$c_ar == "1", ] 
# Bourse
poly2 = arrondissements2[arrondissements2$c_ar == "2", ]
# Temple
poly3 = arrondissements2[arrondissements2$c_ar == "3", ]
# Hôtel de Ville
poly4 = arrondissements2[arrondissements2$c_ar == "4", ]
# Fusion des polygones
poly12   = st_union(poly1,poly2) 
Warning: attribute variables are assumed to be spatially constant throughout
all geometries
poly34   = st_union(poly3,poly4)
Warning: attribute variables are assumed to be spatially constant throughout
all geometries
centre = st_union(poly12,poly34)
Warning: attribute variables are assumed to be spatially constant throughout
all geometries
centre$l_aroff = "Centre" # changer le nom de l'arrondissement
centre$c_ar    =  "3"     # On prend le code qui correspond au 3e arrondissement

# On garde les arrondissemnts qui ne sont pas au centre

arrondissementsp <- arrondissements2 %>%
  filter(c_ar > 4) %>%
  select(c_ar, l_aroff, surface, l_ar, n_sq_co, c_arinsee, n_sq_ar, perimetre, geom_x_y, geometry)

centre_fus = subset(centre, select = c(c_ar, l_aroff,surface, l_ar, n_sq_co, c_arinsee, n_sq_ar, perimetre, geom_x_y, geometry))


# Combiner les data frames et sélectionner les colonnes en une seule étape
arrondissementsnew = rbind(centre_fus, arrondissementsp) %>%
  select(c_ar, l_aroff, geom_x_y, geometry)

mf_map(x = arrondissementsnew,border= "black")
mf_title("Le découpage des municipalités de Paris")

On va représenter cette variable de type qualitative nominale (ici bords politiques des mairies de chaque arrondissement), par un symbole de couleur sans dégradé (palette qualitative).

arrondissementsnew$bords_politiques <- c("PS, EELV", "LR, LREM", "LR", "LR", "LR", "LREM", "PS, EELV", "PS, EELV", "PS, EELV", "PS, EELV", "PS, EELV", "LR", "LR", "LR", "PS, EELV", "PS, EELV", "PS, EELV")

# Choix des couleurs

levels(as.factor(arrondissementsnew$bords_politiques))
[1] "LR"       "LR, LREM" "LREM"     "PS, EELV"
# PS, EELV en "#d175b8", LR, LREM en "#8856a7", LR en "#3182bd" et LREM en "#e6550d"
colors <- c("#3182bd", "#1c9099", "#e6550d","#c51b8a")

# Placer les carrés sur les centroïdes des polygones des arrondissements.
arr_c<-st_centroid(arrondissementsnew)
Warning: st_centroid assumes attributes are constant over geometries
mf_map(x = arrondissementsnew, border = "black")

# Choix  du symbol rectangle (pch=15)
mf_map(
  x = arr_c,
  var = "bords_politiques",
  pal=colors,
  type="symb",
  pch=15,
  cex = 2,
  lwd = .5,
  leg_title = "",
  border="black"
)
the length of pch does not match the number of modalities. The first pch is used for all modalities
# habillage 
mf_layout(
  title = "Bords politiques aux élections municipales de 2020",
  credits = paste0("mapsf ", packageVersion("mapsf")),
  arrow = FALSE,  # Désactiver l'orientation
  scale = FALSE  # Désactiver l'échelle
)

Il est plus courant de représenter les cartes électorales par des cartes chloroplèthe. Ainsi par rapport à la carte précédente, il faut utiliser type="typo" et de retirer l’argument pch. On ajoute également le numéro de l’arrondissement avec la fonction mf_label.

mf_map(
  x = arrondissementsnew,
  # var à représenter  
  var = "bords_politiques",
  pal=colors,
  type="typo",
  cex = 2,
  lwd = .5,
  leg_title = "",
  leg_pos= c(2.43, 48.91396),
  border="black"
)

mf_layout(
  title = "Bords politiques aux élections municipales de 2020",
  credits = paste0("mapsf ", packageVersion("mapsf")),
  arrow = FALSE,  # Désactiver l'orientation
  scale = FALSE   # Désactiver l'échelle
  )

mf_label(
  x = arrondissementsnew, var = "c_ar", col = "grey", halo = FALSE, overlap = FALSE, lines = FALSE,
)

# Ajout des cours d'eau
mf_map(x=cours_deau,lwd=2,border="lightblue",col="lightblue",add=TRUE)

Exporter les cartes

Au format image

# export en format image (.png)
mf_export( 
  x= arrondissementsnew,
  filename ="img/carte.png", width = 600)
mf_map(x = arrondissementsnew)
mf_map(
  x = arrondissementsnew,
   var = "population" ,
  type = "prop",   
  leg_title = "Population des arrondissements",
  col="#C24168",
  add= TRUE,
  inches=0.2)
mf_arrow()
mf_credits (txt = "Fait avec mapsf de T. Giraud",pos = "bottomright",font = 2)
mf_title(txt = "Ma carte")
dev.off()
Attention

Toujours utiliser add = TRUE après un appel à mf_export() et ne pas oublier d’utiliser dev.off() pour finaliser l’export de la figure.

Au format vectoriel

# format vectoriel (.svg)
mf_export( 
  x= arrondissementsnew,
  filename ="img/carte.svg", width = 600)
mf_map(x = arrondissementsnew)
mf_map(
  x = arrondisst4,
   var = "population" ,
  type = "prop",   
  leg_title = "Population des arrondissements",
  col="#C24168",
  add= TRUE,
  inches=0.2)
mf_arrow()
mf_credits (txt = "Fait avec mapsf de T. Giraud",pos = "bottomright",font = 2)
mf_title(txt = "Ma carte")
dev.off()
En savoir plus