Module Cartographie
26/03/2026
Ce diaporama de formation a été rédigé dans le but d’être le support visuel des formations dispensées au SSM Agriculture.
Ces formations de perfectionnement s’adressent aux agents qui ont suivi la formation R initialisation (ou le module de rappels sur la formation initiation) ainsi que le module sur les fonctions, voir sur le site des formations dispensées au MASA.
Les différents modules sont donnés en présentiel sur une durée d’une journée (avant la formation R-perfectionnement était groupée sur 3 jours).
Champ couvert par cette formation
Ce support couvre le module cartographie dans l’environnement du Ministère.
Pour information, Les Modules de la formation R-perfectionnement sont :
ggplot2Les modules sont orientés pour être utiles aux agents du SSM Agriculture et se concentrent sur une utilisation de R via RStudio qui est mise à disposition des agents sur la plateforme interne Cerise basée sur RStudio Workbench.
Voir les fiches Principaux types de cartes, Cartographie, et Sémilogie Graphique et sur https://sigea.educagri.fr/theorie/fiches-synthetiques.
Carte figurative de l’instruction populaire de la France est une carte choroplèthe de la France conçue en 1826 par l’ingénieur, mathématicien et homme politique français Charles Dupin. Elle est considérée comme une des toutes premières cartes thématiques jamais réalisées. Wikipédia
Ceci n’est pas une carte !
Une carte doit présenter : un titre, une légende, une échelle, une flèche nord, des sources, un auteur… et un corps.
La sémiologie graphique est, de façon générale, l’ensemble des règles qui régissent la construction d’un système de signes ou langage permettant la traduction graphique d’une information. Depuis la parution de la Sémiologie graphique de Jacques Bertin en 1967, elle désigne surtout un ensemble standardisé des règles et de pratiques inhérentes à la représentation cartographique au-delà des travaux réalisés par Bertin.
Extrait de Wikipédia.
S’il ne faut retenir qu’une seule règle : pas de stocks en aplat ! (voir https://neocarto.hypotheses.org/5717).
Principales variables graphiques et leur rendu dans {tmap}, issu de Voir Spatial Data Visualization with tmap, Chapter 7
{sf} (4.4) : fonctions sur les objets spatiaux (import, traitement, export…) (documentation){tmap} (4.2) : réalisation de cartes (documentation){cols4all} (documentation) et {colorspace} (documentation) pour la sélection de couleurs.Autres possibilités pour la cartographie avec {ggplot2} + {ggspatial}, {mapsf}, {leaflet}, {mapview}…
{tmap}{ggplot2}).Changements substantiels d’interface depuis la v4.0, voir Releases.
TODO Réaliser une carte départementale métropolitaine du nombre et des parts d’exploitations ayant au moins une parcelle conduite en agriculture biologique (source : RA 2020).
{tmap}Voir Spatial Data Visualization with tmap, Chapter 6
| Function | Element | Geometry |
|---|---|---|
tm_polygons() |
polygons (borders and fill) | polygons |
tm_symbols() |
symbols | points, polygons, and lines |
tm_lines() |
lines | lines |
tm_text() |
text | points, polygons, and lines |
tm_raster() |
raster | raster |
tm_basemap() |
tile | |
tm_tiles() |
tile |
| Function | Element | Geometry |
|---|---|---|
tm_borders() |
polygons (borders) | polygons |
tm_fill() |
polygons (fill) | polygons |
tm_bubbles() |
bubbles | points, polygons, and lines |
tm_dots() |
dots | points, polygons, and lines |
tm_markers() |
marker symbols | points, polygons, and lines |
tm_square() |
squares | points, polygons, and lines |
tm_labels() |
text labels | points, polygons, and lines |
tm_labels_highlighted() |
text labels with background | points, polygons, and lines |
tm_iso() |
lines with text labels | lines |
tm_rgb()/tm_rgba() |
raster (RGB image) | raster |
La fonction read_sf() permet d’ouvrir des données cartographiques au format .TAB (MapInfo), .shp (Shapefile), .gpkg (GeoPackage), des bases de données PostGIS ou DuckDB.
r$> st_layers(gpkg)
Driver: GPKG
Available layers:
layer_name geometry_type features fields crs_name
1 cheflieu Point 34877 7 WGS 84
2 commune_int 102173 0 WGS 84
3 departement_int 238 0 WGS 84
4 region_int 23 0 WGS 84
5 epci_int 3526 0 WGS 84
6 departement 103 4 WGS 84
7 commune 34877 12 WGS 84
8 region 19 3 WGS 84
9 epci 1266 4 WGS 84L’objet dep combine des géométries (ici les polygones des départements, attribut geom) et des données atrtibutaires (attributs insee_dep, nom, insee_reg…) dans un objet de type data.frame ou tibble.
Ce data.frame se comporte comme n’importe quel autre (même utilisation des fonctions str(), names(), les fonctions de {dplyr}…).
r$> head(dep)
Simple feature collection with 6 features and 4 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 394752.2 ymin: 6686771 xmax: 987205.3 ymax: 7030719
Projected CRS: RGF93 v1 / Lambert-93
# A tibble: 6 x 5
insee_dep id nom insee_reg geom
<chr> <chr> <chr> <chr> <MULTIPOLYGON [m]>
1 70 DEPARTEM_FXX_00000000071 Haute-Saône 27 (((972248.1 6762255, 973545.8 6~
2 89 DEPARTEM_FXX_00000000090 Yonne 27 (((707373.3 6805723, 707657.4 6~
3 60 DEPARTEM_FXX_00000000061 Oise 32 (((699240.6 6902196, 699168.9 6~
4 80 DEPARTEM_FXX_00000000081 Somme 32 (((660347.7 7002280, 660606.9 7~
5 14 DEPARTEM_FXX_00000000016 Calvados 28 (((507839.1 6886562, 508318.9 6~
6 27 DEPARTEM_FXX_00000000028 Eure 28 (((509647.6 6912733, 508374.9 6~ plot() permet d’afficher le fond pour toutes les variables dans la fenêtre graphique (documentation).
exp_dep <- read_rds("~/CERISE/03-Espace-de-Diffusion/030_Structures_exploitations/3020_Recensements/RA_2020/01_BASES DIFFUSION RA2020/DEF_240112/RA2020_EXPLOITATIONS_240112.rds") |>
as_tibble(.name_repair = make_clean_names) |>
filter(champ_geo == "1") |>
group_by(siege_dep) |>
summarise(n_exp = n(),
n_exp_bio = sum(bio_fil, na.rm = TRUE)) |>
mutate(part_exp_bio = n_exp_bio / n_exp * 100)
head(exp_dep)
bio <- dep |>
left_join(exp_dep, by = c("insee_dep" = "siege_dep"))| siege_dep | n_exp | n_exp_bio | part_exp_bio |
|---|---|---|---|
| 01 | 3017 | 301 | 9.976798 |
| 02 | 4472 | 221 | 4.941860 |
| 03 | 4356 | 328 | 7.529844 |
| 04 | 2064 | 520 | 25.193798 |
| 05 | 1646 | 367 | 22.296476 |
| 06 | 1192 | 235 | 19.714765 |
Affichage minimaliste par défaut avec fonction sf::plot(), e.g. plot(bio |> select(geom, part_exp_bio)).
tm_polygons# "view" = interactif <https://r-tmap.github.io/tmap/reference/tmap_mode.html>
tmap_mode("view")
tm_shape(bio) +
tm_polygons(
fill = "part_exp_bio",
col = "grey60",
fill.scale = tm_scale_intervals(
style = "pretty", # default
n = 5,
values = "brewer.bu_gn",
label.format = tm_label_format(
text.separator = " - "
)
),
fill.legend = tm_legend(
title = "part en %",
lwd = 0.25, # lwd = line width
reverse = TRUE,
)
)Carte interactive avec symbologie sur mesure.
# "plot" = statique <https://r-tmap.github.io/tmap/reference/tmap_mode.html>
tmap_mode("plot")
tm_shape(bio) +
tm_borders(col = "grey30", lwd = 0.25) +
tm_symbols(
size = "n_exp",
size.scale = tm_scale(values.scale = 1.5),
fill = "darkolivegreen4",
size.legend = tm_legend(
title = "Nombre d'exploitations en AB",
orientation = "landscape",
position = tm_pos_in()
)
)tm_shape(bio) +
tm_polygons(
fill = "part_exp_bio",
col = "grey60",
fill.scale = tm_scale_intervals(
values = "brewer.bu_gn",
),
fill.legend = tm_legend(
title = "Part d'exploitations en AB (en %)",
reverse = TRUE,
)
) +
tm_symbols(
size = "n_exp",
size.scale = tm_scale(values.scale = 1.5),
fill = "darkolivegreen4",
size.legend = tm_legend(
title = "Nombre d'exploitations en AB",
reverse = TRUE,
)
)Une alternative consiste à faire varier la taille + la couleur du cercle : les couleurs des classes de la variable représentée en aplats sont placées dans les ronds proportionnels.
tm_shape(bio) +
tm_borders(col = "grey30", lwd = 0.25) +
tm_symbols(
fill = "part_exp_bio",
fill.scale = tm_scale(
values = "brewer.bu_gn"
),
fill.legend = tm_legend(
title = "Part d'exploitations en AB (en %)",
reverse = TRUE,
position = tm_pos_in("left", "bottom"),
),
size = "n_exp",
size.scale = tm_scale(
values.scale = 1.5
),
size.legend = tm_legend(
title = "Nombre d'exploitations en AB",
position = tm_pos_in("left", "bottom"),
frame = FALSE,
bg.alpha = 0.0
),
)Les couleurs sont à préciser dans l’argument values de la fonction tm_scale() des arguments .scale comme fill.scale.
{cols4all} (par l’auteur de {tmap}) propose une fonction cols4all::c4a_gui() qui permet de visualiser des palettes de couleurs, en simulant les déficiences visuelles. series description cat seq div cyc bivs bivc bivd bivg
1 bivario Palettes from the Python library bivario 0 0 0 0 25 0 0 0
2 brewer ColorBrewer palettes 8 18 9 0 2 2 1 0
3 carto Palettes designed by CARTO 6 21 7 0 0 0 0 0
4 cols4all cols4all palettes (in development) 14 0 2 0 2 0 2 5
5 gmt Palettes from General Mapping Tools 0 19 4 0 0 0 0 0
6 hcl Palettes from the Hue Chroma Luminance color space 9 23 11 6 0 0 0 0
7 kovesi Palettes designed by Peter Kovesi 0 28 14 8 0 0 0 0
8 matplotlib Palettes from the Python library matplotlib 0 51 12 3 0 0 0 0
9 met Palettes inspired by The Metropolitan Museum of Art 33 8 14 0 0 1 0 0
10 meteo Palettes by Oliver Fuhrer from MeteoSwiss 2 14 7 0 0 0 0 0
11 misc Miscellaneous palettes 5 0 0 0 0 3 0 0
12 ocean Colormaps for Oceanography by Thyng et al. 0 15 3 0 0 0 0 0
13 parks Palettes inspired by National Parks 22 5 3 0 0 0 0 0
14 poly Qualitative palettes with many colors 9 0 0 0 0 0 0 0
15 powerbi Palettes from Microsoft Power BI 19 1 4 0 0 0 0 0
16 scico Scientific colour maps by Fabio Crameri 21 21 10 5 0 2 0 1
17 seaborn Palettes from the Python library Seaborn 6 4 2 0 0 0 0 0
18 stevens Bivariate palettes by Joshua Stevens 0 5 0 0 5 0 0 0
19 tableau Palettes designed by Tableau 29 23 28 0 0 3 0 0
20 tol Palettes designed by Paul Tol 8 8 4 0 0 0 0 0
21 wes Palettes from Wes Anderson movies 23 0 1 0 0 0 0 0# A tibble: 9 x 37
name series fullname type n min_dist nameability min_step max_step inter_wing_dist tri_ineq Cmax H HL HR Lmid Hwidth HwidthL HwidthR Lrange Crange fairness CRmin
<chr> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 br_bg brewer brewer.~ div 9 NA NA 3.23 NA 7.52 -0.82 72 110 54 180 97 145 33 6 58 72 64 1.06
2 pi_yg brewer brewer.~ div 9 NA NA 3.84 NA 13.6 2.91 97 44 336 112 97 151 16 16 53 97 23 1.07
3 prgn brewer brewer.~ div 9 NA NA 8.25 NA 12.9 6.33 62 360 300 127 97 187 14 15 65 62 78 1.13
4 pu_or brewer brewer.~ div 9 NA NA 7.21 NA 15.5 5.27 98 340 44 270 97 158 29 19 70 98 22 1.09
5 rd_bu brewer brewer.~ div 9 NA NA 7.22 NA 12.1 5.32 111 313 26 238 97 177 32 27 59 111 10 1
6 rd_gy brewer brewer.~ div 9 NA NA 6.5 NA 6.34 -2.35 111 26 26 180 100 32 32 0 67 111 10 1.01
7 rd_yl~ brewer brewer.~ div 9 NA NA 7.56 NA 22.1 3.21 132 360 40 230 99 237 55 41 51 120 6 1.03
8 rd_yl~ brewer brewer.~ div 9 NA NA 6 NA 0.52 -7.69 132 75 40 118 99 125 56 40 51 87 38 1.03
9 spect~ brewer brewer.~ div 9 NA NA 3.84 NA 0.53 -6.25 115 360 38 167 99 233 61 147 49 72 64 1.1
# i 14 more variables: CRwt <dbl>, CRbk <dbl>, Blues <dbl>, cbfriendly <dbl>, chroma <chr>, Hspread <dbl>, fair <chr>, hues <chr>, HwidthLR <dbl>, equiluminance <lgl>,
# contrastWT <lgl>, contrastBK <lgl>, float <lgl>, nameable <lgl>L’argument style de la fonction tm_scale_intervals() utilisée dans les arguments .scale des objets cartographiques créés avec tm_polygons() permet de définir la méthode (automatique) de création des classes, l’argument n reçoit le nombre de classes à construire.
Les arguments passés à classInt::classIntervals() qui fait le calcul.
Les méthodes disponibles sont "cat", "fixed", "sd", "equal", "pretty", "quantile", "kmeans", "hclust", "bclust", "fisher", "jenks", "dpih", "headtails" et "log10_pretty". Les principales sont :
"sd" : classes construites à partir de la moyenne et dont les amplitudes valent un écart-type (standard deviation),"equal" : classes d’amplitudes égales,"quantile" : classes de même effectif,"fisher" ou "jenks" : classes construites avec une méthode qui minimise les variances intra-classes et maximise les variances inter-classes,"headtails" : classes pour les distributions avec de nombreuses valeurs hautes,Voir fichier 12_demo_classes.R pour la génération des illustrations après. Toutes ne sont pas adaptées au cas.
Il est possible de renseigner manuellement ses propres classes dans l’argument breaks de la fonction tm_scale_intervals(style = "fixed"). Pour renseigner un découpage en n classes, l’argument breaks doit contenir un vecteur de taille n+1 : c(min, borne₁, borne₂, … , borneₙ₋₁, max).
Exemple sur le % d’exploitation en AB : la méthode "quantile" à 5 classes donne les ruptures comme suit, qu’on peut arrondir et passer à breaks.
cesures <- classIntervals(bio$part_exp_bio, style = "quantile", n = 5)
cesures
# style: quantile
# one of 3,183,545 possible partitions of this variable into 5 classes
# [4.02,7.52) [7.52,9.97) [9.97,13.38) [13.38,17.18) [17.18,33.33]
# 19 19 19 19 20
tm_shape(bio) +
tm_polygons(
...
fill.scale = tm_scale_intervals(
style = "fixed",
breaks = round(cesures$brks, 1),
values = c4a("viridis", n = 5),
),
...
)
classIntervals(bio$part_exp_bio, style = "jenks", n = 5)
# style: jenks
# one of 3,183,545 possible partitions of this variable into 5 classes
# [4.02,7.17] (7.17,10.10] (10.10,14.94] (14.94,20.55] (20.55,33.33]
# 18 24 26 15 13 tmap_mode("plot")
m_base <- tm_shape(bio) +
tm_polygons(
fill = "part_exp_bio",
col = "grey60",
fill.scale = tm_scale_intervals(
values = "brewer.bu_gn",
),
fill.legend = tm_legend(
title = "Part en %",
reverse = TRUE,
position = tm_pos_in("left", "center"),
frame = FALSE,
bg.alpha = 0.0
)
)
m <- m_base +
tm_layout(
text.fontfamily = "Marianne"
) +
tm_text(
text = "insee_dep",
size = 0.5,
options = opt_tm_text(remove_overlap = TRUE)
) +
tm_title_out(
text = "Exploitations (ayant au moins une parcelle)\nen Agriculture Biologique (AB)"
) +
tm_credits(
text = "Recensement Agricole 2020 - Agreste.\nFond carto. IGN Admin Express 2025.",
position = tm_pos_in("left", "bottom")
) +
tm_scalebar(
color.dark = "grey40",
width = 24,
position = tm_pos_in("center", "bottom")
) +
tm_compass(
type = "4star",
size = 5,
position = tm_pos_in("right", "top")
) +
tm_logo(
file = "./img/logos/png/logoMASAF.png",
position = tm_pos_in("left", "top"),
height = 5
)
tmap_save(
m,
"images/4-1-habillage_carte.png",
width = 20,
units = "cm",
asp = 1.618,
dpi = 300,
device = agg_png
)
# Pour une carte interactive :
# tmap_mode("view")
# tmap_save(m, "pcent_bio_fr.html")m_facet <- tm_shape(bio) +
tm_polygons(
fill = "part_exp_bio",
col = "grey60",
fill.scale = tm_scale_intervals(
values = "brewer.bu_gn",
),
fill.legend = tm_legend(
title = "Part en %",
reverse = TRUE,
position = tm_pos_out(),
)
) +
tm_facets(by = "insee_reg") +
tm_title(text = "Exploitations en AB par région")
library(cartogram)
bio |>
# Construct a cartogram which represents each geographic
# region as non-overlapping circles
cartogram_dorling("n_exp") |>
tm_shape() +
tm_polygons(
fill = "n_exp",
fill.scale = tm_scale_intervals(
values = "brewer.bu_gn",
style = "quantile",
n = 5
),
fill.legend = tm_legend(
title = "Nombre d'exploitations",
reverse = TRUE,
)
) +
tm_text(
text = "insee_dep",
size = 0.8,
options = opt_tm_text(remove_overlap = TRUE)
)library(tilemaps)
bio_metropole <- bio |>
filter(insee_reg != "94") |>
mutate(
tile_map = generate_map(geom, square = FALSE, flat_topped = TRUE)
)
bio_metropole |>
st_set_geometry("tile_map") |>
tm_shape() +
tm_polygons(
fill = "part_exp_bio",
fill.legend = tm_legend(
title = "Part d'expl. en AB",
reverse = TRUE
)
) +
tm_text("insee_dep")Pour aller plus loin
Objectifs Réaliser la carte de densité de population communale du département de l’Aisne.
Données disponibles sur https://github.com/SSM-Agriculture/site-formations-R/wiki dans le fichier donnees_exercices.zip
popD02_2013.rds.ComD02.TAB.TODO Calculer la jointure com_pop des deux jeux de données sur l’attribut codgeo, en calculant la densité de population et l’évolution de 2008 à 2013 en %.
com_pop
Simple feature collection with 816 features and 24 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 696994 ymin: 6859808 xmax: 790281 ymax: 6997000
Projected CRS: RGF93 / Lambert-93
# A tibble: 816 x 25
codgeo chef_lieu tncc dct dar dau99 dau10 typo_au2010 deu99 duu99 duu10 z90 z10 epc bv int_reg reg dep geometry libgeo
* <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <MULTIPOLYGON [m]> <chr>
1 02001 0 1 0203 022 248 998 300 1A "" "" 2232 2202 2402006~ 02173 NE 22 02 (((712717 6942795, 71199~ Abbéc~
2 02002 0 1 0218 022 999 998 300 1A "" "" 2232 2205 2402004~ 02738 NE 22 02 (((728639 6953410, 72807~ Achery
3 02003 0 1 0217 024 117 127 112 1A "" "" 2207 2206 2402004~ 02722 NE 22 02 (((731200.1 6913598, 730~ Acy
4 02004 0 1 0211 022 000 000 400 9Z "" "" 2242 2204 2402004~ 02468 NE 22 02 (((768060 6955198, 76720~ Agnic~
5 02005 0 1 0206 022 029 029 112 1A "" "" 2242 2204 2402005~ 51454 NE 22 02 (((769828 6920184, 76786~ Aguil~
6 02006 0 1 0207 025 000 998 300 9Z "" "" 2241 2205 2402004~ 02095 NE 22 02 (((736934 6979095, 73622~ Aison~
7 02007 0 1 0206 022 999 997 120 1A "" "" 2242 2204 2402005~ 51454 NE 22 02 (((760905 6931148, 75915~ Aizel~
8 02008 0 1 0205 024 999 997 120 1A "" "" 2207 2206 2402005~ 02722 NE 22 02 (((736093 6924183, 73584~ Aizy-~
9 02009 0 1 0212 023 074 074 112 1A "" "" 2231 2205 2000404~ 02691 NE 22 02 (((726606 6961580, 72541~ Alain~
10 02010 0 1 0205 024 999 127 112 1A "" "" 2207 2206 2402005~ 02018 NE 22 02 (((733662 6928092, 73222~ Allem~
# i 806 more rows
# i 5 more variables: pop13 <dbl>, pop08 <dbl>, surf <dbl>, dpop_habkm2 <dbl>, evol_pop_pcent <dbl>
# i Use `print(n = ...)` to see more rowsTODO Représenter la densité de population en aplat (carte choroplète).
TODO Habiller la carte avec titre, rose des vents, légende, échelle et crédits.
TODO Réaliser la carte d’évolution de la population communale du département de l’Aisne. On différenciera les évolutions positives et les évolutions négatives avec une palette adaptée (on pourra se passer de l’habillage).
TODO Reprendre la carte précédente en construisant cinq classes manuelles entre -20 et +20 avec des points de rupture à -/+10, -/+5 et 0.
TODO Habiller la carte précédente et l’exporter au format PDF au format 20 cm x 28.7 cm.