Le nouveau rideau de fer
Un exemple de carte en 2,5D
Introduction
Ce document montre comment réaliser cette carte de discontinuités en 2,5D (fausse 3D) joliment mise en page avec R. Des versions antérieures de cette carte ont déjà été publiées, dans le Manuel de cartographie (Lambert, Zanin 2016), ou dans Mad Maps (Lambert, Zanin 2019) et ont fait l’objet de billets de blog (Lambert 2017). Ici, nous entendons prouver qu’il est possible de réaliser ce type de carte sans passer par un logiciel DAO (Lambert 2019). Les sources et les références sont précisées à la fin du document.
1 Préparation des données
1.1 Packages
Pour réaliser cette carte, nous nous appuyons sur 5 packages :
- eurostat
(Lahti et al. 2017) pour les données,
- rnaturalEarth
(South 2017) pour quelques couches d’habillages supplémentaires,
- sf
(Pebesma 2018) pour gérer les objets spatiaux,
- mapsf
(Giraud 2021) pour l’affichage des différentes couches composant la carte,
- scales
(Wickham, Seidel 2020) pour réaliser le rééchelonnage d’une série statistique.
library("sf")
library("mapsf")
library("eurostat")
library("rnaturalearth")
library("scales")
1.2 Données géométriques
Pour commencer, nous créons un fond de carte basé sur le système de découpage territoriale NUTS1. Afin de couvrir l’espace européen de manière exhaustive, nous construisons un maillage hybride et homogène combinant différentes versions et niveaux de découpage NUTS.
Le découpage NUTS3 (version 2016) n’est pas disponible pour les pays suivants : Autriche, Belgique, Suisse, Allemagne, Grèce, Pays-Bas, Turquie, Irlande, Islande et Norvège. Nous utiliserons donc le découpage NUTS2 pour ces territoires. Pour des raisons de disponibilité des données post-Brexit, nous l’utiliserons dans sa version 2013 pour le Royaume-Uni.
Récupération des découpages NUTS de 2016 et construction d’un fond de carte hybride NUTS2/3.
# NUTS 2016
<- get_eurostat_geospatial(
nuts2016 output_class = "sf",
resolution = "20",
nuts_level = "all",
year = "2016")
# Couche géographique des NUTS3 et NUTS2 pour 2016
<- nuts2016[nuts2016$LEVL_CODE == 3, ]
nuts2016_3 <- nuts2016[nuts2016$LEVL_CODE == 2, ]
nuts2016_2
# Liste des pays (code ISO) sans découpage NUTS3
<- c("AT", "BE", "CH", "DE", "EL", "NL", "UK", "TR", "IE", "IS", "NO")
N2
# Couche géographique NUTS2/3 en fonction de la liste de pays N2
<- rbind(nuts2016_2[nuts2016_2$CNTR_CODE %in% N2, ],
nuts !nuts2016_3$CNTR_CODE %in% N2, ])
nuts2016_3[
# Suppression des départements d'Outre-mer français
<- nuts[!nuts$id %in% c("FRY10", "FRY20", "FRY30", "FRY40", "FRY50"), ]
nuts
# Suppression des NUTS 2016 du Royaume-Uni
<- nuts[nuts$CNTR_CODE != "UK", ]
nuts
# Sélection et renommage de colonnes
<- nuts[,c("id","NUTS_NAME","geometry")]
nuts colnames(nuts) <- c("id","name","geometry")
Fusion avec le découpage NUTS2 2013 du Royaume-Uni.
# Récupération du découpage NUTS2 2013
<- get_eurostat_geospatial(
nuts2013 output_class = "sf",
resolution = "20",
nuts_level = "2",
year = "2013")
# Sélection des NUTS2 du Royaume-Uni
<- nuts2013[nuts2013$CNTR_CODE == "UK",]
uk
# Sélection et renommage de colonnes
<- uk[,c("id","NUTS_NAME","geometry")]
uk colnames(uk) <- c("id","name","geometry")
# Fusion des NUTS2 2013 du Royaume-Uni avec le fond de carte NUTS2/3 2016
<- rbind(nuts, uk) nuts
Le fond de carte (ou couche géographique) créé est donc une fusion des découpages territoriaux suivants :
1.3 Données statistiques
Grâce au package eurostat
, nous récupérons des données de PIB par habitant en 2016.
# Récupération des données (PIB/hab)
<- "nama_10r_3gdp"
var <- get_eurostat(var, time_format = "num")
gdpinh
# Sélection de l'unité de mesure et de la date
<- gdpinh[gdpinh$unit == "EUR_HAB",]
gdpinh <- gdpinh[gdpinh$time == 2016, c("geo","values")]
gdpinh
colnames(gdpinh) <- c("id","GDPINH_2016")
Les données pour le Royaume-Uni ne sont plus disponibles depuis le Brexit. Elles sont également manquantes pour quelques unités territoriales. Nous combinons donc les données issues d’eurostat
avec des estimations issues de la base de données ESPON (fichier missing.csv, téléchargeable ici).
Nous combinons les deux jeux de données pour avoir une couverture exhaustive de l’espace à représenter.
# Import des données
<- read.csv("data/missing.csv")
missing # Fusion des deux tableaux
<- rbind(gdpinh, missing) gdpinh
Pour des questions de reproductibilité, nous sauvegardons les données complétées dans le répertoire local data.
write.csv(gdpinh, "data/gdpinh.csv")
Les estimations issues de la base de données ESPON (“missing”’“) ainsi que le tableau de données complété (”gdpinh”) sont récupérables à ce lien :
Nous effectuons ensuite une jointure entre les données et les géométries.
<- merge(
nuts x = nuts,
y = gdpinh,
by = "id",
all.x = TRUE)
2 Modèle de mise en page
2.1 Couches d’habillage
Pour habiller la carte, nous utilisons des couches géographiques mises à disposition par le package rnaturalearth
.
# Surface terrestre, à petite échelle
<- ne_download(
land scale = 110,
type = "land",
category = "physical",
returnclass = "sf")
Il est possible d’afficher la couche d’habillage avec la fonction mf_map
du package mapsf
.
mf_map(land, border = NA, col = "#6eb1db")
# Mers et océans, à petite échelle
<- ne_download(
ocean scale = 110,
type = "ocean",
category = "physical",
returnclass = "sf")
mf_map(ocean, border = NA, col = "#6eb1db")
Puis, nous créons une couche de graticules avec la fonction st_graticule
du package sf
.
= st_graticule(
graticule crs = st_crs(4326),
ndiscr = 100,
lon = seq(-180, 180, by = 2),
lat = seq(-90, 90, by = 1),
margin = 0.01)
mf_map(graticule, col = "#6eb1db")
2.2 Projection orthographique
Pour donner un effet de rotondité et permettre une représentation en 2,5D, on opte pour une projection orthographique centrée sur l’Afrique. Pour éviter tout problème dans l’opération de projection (bug, artefacts, etc.), nous définissons au préalable un rectangle qui servira à découper les différentes couches géographiques.
# Construction du rectangle (bounding box)
<- st_as_sfc(x = st_bbox(c(xmin = -50 , xmax = 70, ymin = 20, ymax = 80),
bb crs = st_crs(4326)))
Nous pouvons ensuite découper toutes les couches d’habillage en fonction du rectangle préalablement créé. Pour que cette opération se passe bien, nous utilisons la fonction sf_use_s2
du package sf
en paramétrant l’argument use_s2
en FALSE
pour faire comme si les latitudes et longitudes étaient des coordonnées euclidiennes. Une fois les intersections effectuées, nous réexécutons cette fonction en paramétrant l’argument use_s2
en TRUE
.
sf_use_s2(FALSE)
<- st_intersection(ocean, bb)
ocean <- st_segmentize(ocean, 100)
ocean <- st_intersection(land, bb)
land <- st_segmentize(land, 100)
land <- st_intersection(graticule, bb)
graticule
sf_use_s2(TRUE)
Nous projetons ensuite toutes les couches géographiques créées dans une projection orthographique centrée sur l’Afrique (10° de latitude nord et 15° de longitude).
# Définition de la projection en format "proj-strings" (PROJ.4)
<- "+proj=ortho +lat_0=-10 +lon_0=15 +x_0=0 +y_0=0
ortho +ellps=WGS84 +units=m +no_defs"
# Projection des couches géographiques
<- st_transform(ocean, ortho)
ocean <- st_transform(land, ortho)
land <- st_transform(graticule, ortho)
graticule <- st_transform(nuts, ortho) nuts
Affichons l’ensemble des couches recadrées et projetées pour visualiser le résultat :
par(mar = c(0, 0, 0, 0), mfrow = c(2, 2))
mf_map(land, col = "#6eb1db", border = NA)
mf_title("land", bg = "#6eb1db")
mf_map(ocean, col = "#6eb1db", border = NA)
mf_title("ocean", bg = "#6eb1db")
mf_map(graticule, col = "#6eb1db", lwd = 1)
mf_title("graticule", bg = "#6eb1db")
mf_map(nuts, col = "#6eb1db", border = "white", lwd = 0.2)
mf_title("NUTS2/3", bg = "#6eb1db")
2.3 Effet d’ombrage
On peut générer un effet d’ombrage en agrégeant les régions NUTS en un seul polygone, puis en affichant plusieurs fois ce polygone avec de la transparence et un léger décalage dans l’espace. Ci-dessous, un exemple sur la France métropolitaine :
# Union de l'ensemble des entités de la couche géographique "nuts"
<- st_union(nuts[substr(nuts$id, 1, 2) == "FR", ])
fr
# Paramétrage des marges de la fenêtre graphique
par(mar = c(0, 0, 0, 0))
# Affichage multiple de la couche, en appliquant à chaque fois un léger décalage
mf_map(fr + c(5000,-5000), col = "#827e6c40", border = NA)
mf_map(fr + c(10000,-10000), col = "#827e6c40", border = NA, add = TRUE)
mf_map(fr + c(15000,-15000), col = "#827e6c40", border = NA, add = TRUE)
mf_map(fr + c(20000,-20000), col = "#827e6c40", border = NA, add = TRUE)
mf_map(fr + c(25000,-25000), col = "#827e6c40", border = NA, add = TRUE)
mf_map(fr, col = "#6eb1db", border = "white", lwd = 0.1, add = TRUE)
2.4 Fonction template()
A partir des différentes couches géographiques recadrées et projetées, nous allons à présent réaliser un modèle de mise en page cartographique.
Pour cela, nous définissons précisément l’emprise de la carte dans le système de coordonnées de la projection. Les coordonnées étant en mètres, nous utilisons un facteur 100 000 (variable k) qui nous permet de manipuler de petits chiffres avec un niveau de précision satisfaisant. Nous utiliserons également ce facteur k pour positionner les différents éléments d’habillage de la carte.
# Création de la variable k
<- 100000
k
# Coordonnées de l'emprise * k
<- c(-20, 42, 24.5, 63) * k
extent
# Construction de l'emprise (objet sfc)
<- st_as_sfc(x= st_bbox(c(xmin = extent[1],
bb xmax = extent[3],
ymin = extent[2],
ymax = extent[4]),
crs = st_crs(nuts)))
On crée ensuite la fonction template()
qui contiendra tous les éléments de la mise en page souhaitée. Ce modèle est construit à l’aide de fonctions du package mapsf
.
# Création de la fonction
= function(file) {
template
# Création d'un thème
<- mf_theme(x = "default",
theme bg = "#f2efe6",
fg = "#f2efe6",
mar = c(0, 0, 0, 0),
tab = TRUE,
pos = "left",
inner = FALSE,
line = 2,
cex = 1.9,
font = 3)
# Paramétrage de l'export de la carte en format png
mf_export(bb,
export = "png",
width = 2000,
filename = file,
res = 150,
theme = theme,
expandBB = c(-.02, 0, 0.05, 0))
# Affichage de la couche 'ocean'
mf_map(ocean, col = "#9acbe3", border = "#9acbe3", lwd = 5, add = TRUE)
# Affichage de la couche 'graticule'
mf_map(graticule, col = "#FFFFFF80", lwd = 1.5, lty = 3, add = TRUE)
# Affichage d'un effet d'ombrage pour la couche 'nuts'
<- st_union(nuts)
ue mf_map(ue + c(5000,-5000), col = "#827e6c40", border = NA, add = TRUE)
mf_map(ue + c(10000,-10000), col = "#827e6c40", border = NA, add = TRUE)
mf_map(ue + c(15000,-15000), col = "#827e6c40", border = NA, add = TRUE)
mf_map(ue + c(20000,-20000), col = "#827e6c40", border = NA, add = TRUE)
mf_map(ue + c(25000,-25000), col = "#827e6c40", border = NA, add = TRUE)
# Affichage de la couche 'nuts'
mf_map(nuts, col = "#dbccb6", border = "white", lwd = 0.3, add = TRUE)
# Affichage d'un bandeau bleu transparent sous le titre
rect(-22 * k,
41.3 * k,
28 * k,
41.3 * k + 250000,
border = NA, col = "#2369bd80")
# Affichage du titre
text(x = -21.5 * k,
y = 42.4 * k,
labels = "30 YEARS LATER, THE IRON CURTAIN IS STILL VISIBLE",
cex = 2.14,
pos = 4,
font = 2,
col = "#FFFFFF80")
# Affichage des sources
text(x = -21.75 * k,
y = 44.25 * k,
labels = "Map 100% designed in the R language by Nicolas Lambert, 2019.
Code source available here: https://github.com/neocarto/ironcurtain). Data sources: Eurostat & Natural Earth, 2019",
cex = 0.5,
pos = 4,
font = 1,
col = "#3f4654")
# Affichage d'une échelle
mf_scale(size = 700,
lwd = 0.6,
cex = 0.5,
col = "#3f4654",
pos = c(19 * k, y = 44 * k))
}
La fonction d’export mf_export()
est incluse dans la fonction template()
. Le résultat de cette fonction est donc une sortie graphique au format png, directement enregistrée sur votre machine. Ainsi, l’utilisation de cette fonction doit obligatoirement être couplée avec la fonction dev.off()
qui permet de fermer le périphérique graphique et de lancer l’enregistrement de son contenu dans un fichier.
template()
permet de parfaitement contrôler les marges et le dimensionnement de la carte produite, quelle que soit la taille de sa fenêtre graphique.
Et voilà le résultat :-)
# Indiquez le nom du fichier png créé
# Utilisez dev.off() pour clôturer l'enregistrement du fichier
template("figures/fig1.png")
dev.off()
Le résultat ne s’affiche pas dans la fenêtre graphique. Il est directement enregistré en format png dans le répertoire souhaité.
3 Carte choroplèthe2
Maintenant que le modèle de mise en page est facilement reproductible avec la fonction template()
, penchons-nous sur la représentation cartographique du PIB par habitant.
3.1 Discrétiser la variable
Afin de cartographier cette variable quantitative relative, nous devons commencer par discrétiser la distribution statistique par classe de valeurs. Pour cela, nous utilisons la fonction mf_get_breaks()
du package mapsf
.
# Discrétisation par quantile (calcul des bornes de classes)
<- mf_get_breaks(x = nuts$GDPINH_2016,
bks nbreaks = 6,
breaks = "quantile")
# Vecteur de couleurs (1 par classe)
<- c("#50b160",
cols "#98c17e",
"#cce3c4",
"#fbf5bd",
"#fcc34f",
"#e97d40")
3.2 Représentation graphique
Nous pouvons ensuite facilement cartographier le PIB par habitant en utilisant la fonction de mise en page template()
puis la fonction mf_map()
pour réaliser la carte choroplèthe.
# Utilisation du modèle de mise en page (+ export de la carte)
template("figures/fig2.png")
# Cartographie du PIB par habitant
mf_map(x = nuts,
var = "GDPINH_2016",
type = "choro",
breaks = bks,
pal = cols,
lwd = 0.2,
leg_pos = "n",
add = TRUE)
# Ajout d'une légende
mf_legend(type = "choro",
pos = c(11 * k, 59.05 * k),
title = "",
val = bks,
val_cex = 0.4,
pal = cols,
fg = "#333333",
cex = 0.85,
border = "red",
val_rnd = 0,
no_data = FALSE,
frame = FALSE)
# Ajout d'un titre de légende
text(10.5 * k,
y = 59.1 * k,
labels = "Gross Domestic Product",
cex = 0.75,
pos = 4,
font = 2,
col = "#404040")
# Ajout d'un sous-titre de légende
text(10.5 * k,
y = 58.7 * k,
labels = "(in € per inh. in 2016)",
cex = 0.55,
pos = 4,
font = 1,
col = "#404040")
# NE PAS OUBLIER
dev.off()
4 Discontinuités
La première étape pour cartographier les discontinuités spatiales consiste à récupérer les frontières entre chaque entité territoriale NUTS.
4.1 Récupérer les frontières
Pour cela, il suffit de réaliser une auto-intersection des NUTS (polygones de la couche ‘nuts’). Afin d’éviter d’éventuelles erreurs topologiques, il est préférable de calculer une petite zone tampon autour des polygones avant de réaliser l’intersection spatiale. Les géométries générées (lignes) doivent par la suite être définies en MULTILINESTRING.
# Auto-intersection de la couche NUTS (avec zone tampon de 5m)
<- st_intersection(st_buffer(nuts, 5), st_buffer(nuts, 5))
nuts.borders
# Transformation des géométries en 'MULTILINESTRING'
<- st_cast(nuts.borders ,"MULTILINESTRING") nuts.borders
Il est ensuite nécessaire de nettoyer la couche géographique et de créer un identifiant unique pour chaque ligne (frontière) détectée.
# Suppression des intersections entre un même polygone
<- nuts.borders [nuts.borders $id != nuts.borders $id.1, ]
nuts.borders
# Construction d'un identifiant unique pour chaque frontière
$id1 <- nuts.borders$id
nuts.borders$id2 <- nuts.borders$id.1
nuts.borders$id <- paste0(nuts.borders$id1, "_", nuts.borders$id2)
nuts.bordersrownames(nuts.borders) <- nuts.borders$id
<- nuts.borders [,c("id","id1","id2","geometry")] nuts.borders
4.2 Mesurer les discontinuités
Nous pouvons maintenant effectuer une double jointure pour relier à chaque “frontière” de NUTS les données de PIB par habitant des régions limitrophes.
# Récupération des données de PIB par habitant, en supprimant la géométrie associée
<- st_set_geometry(x = nuts[, c("id","GDPINH_2016")],
vals value = NULL)
# Double jointure pour récupérer les valeurs des NUTS limitrophes
<- merge (x = nuts.borders, y = vals, by.x = "id1", by.y = "id", all.x = T)
nuts.borders <- merge (x = nuts.borders, y = vals, by.x = "id2", by.y = "id", all.x = T) nuts.borders
Pour chaque frontière (ligne), nous calculons une valeur de discontinuité relative :
\[ Discontinuité~relative = \frac{{PIB~par~habitant~de~la~région~A~(ou~B)}}{{PIB~par~habitant~de~la~région~B~(ou~A)}} \]
$disc <- nuts.borders$GDPINH_2016.x / nuts.borders$GDPINH_2016.y nuts.borders
Nous choisissons de conserver uniquement les plus fortes discontinuités (10 %). Cela revient à choisir comme seuil la valeur 0,95 (95%) car la table présente deux valeurs pour chaque frontière (les rapports A/B et B/A).
<- 0.95
threshold <- nuts.borders[nuts.borders$disc >= quantile(nuts.borders$disc,threshold),] disc
Affichons les plus fortes discontinuités sélectionnées avec la mise en page précédemment créée :
template("figures/fig3.png")
mf_map(x = disc,
col = "#d92e94",
lwd = 3,
add = TRUE)
dev.off()
On constate que les fortes discontinuités entre les régions européennes suivent très largement le tracé de l’ancien rideau de fer (si on fait abstraction de l’ancienne frontière RFA/RDA). C’est ce que nous souhaitons mettre en valeur par un procédé d’extrusion, pour rappeler la symbolique du mur.
4.3 Extrusion (effet 2,5D)
Pour extruder les lignes, nous procédons comme pour l’effet d’ombrage (cf. partie 1.6) : nous translatons les lignes plusieurs fois en ordonnée (y, vers le haut). Sur la projection orthographique utilisée, cela produit un effet 3D. Le nombre d’itérations et l’écart entre les lignes détermine la hauteur du mur. Exemple pour une frontière :
# On sélectionne une ligne (frontière) au hasard
<- st_geometry(disc[5, ])
line
# Choix d'un nombre d'itérations
<- 15
nb
# Choix d'une valeur de translation
<- 200 delta
On effectue alors une boucle for qui construit “nb” lignes (15), décalées de “delta” (200) à chaque fois.
# Paramétrage des marges et de la couleur de fond
par(mar = c(0, 0, 0, 0), bg = "#f2efe6")
# Affichage de la frontière
mf_map(line, col = "#66666690", lwd = 0.5)
# "nb" affichage de la frontière, décalée de "delta" à chaque fois
for (j in 1:nb) {
<- line + c(0, delta)
line mf_map(line,
col = "#66666690",
lwd = 0.5 ,
add = TRUE)
}
# Affichage de la dernière ligne calculée en rouge, avec une épaisseur de 1.2
mf_map(line,
col = "#cf0e00",
lwd = 1.2,
add = TRUE)
Pour que l’effet 3D fonctionne, l’ordre d’affichage des discontinuités est important. Nous décomposons donc les lignes et les ordonnons en fonction de la valeur en ordonnée (y) de leur centroïde. Cela permet d’afficher les discontinuités du Nord au Sud. Ainsi, les lignes qui sont “devant” apparaissent devant.
# Transformation du type de géométrie
<- st_cast(disc,"LINESTRING")
disc
# Calcul des coordonnées des centroïdes de chaque ligne
<- as.data.frame(st_coordinates(st_centroid(disc)))
c
# Récupération de la valeur y de chaque centroïde
$Y <- c$Y
disc
# Tri des discontinuités en fonction de la valeur de y
<- disc[order(disc$Y, decreasing = TRUE), ] disc
Nous considérons que les frontières nationales renvoient à des disparités historiques plus significatives. Ainsi, nous choisissons de traiter différemment les discontinuités entre deux régions d’un même pays et entre deux régions de deux pays différents. Les premières auront une “hauteur de mur” constante (8 itérations). Les secondes auront une “hauteur de mur” qui dépendra de la valeur des discontinuités (entre 30 et 70 itérations) et seront représentées en rouges.
Dans un premier temps, nous calculons une “hauteur de mur” proportionnelle à la valeur de discontinuité relative de chaque ligne. Nous rééchelonnons l’étendue de la distribution entre les valeurs 30 et 70. La plus faible (des plus fortes) discontinuité sera itérée 30 fois, la plus forte 70 fois.
Pour réaliser ce rééchelonnage, nous utilisons la fonction rescale
du package scale
.
# Rééchelonnage des valeurs de discontinuité de 30 à 70
$height <- round(rescale(disc$disc, to=c(30,70)),0) disc
On affecte également par défaut la couleur rouge et la même épaisseur à toutes les lignes, en les stockant dans deux nouvelles variables (“col” et “thickness”).
$col <-"#cf0e00"
disc$thickness <- 1.2 disc
Nous devons ensuite repérer les discontinuités infra-nationales afin de modifier les valeurs à représenter. Pour cela nous utilisons les deux premières lettres des codes NUTS associées à chaque ligne, puisqu’elles correspondent au code ISO du pays d’appartenance.
$c1 <- substr(disc$id1,1,2)
disc$c2 <- substr(disc$id2,1,2) disc
A l’aide d’une boucle for et d’un test if, nous pouvons détecter les frontières infra-nationales. Nous modifions alors les valeurs des variables “height”, “col” et “thickness” (qui seront utilisées pour la représentation des discontinuités) pour toutes ces lignes.
# Boucle qui parcourt toutes les lignes
for (i in 1:length(disc$disc)){
# Pays 1 == Pays 2 ?
if (disc$c1[i]== disc$c2[i]) {
# 8 itérations
$height[i] <- 8
disc# Couleur grise
$col[i] <-"#66666690"
disc# Petite épaisseur
$thickness[i] <- 0.5
disc
} }
Toutes les valeurs à représenter sont maintenant stockées dans l’objet “disc”. Nous pouvons alors construire une fonction d’extrusion des lignes en fonction de ces valeurs calculées.
# Valeur de translation
<- 2500
delta
# Création de la fonction extrude()
<- function(id){
extrude
<- st_geometry(disc[id,])
line mf_map(line, col= "#66666690",lwd = 0.5 ,add= TRUE)
<- as.numeric(disc[id,"height"])[1]
nb
for (j in 1:nb){
<- st_geometry(line) + c(0,delta)
line mf_map(st_geometry(line), col= "#66666690",lwd = 0.5 ,add= TRUE)
}
mf_map(line, col= disc$col[id],lwd = disc$thickness[id] ,add= TRUE)
}
Nous pouvons appliquer cette fonction à toutes les lignes en utilisant une boucle for. Voici un exemple d’utilisation de la fonction extrude()
, combinée à template()
avec l’ajout d’une légende pour les discontinuités représentées.
template("figures/fig4.png")
# BOUCLE for pour appliquer la fonction extrude() à toutes les lignes
for (i in 1:length(disc$height))
{extrude(i)
}
# TEXTE de la légende pour les discontinuités
# Utilisation du facteur k pour un placement précis des éléments
= 0.75 * k
d # Titre légende
text(14.4*k - d, y = 57.4*k, "Discontinuities",
cex = 0.6, pos = 4, font = 2, col="#404040")
# Intitulé classe 1
text(15.5*k - d, y = 56.6*k, "Between two regions of the same country",
cex = 0.4, pos = 4, font = 1, col="#404040")
# Intitulé classe 2
text(15.5*k - d, y = 55.7*k, "Between two regions of two different countries",
cex = 0.4, pos = 4, font = 1, col="#404040")
# Description
text(15.5*k - d, y = 55.3*k,
"(The height is proportional to the value of the dicontinuity)",
cex = 0.4, pos = 4, font = 1, col="#404040")
# NB
text(10.7*k, y = 54.4*k,
"NB: only the 10% highest discontinuities are represented on the map.",
cex = 0.4, pos = 4, font = 3, col="#404040")
# SYMBOLE pour la légende des discontinuités
# Récupération d'une ligne infra-nationale presque horizontale
<- disc[disc$id == "TR21_BG341",]
myline1
# Translation de la ligne 1 pour la positionner dans la légende (classe 1)
st_geometry(myline1) <- st_geometry(myline1) + c(4.2*k, 5*k)
# On duplique la ligne
<- myline1
myline2 # Translation de la ligne 2 pour la positionner dans la légende (classe 2)
st_geometry(myline2) <- st_geometry(myline2) + c(0, 1.5*k)
# Symbole de légende pour les discontinuités entre deux pays
plot(myline1, col= "#66666690",lwd = 0.5 ,add= T)
# 40 itérations de la ligne
for (i in 1:40){
<- st_geometry(myline1) + c(0,delta)
myline1 plot(st_geometry(myline1), col= "#66666690",lwd = 0.5 ,add= T)
}# Dernière ligne en rouge
plot(myline1, col= "#cf0e00",lwd = 1.2 ,add= T)
# Symbole de légende pour les discontinuités infra-nationales
plot(myline2, col= "#66666690",lwd = 0.5 ,add= T)
# 8 itérations de la ligne
for (i in 1:8){
<- st_geometry(myline2) + c(0,delta)
myline2 plot(st_geometry(myline2), col= "#66666690",lwd = 0.5 ,add= T)
}plot(myline2, col= "#66666690",lwd = 0.5 ,add= T)
# Ne pas oublier
dev.off()
5 Carte finale
Le modèle de mise en page et la représentation des discontinuités en 2,5D ont été encapsulés dans des fonctions et la variable à représenter a été discrétisée. Nous avons donc tous les éléments pour générer la carte finale :
# Modèle de mise en page
template("figures/ironcurtain.png")
# Carte choroplèthe
mf_map(x = nuts,
var = "GDPINH_2016",
type = "choro",
breaks = bks,
pal = cols,
lwd = 0.2,
leg_pos = "n",
add = TRUE)
# Légende carte choroplèthe
mf_legend(type = "choro",
pos = c(11 * k, 59.05 * k),
title = "",
val = bks,
val_cex = 0.4,
pal = cols,
fg = "#333333",
cex = 0.85,
border = "red",
val_rnd = 0,
no_data = FALSE,
frame = FALSE)
# Titre légende carte choroplèthe
text(10.5 * k,
y = 59.1 * k,
labels = "Gross Domestic Product",
cex = 0.75,
pos = 4,
font = 2,
col = "#404040")
# Sous-titre légende carte choroplèthe
text(10.5 * k,
y = 58.7 * k,
labels = "(in € per inh. in 2016)",
cex = 0.55,
pos = 4,
font = 1,
col = "#404040")
# Construction discontinuités
for (i in 1:length(disc$height)){extrude(i)}
# Texte légende discontinuités
= 0.75 * k
d text(14.4*k - d, y = 57.4*k, "Discontinuities",
cex = 0.6, pos = 4, font = 2, col="#404040")
text(15.5*k - d, y = 56.6*k, "Between two regions of the same country",
cex = 0.4, pos = 4, font = 1, col="#404040")
text(15.5*k - d, y = 55.7*k, "Between two regions of two different countries",
cex = 0.4, pos = 4, font = 1, col="#404040")
text(15.5*k - d, y = 55.3*k,
"(The height is proportional to the value of the dicontinuity)",
cex = 0.4, pos = 4, font = 1, col="#404040")
text(10.7*k, y = 54.4*k,
"NB: only the 10% highest discontinuities are represented on the map.",
cex = 0.4, pos = 4, font = 3, col="#404040")
# Symbole légende discontinuités
<- disc[disc$id == "TR21_BG341",]
myline1 st_geometry(myline1) <- st_geometry(myline1) + c(4.2*k, 5*k)
<- myline1
myline2 st_geometry(myline2) <- st_geometry(myline2) + c(0, 1.5*k)
plot(myline1, col= "#66666690",lwd = 0.5 ,add= T)
for (i in 1:40){
<- st_geometry(myline1) + c(0,delta)
myline1 plot(st_geometry(myline1), col= "#66666690",lwd = 0.5 ,add= T)
}plot(myline1, col= "#cf0e00",lwd = 1.2 ,add= T)
plot(myline2, col= "#66666690",lwd = 0.5 ,add= T)
for (i in 1:8){
<- st_geometry(myline2) + c(0,delta)
myline2 plot(st_geometry(myline2), col= "#66666690",lwd = 0.5 ,add= T)
}plot(myline2, col= "#66666690",lwd = 0.5 ,add= T)
# Clôture graphique - enregistrement png
dev.off()
Et voilà. Même si cela nécessite quelques tâtonnements pour positionner les différents éléments, nous venons de faire la démonstration qu’il est donc possible de faire de la cartographie d’édition, stylisée et mise en page, uniquement avec R :-)
Bibliographie
Annexes
Info session
setting | value |
---|---|
version | R version 4.0.2 (2020-06-22) |
os | Ubuntu 18.04.5 LTS |
system | x86_64, linux-gnu |
ui | X11 |
language | (EN) |
collate | fr_FR.UTF-8 |
ctype | fr_FR.UTF-8 |
tz | Europe/Paris |
date | 2021-12-17 |
package | ondiskversion | source |
---|---|---|
eurostat | 3.7.5 | CRAN (R 4.0.2) |
mapsf | 0.3.0 | CRAN (R 4.0.2) |
rnaturalearth | 0.1.0 | CRAN (R 4.0.2) |
scales | 1.1.1 | CRAN (R 4.0.2) |
sf | 1.0.2 | CRAN (R 4.0.2) |
Citation
Lambert N (2021). “Le nouveau rideau de fer.” doi: 10.48645/a4ra-yr11, (URL: https://doi.org/10.48645/a4ra-yr11), <URL:, https://rzine.fr/publication_rzine/20191125_ironcurtain/>.
BibTex :
@Misc{,
title = {Le nouveau rideau de fer},
subtitle = {Un exemple de carte en 2,5D},
author = {Nicolas Lambert},
doi = {10.48645/a4ra-yr11},
url = {https://rzine.fr/publication_rzine/20191125_ironcurtain/},
keywords = {FOS: Other social sciences},
language = {fr},
publisher = {FR2007 CIST},
year = {2021},
copyright = {Creative Commons Attribution Share Alike 4.0 International},
}
Glossaire
La nomenclature NUTS (Nomenclature des unités territoriales statistiques) est un système hiérarchique de découpage du territoire économique de l’UE à 3 niveaux. Elle sert de référence pour la collecte des statistiques régionales, pour les analyses socio-économiques des régions, pour la définition des politiques régionales de l’UE.↩︎
La carte choroplèthe est le type le plus usuel de carte statistique. Il s’agit d’une représentation de quantités relatives à des espaces, ou aires géographiques, par le moyen d’une « échelle » de tons gradués. La carte choroplèthe pose un problème à la fois mathématique et graphique. Sa réalisation repose d’abord sur le choix d’une méthode de discrétisation, c’est-à-dire de division de la série statistique que l’on veut cartographier en classes, ou intervalles. Il faut par ailleurs déterminer le nombre de classes retenues pour la représentation, qui correspond au nombre de paliers visuels à réaliser (Palsky 2004).↩︎