rCarto, un package de cartographie statistique

Deuxièmes Rencontres R

Lyon, 27 et 28 juin 2013
Timothée Giraud, UMS RIATE
timothee(point)giraud(at)ums(tiret)riate(point)fr


Résumé

Une rapide recherche du terme « maps » dans l'agrégateur de blogs « R-bloggers » renvoie à de nombreux billets comprenant des cartes produites avec R, ou même des tutoriaux complets. L'intérêt pour la cartographie semble assez fort dans la communauté des utilisateurs.
L'utilisation de R permet la conception automatisée de cartes tout en minimisant les ruptures dans la chaîne logicielle partant des données et aboutissant à la carte.
Après une rapide revue critiques des solutions régulièrement employées (I), nous présenterons un exemple de cartographie statistique respectueuse de la sémiologie graphique et comprenant les éléments d’habillage indispensables à ce type de représentation (II).
Nous aborderons plus précisément le package rCarto (III) qui propose plusieurs types de cartes statistiques et des exemples permettrons d’explorer dans le détail les paramètres des fonctions disponibles dans ce package.

Bibliographie

Beguin, M., Pumain, D. (2000), La représentation des données géographiques : statistiques et cartographie, coll. Cursus Armand Colin, 2e édition

Beauguitte, L., Giraud, T. (2012). Cartographier avec le logiciel R, http://quanti.hypotheses.org/795/

Giraud, T., Severo, M. (2012). Visualisation de données médiatiques et géographiques avec R. Représenter et visualiser des données avec R - Séminaire Ined SMS, http://wukan.ums-riate.fr/wukan

MacEachren, A. M. (2004). How maps work: representation, visualization, and design. The Guilford Press.

I. Quelques solutions générales de cartographie avec R

Ces billets de blogs proposent différentes solutions utilisant différents packages, les codes mis à disposition sont plus ou moins détaillés et accessibles Les cartes présentes dans ces posts sont de natures différentes : certaines sont des cartes statistiques, d'autres sont des cartes de situation, d'autres encore des cartes d'analyse spatiale ; certaines cartes sont interactives (SVG, utilisation de googlemap ou de openstreetmap), d'autres statiques…

Rappelons tout d'abord que la plus part des cartes présentées dans ces blogues ne sont pas des cartes finies et publiables.
La démarche de publication de ces post est surtout celle du partage d'expérience.
Il est donc logique que ces exemples ne soient pas finalisés. Notons également que les utilisateurs créant des cartes avec R sont rarement cartographes ou géographes.

Les problèmes

Un grand nombre de ces cartes ne sont pas complètes dans le sens ou certains éléments nécessaires à la compréhension du message de la carte sont négligés.
De plus certaines options sémiologiques semblent plus guidés par des facilités techniques que par des choix réfléchis.

Plusieurs cartes ont également des problèmes assez important de respect des règles de cartographie.

Généralités

Toutes ces cartes sont globalement construites de la même manière :

  1. construction d'un jeu de données avec une référence spatiale (coordonnées XY ou référence à un identifiant spatiale)
  2. importation d'un fond de carte
  3. liaison entre les données et les fonds de carte
  4. affichage des données
  5. ajout d'un habillage (légende, titre…)

    Les 3 premiers points peuvent être traités en utilisant différents packages et selon des techniques légèrement différentes mais les principes généraux restent les mêmes et ces opérations ne posent pas de problème.

    Les points 4 et 5 sont ceux qui peuvent poser problème. Les différences entre les solutions sont d'ordre technique (ggplot ou lattice?, points ou symbols?) et sémiologique (coloration continue ou discrétisation? symboles proportionnels ou classe de taille?). Il est fréquent que les solutions techniques soient indifférentes

II. Un exemple de cartographie statistique

Le cadre

Alt text MacEachren, 1994

Si l'on se réfère à la figure ci-dessus l'objectif sera ici la communication.

Nous nous plaçons donc à l'extrémité de la dimension transversale vizualisation–communication de ce cube. Notons que de nombreux exemples listés plus haut se trouvent plutôt dans la démarche inverse.

Créer une carte en symboles proportionnels :

  1. Import du fond de carte : readShapeSpatial()
  2. Création d'un dataframe avec les coordonnées des centroides des communes : coordinates()
  3. Jointure entre le dataframe des coordonnées des centroides et les données à cartographier : merge()
  4. Création d'une variable contenant les rayons des cercles à représenter
  5. Tri du dataframe de manière à ce que les cercles soient dessinés du plus gros au plus petit
  6. Affichage de la carte : plot() + symbols()
  7. Affichage de la légende (dessin)
  8. Titre et sous titres
# chargement du package rCarto qui ne sera utilisé que pour les données
# qu'il contient
library(rCarto)

# import du fd de carte
fileShp <- file.path(path.package("rCarto"), "shapes/COMMUNE")
fdc <- readShapeSpatial(fileShp)

# création d'un dataframe avec les coordonnées des centroides des communes
pt <- cbind(fdc@data[, "INSEE_COM"], as.data.frame(coordinates(fdc)))

# renommage des colonnes de ce dataframe
colnames(pt) <- c("Code", "x", "y")

# import des données
data(mtq)

# jointure entre le dataframe des coordonnées des centroides et les
# données à cartographier
pt <- merge(pt, mtq, by.x = "Code", by.y = "ID", all.x = TRUE)

# extension maximale du fond de carte la fonction bbox donne les
# coordonnées max et min du fond de carte
x1 <- bbox(fdc)[1]
y1 <- bbox(fdc)[2]
x2 <- bbox(fdc)[3]
y2 <- bbox(fdc)[4]

# surface maximale de la carte
sfdc <- (x2 - x1) * (y2 - y1)

# somme de la variable à cartographier
sc <- sum(pt$P09_POP, na.rm = TRUE)

# création d'une variable contenant les rayons des cercles à représenter
pt$var <- sqrt((pt$P09_POP * 0.04 * sfdc/sc)/pi)  #la somme des surfaces des cercles
# représentera ici 4% (0.04) de la surface de la carte

# tri du dataframe de manière à ce que les cercles soient dessiner du plus
# gros au plus petit
pt <- pt[order(pt$var, decreasing = TRUE), ]

# affichage de la carte
plot(fdc, border = "Grey", col = "#FEE08B", ann = FALSE)
symbols(pt[, c("x", "y")], circles = pt$var, add = TRUE, bg = "#CCEBC5", inches = FALSE)

# affichage de la légende (dessin)
rLeg <- quantile(pt$var, c(1, 0.9, 0), type = 1, na.rm = TRUE)
rVal <- quantile(pt$P09_POP, c(1, 0.9, 0), type = 1, na.rm = TRUE)
l <- NA
l$x <- x1
l$y <- y1
xinit <- l$x + rLeg[1]
ypos <- l$y + rLeg
symbols(x = rep(xinit, 3), y = ypos, circles = rLeg, add = TRUE, bg = "#C7E9C0", 
    inches = FALSE)
text(x = rep(xinit, 4) + rLeg[1] * 1.2, y = (l$y + (2 * rLeg)), rVal, cex = 0.7, 
    srt = 0, adj = 0)
for (i in 1:3) {
    segments(xinit, (l$y + (2 * rLeg[i])), xinit + rLeg[1] * 1.1, (l$y + (2 * 
        rLeg[i])))
}
text(x = xinit - rLeg[1], y = (l$y + (2 * rLeg[1])), "Population résidente\n", 
    adj = c(0, 0), cex = 0.7)

# titre et sous titres
title(main = paste("Répartition de la population\nen Martinique"), sub = "Auteur: T. Giraud, UMS RIATE, 2012\nSource: INSEE, 2009", 
    cex.sub = 0.8)

plot of chunk unnamed-chunk-1

III. rCarto

Installation du package

install.packages("rCarto", dependencies = TRUE)

Une première carte simple

library(rCarto)
data(mtq)
fileShp <- file.path(path.package("rCarto"), "shapes/COMMUNE")
mapCircles(shpFile = fileShp, shpId = "INSEE_COM", df = mtq, dfId = "ID", var = "P09_POP")

Alt text

Carte en cercles proportionnels

library(rCarto)
data(mtq)
fileShp <- file.path(path.package("rCarto"), "shapes/COMMUNE")
mapCircles(shpFile=fileShp,                                    # chemin du shapefile
           shpId="INSEE_COM",                                  # champ des identifiants du shapefile
           df=mtq,                                             # nom du dataframe
           dfId="ID",                                          # champ des identifiants du dataframe
           var="P09_POP",                                      # variable à représenter
           shareOfCircle=0.1,      # part de la surface de la carte occupée par les cercles 
           posLeg="topright",                                  # position de la légende
           circleCol="tan1",                                   # couleur des cercles
           baseCol="honeydew",                                 # couleur du fond de carte
           title="Distribution de la population\nen Martinique", # titre  de la carte
           legend="Population\nrésidente en 2009",             # titre de la légende
           author=Sys.getenv("USERNAME"),                      # auteur ou autre texte
           sources="Données : INSEE, 2009 ; fond de carte : IGN, 2012", # source ou autre texte
           scalebar=TRUE,                                      # échelle  
           scalebarSize=5000,                                  # taille de l'echelle
           scalebarText="5 km",                                # texte de l'échelle
           northArrow=TRUE,                                    # flèche nord
           northArrowSize=5000)                                # taille de la flèche nord  

Alt text

Carte Choroplèthe

library(rCarto)
data(mtq)
fileShp <- file.path(path.package("rCarto"), "shapes/COMMUNE")
# calcul de la part des moins de 15 ans dans la population
mtq$pct0014_09 <- mtq$P09_POP0014/mtq$P09_POP*100 
mapChoropleth(shpFile=file.path(path.package("rCarto"), "shapes/COMMUNE"),#
              shpId="INSEE_COM",df=mtq,dfId="ID",var="pct0014_09",
              style="quantile",nclass=6,
              lgdRnd=1,
              palCol="Greens",
              title="Part des jeunes dans\nla population en Martinique",  
              legend="Part des 0-14 ans\ndans la population total\nen2009",
              author="Discrétisation : effectifs égaux",
              sources="Auteur : T. Giraud - Sources : INSEE, 2009 ; IGN, 2012",
              scalebar=TRUE,scalebarSize=5000,scalebarText="5 km",
              northArrow=TRUE,northArrowSize=5000)

Alt text

Carte Choroplèthe, double gamme de couleur, discrétisation “à la main”

library(rCarto)
data(mtq)
fileShp <- file.path(path.package("rCarto"), "shapes/COMMUNE")
# calcul du taux de croissance annuel moyen de la population
mtq$POPVAR <- (((mtq$P09_POP/mtq$P99_POP)^(1/10)) - 1) * 100

# calcul manuel des bornes de la discrétisation (basée sur la moyenne et l'écart-type, avec la moyenne comme centre de classe et l'écart-type comme étendue)
brks <- mean(mtq$POPVAR)+c(4.5,3.5,2.5,1.5,0.5,-0.5,-1.5,-2.5,-3.5,-4.5)*sd(mtq$POPVAR)
listBrks <- c(max(mtq$POPVAR),brks[brks>min(mtq$POPVAR)&brks<max(mtq$POPVAR)],min(mtq$POPVAR))
nbclass <- length(listBrks)-1

mapChoropleth(shpFile=file.path(path.package("rCarto"), "shapes/COMMUNE"),#
              shpId="INSEE_COM",df=mtq,dfId="ID",var="POPVAR",
              fixBrks=TRUE,listBrks=listBrks,
              diverg=TRUE,divergBrk=mean(mtq$POPVAR),
              lgdRnd=2,posLeg="bottomleft",
              palColPos="Greens",palColNeg="Blues",NACol="grey",
              title="Dynamique de la population\nen Martinique",  
              legend="Taux de croissance\nannuel moyen de la\npopulation (1999-2009)",
              author=Sys.getenv("USERNAME"),
              sources="Données : INSEE, 2009 ; fond de carte : IGN, 2012",
              scalebar=TRUE,scalebarSize=5000,scalebarText="5 km",
              northArrow=TRUE,northArrowSize=5000)

Alt text

Carte de cercles proportionnels à une variable de stock et colorés selon la discrétisation d’une variable quantitative

mapCirclesChoro(shpFile=file.path(path.package("rCarto"), "shapes/COMMUNE"),#
                shpId="INSEE_COM",df=mtq,dfId="ID",var2="POPVAR",var="P09_POP",
                shareOfCircle=0.1,
                lgdRndCircles=0,
                fixBrks=TRUE,listBrks=listBrks,
                diverg=TRUE,divergBrk=mean(mtq$POPVAR),palColPos="Greens",
                title="Dynamique de la population\nen Martinique",
                legendCircles="Population résidente\nen 2009",
                legendDistr="Taux de croissance\nannuel moyen de la\npopulation (1999-2009)",
                author=Sys.getenv("USERNAME"),
                sources="Données : INSEE, 2009 ; fond de carte : IGN, 2012",
                scalebar=TRUE,scalebarSize=5000,scalebarText="5 km",
                northArrow=TRUE,northArrowSize=5000)

Alt text

Cartes choroplèthes colorées selon les modalités d’une variable qualitative

# classification des communes en fonction de leur accès aux plages
mtq[c(1, 12, 18, 23, 33, 8, 24), "beach"] <- "Pas d'accès aux plages"
mtq[c(2, 4, 5, 6, 9, 13, 17, 20, 21, 25, 26, 29, 31, 34, 11, 27, 7, 19), "beach"] <- "Mer des Antilles"
mtq[c(14, 5, 16, 22, 28, 30, 32, 10, 3), "beach"] <- "Ocean Atlantique"
mtq[c(26, 17, 11), "beach"] <- "Accès aux deux mers"

# carte représentant des données qualitatives - Accès aux plages
mapChoroTypo(shpFile = file.path(path.package("rCarto"), "shapes/COMMUNE"), 
    width = 5, shpId = "INSEE_COM", df = mtq, dfId = "ID", var = "beach", posLeg = "bottomleft", 
    title = "Accès aux plages martiniquaises", legend = "Quel accès?", palCol = "Set1", 
    author = Sys.getenv("USERNAME"), sources = "Données : l'auteur ; fond de carte : IGN, 2012", 
    scalebar = TRUE, scalebarSize = 5000, scalebarText = "5 km", northArrow = TRUE, 
    northArrowSize = 5000)