Premiers pas en cartographie avec R

La semaine dernière, j’ai fait mes premiers pas dans le domaine de la cartographie sous R. En réalité, c’était aussi un peu mes premiers pas en cartographie tout court, parce que mes connaissances étaient très basiques (niveau collège grand max), et qu’elles dataient de…..loin !
J’ai donc dû reprendre pas mal de choses. Et puis coté R, je me suis rendu compte qu’il existe plein de packages qui touchent aux objets spatiaux (sf, raster, sp, etc…) avec parfois des formats d’objet différents (un peu comme data frame et tibble) et plein de packages qui s’intéressent à la cartographie (ggmap, tmap, leaflet, cartography..etc). Sans compter qu’il existe aussi des formats de fichiers SIG (fichier de codage de l’information géographique) différents (shapefile, TIFF, ect…). J’ai vraiment eu du mal à m’y retrouver. Et même s’il y a encore plein de zones d’ombre, j’ai eu envie de partager mes avancées, en espérant aider au moins un peu, d’autres débutants.

Pour ceux qui maîtrisent le sujet, merci par avance d’être indulgent ! N’hésitez pas à contribuer à l’amélioration de cet article en laissant un commentaire !

Mon but

Si je me suis lancée dans la cartographie sous R, c’est parce que j’avais besoin de créer une carte avec les pays de l’Europe de l’Ouest, sur laquelle je pourrais afficher les valeurs de variables relatives à ce pays . Par exemple des statistiques de foot récupérées ici :

  ##           country score
    ## 1         Austria   769
    ## 2         Belgium  1465
    ## 3          Cyprus   495
    ## 4         Denmark   419
    ## 5         Finland    18
    ## 6          France  3300
    ## 7         Germany  4748
    ## 8          Greece  1020
    ## 9         Iceland     0
    ## 10        Ireland    32
    ## 11          Italy  4775
    ## 12          Malta     0
    ## 13    Netherlands  1692
    ## 14         Norway   219
    ## 15       Portugal  3245
    ## 16          Spain  8457
    ## 17         Sweden   246
    ## 18    Switzerland  1023
    ## 19 United Kingdom  6952 

Quelques notions de base de cartographie qui m'ont été utiles:

  • La Terre est une sphère, autrement dit un objet en 3 dimensions.
  • Sur cette sphère, un lieu est défini par des coordonnées géographiques qui sont la latitude et la longitude ; ce sont des mesures angulaires. Si vous avez besoin d’une piqûre de rappel, je vous
    conseille cette vidéo.
  • Ces angles peuvent être exprimés sous différents formats : en degrés sexa-décimaux: 43°49′43″ ou en degrés décimaux: 43°49.7298′Nord.
  • Une carte est un objet en deux dimensions.
  • Représenter une sphère sur une carte s’appelle une projection, et il en existe de trois grands types (conique, cylindrique et azimutal). Pour plus de détails, je vous conseille cette vidéo.
  • Sur une carte, les lieux sont aussi définis par des coordonnées, mais dans un environnement cartésien cette fois, c’est-à-dire en X et Y.
  • Dans cet environnement cartésien, la latitude correspond à l’axe des Y et la longitude à l’axe de X.
  • Il existe différentes unités pour exprimer la latitude et la longitude d’un lieux sur une carte :
    • en degrés décimaux : par exemple, 43.8333° de latitude et 5.78306° de longitude dans ce cas là, on est dans un référentiel appelé WGS84 (utilisé par les GPS).
    • en mètre, dans ce cas là, on est en projection Lambert93, par exemple X : 923825 Y : 6307755.

Mon point de départ concernant R pour la cartographie

  • L’utilisation du package ggmap n’est pas envisageable car il faut avoir un compte google map qui nécessite d’entrer une carte bancaire : je n’ai pas envie !
  • Le package leaflet permet d’avoir un fond de carte provenant d’Open Street Map : j’ai déjà essayé vite fait, il y a deux ou trois ans.
  • La représentation d’un pays sur un fond de carte fait appel à la notion de polygons.
  • Il existe plusieurs formats d’objets spatiaux et ils ont l’air assez compliqués !
  • Il existe plein de package pour faire de la cartographie !
  • Sébastien Rochette a écrit un article d’initiation à la cartographie, qui me sera sans doute utile.

Mon cheminement

Le fond de la carte avec leaflet

Pour obtenir ce fond de carte, je me suis appuyé sur la vignette de “leaflet” qui est vraiment très bien faite.

J’ai utilisé la fonction `fitBounds()` pour limiter le fond de carte. J’ai trouvé cette fonction dans l’onglet AdditionalFeatures. Les arguments à fournir sont long1, lat1, lng2, lat2, tels que définis dans la page d’aide :

C’est-à-dire les longitudes et les latitudes min et max de la fenêtre qu’on souhaite afficher.

Pour les déterminer :

  • je suis allée sur Open Street Map
  • je me suis positionné sur deux pays extrêmes : l’Islande et la Grèce, et j’ai recueilli leur coordonnées ( Island : 65, -20, Grèce :40,20).
library(leaflet)
    leaflet() %>% 
        fitBounds(-20,65,20,40) %>% 
        addTiles() 

C’était pas trop mal, mais je voulais les noms des pays en anglais ! J’ai donc essayé plusieurs fonds de carte avec la fonction `addProviderTiles()`(trouvé dans l’onglet BaseMap du tuto leaflet).
L’option `CartoDB.Positron` me convenait assez, même si j’aurais préféré voir les mers et océans en bleu, plutôt qu’en gris !

leaflet() %>%
fitBounds(-20,65,22,39) %>%
addProviderTiles(providers$CartoDB.Positron) 

Pour vous amuser, vous pouvez essayer :

  • `addProviderTiles(providers$Stamen.Toner)`
  • `addProviderTiles(providers$Esri.NatGeoWorldMap)`
  • `addProviderTiles(“Stamen.Watercolor”)`
  • `addProviderTiles(“Stamen.TonerHybrid”)`

Il y en a d’autres de disponibles, vous trouverez une liste ici, certains nécessitent une inscription au préalable (pas testé !).

Ajouter un contour sur les pays

C’est là, que l’affaire s’est corsée ! Pour ajouter des contours sur une carte leaflet, il faut des données de contour ! Et ces données il faut aller les chercher dans un fichier de format shapefile, qu’il faut lui-même aller chercher quelle que part sur internet ! Ça n’a l’air de rien, mais comprendre ça c’est déjà une victoire  ! Merci Sandrine Roux !

A la recherche d'un fichier shapefile

A cette étape, je me suis dit que je trouverais peut être ça sur le site d’Eurostats , puisque je l’avais déjà un peu exploré pour cet article “A la découverte des statistiques européennes d’Eurostat“et que j’avais vu des cartes. Bonne pioche !

Comme je ne savais pas trop quelle échelle choisir, j’ai pris celle du milieu !

Le ficher zip comportait de nombreux autres dossiers compressés:

J’ai choisi d’utiliser le dossier “CNTR_RG_10M_2016_4326.shp” car en lisant le fichier “release_notes.txt”, j’ai vu que :

  • RG correspond aux “regions (multipolygons)” (je savais que j’avais besoin de polygons )
  • 4326 correspond au référentiel WGS84, avec des coordonnées en degrés décimal, et que ça me semblait “courant”.

Contenu du fichier shapefile

Au final j’ai décompressé le fichier “CNTR_RG_10M_2016_4326.shp” et j’ai placé les 5 fichiers qu’il contient dans un dossier “data_carto” lui même à la racine de mon projet R, comme ça :

Pour plus de détail sur ces différents fichiers, vous pouvez consulter cette page.

L'importation dans R

En lisant cette page, j’ai vu que le fichier .DBF pouvait être ouvert avec Excel. En le faisant (d’abord ouvrir Excel, puis aller chercher le fichier), j’ai vu que les données concernaient tous les pays du monde et pas que l’Europe. J’allais donc être obligé de sélectionner les pays de l’Europe de l’Ouest qui m’intéressaient.

Je me suis alors souvenu d’un article de blog de Sébastien Rochette (Initiation à la cartographie avec sf et compagnie) dans lequel il sélectionnait des départements à partir des données de tous les départements de la France :

Cet article m’a été d’une grande aide, car j’ai appris qu’en important mes données shapefile avec la fonction `st_read()` du package `sf` elles allaient devenir une table de données classiques et que je pourrais utiliser les fonctions du `tidyverse` pour filtrer les lignes des pays qui m’intéressaient !

library(tidyverse)
library(sf)

# importation des données shapefile
Monde <- st_read(here::here("data_carto","CNTR_RG_10M_2016_4326.shp"), quiet=TRUE) 

head(Monde)

Simple feature collection with 6 features and 5 fields
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: -63.1112 ymin: 16.99742 xmax: 74.88986 ymax: 42.65309
geographic CRS: WGS 84
  CNTR_ID
1      AD
2      AE
3      AF
4      AG
5      AI
6      AL
                                                                                                                                                                           CNTR_NAME
1                                                                                                                                                                            Andorra
2 <U+0627><U+0644><U+0625><U+0645><U+0627><U+0631><U+0627><U+062A> <U+0627><U+0644><U+0639><U+0631><U+0628><U+064A><U+0629> <U+0627><U+0644><U+0645><U+062A><U+062D><U+062F><U+0629>
3                                  <U+0627><U+0641><U+063A><U+0627><U+0646><U+0633><U+062A><U+0627><U+0646>-<U+0627><U+0641><U+063A><U+0627><U+0646><U+0633><U+062A><U+0627><U+0646>
4                                                                                                                                                                Antigua and Barbuda
5                                                                                                                                                                           Anguilla
6                                                                                                                                                                          Shqipëria
             NAME_ENGL ISO3_CODE FID
1              Andorra       AND  AD
2 United Arab Emirates       ARE  AE
3          Afghanistan       AFG  AF
4  Antigua and Barbuda       ATG  AG
5             Anguilla       AIA  AI
6              Albania       ALB  AL
                        geometry
1 MULTIPOLYGON (((1.7258 42.5...
2 MULTIPOLYGON (((56.26584 25...
3 MULTIPOLYGON (((74.88986 37...
4 MULTIPOLYGON (((-61.65852 1...
5 MULTIPOLYGON (((-63.1112 18...
6 MULTIPOLYGON (((20.0763 42....
 

Sélection des pays d'intérêt

Pour cela, j’ai récupéré la liste des pays qui m’intéressaient dans le fichier data_footet j’ai filtré les lignes correspondante dans le fichier “Monde”,(variable NAME_ENGL) en utilisant la fonction filter() de dplyr:

# pays d'intérêt

my_countries<-data_foot$country        

# selection des données shapefile pour les pays d'interet
Europe_Ouest <- Monde %>% 
        dplyr::filter(NAME_ENGL %in% my_countries) 

Ajout sur la carte leaflet

Pour cela, j’ai utilisé la fonction addPolygons() :

 leaflet() %>% 
        fitBounds(-20,65,20,40) %>% 
         addProviderTiles(providers$CartoDB.Positron) %>% 
         addPolygons(data=Europe_Ouest,weight = 2, color="orange",fillOpacity=0.35 

C’était déjà pas mal, mais je me suis dit que je pourrais renforcer le blanc sur les pays qui ne m’intéressent pas. Pour cela, j’ai filtré comme précédemment leurs lignes à partir du fichier Monde et j’ai ajouté l’option `fillOpacity=0.65` dans une seconde fonction `addPolygons()` que j’ai
placé en premier pour que les polygons orange des pays d’intérêt recouvrent le blanc :

Autre <- Monde %>% 
        dplyr::filter(! NAME_ENGL %in% my_countries )

leaflet() %>% 
         fitBounds(-20,65,20,40) %>% 
         addProviderTiles(providers$CartoDB.Positron) %>%  
         addPolygons(data=Autre,weight = 2, color="white",fillOpacity=0.65)  %>% 
         addPolygons(data=Europe_Ouest,weight = 2, color="orange",fillOpacity=0.35) 

Ajout de valeurs sur la carte

Collecte des coordonnées gps du centre des pays

Pour ajouter mes scores de foot sur la carte, il a fallu que je récupère les coordonnées des pays. Pour cela, j’ai utilisé les packages `rworldmap` et `rgeos` qui permettent d’obtenir les coordonnées des centroides de tous les pays du monde :

library(rworldmap)
    library(rgeos)

    # get world map
    wmap <- getMap(resolution="high")

    # get centroids
    centroids <- gCentroid(wmap, byid=TRUE)

    # get a data.frame with centroids
    centroid_df <- as.data.frame(centroids)


    # affichage des premières lignes
    head(centroid_df)

    ##                     x         y
    ## Aruba       -69.98267  12.52089
    ## Afghanistan  66.00473  33.83523
    ## Angola       17.53736 -12.29336
    ## Anguilla    -63.06498  18.22397
    ## Albania      20.04983  41.14245
    ## Aland        19.95325  60.21490 

J’ai ensuite modifié les noms “x” et “y” en “long” et “lat”.

centroid_df <- centroid_df %>% 
        mutate(country=rownames(.)) %>% 
        rename(lat=y, long=x)


head(centroid_df)

    ##        long       lat     country
    ## 1 -69.98267  12.52089       Aruba
    ## 2  66.00473  33.83523 Afghanistan
    ## 3  17.53736 -12.29336      Angola
    ## 4 -63.06498  18.22397    Anguilla
    ## 5  20.04983  41.14245     Albania
    ## 6  19.95325  60.21490       Aland 

Si vous avez besoin de collecter d’autres types de coordonnées gps (par exemple celles d’une gare), je vous conseille de consulter l’article de Marie Vaugoyeau : ‘Visualiser des zones géographiques autour de points d’intérêt avec leaflet” . A la fin de celui-ci, Marie donne une astuce pour le faire avec Open Cage Data !

Ajout des coordonnées aux données

J’ai ensuite sélectionné uniquement les pays de l’Europe de l’Ouest qui m’intéressaient :

centroid_europe <- centroid_df %>%
filter(country %in% my_countries) 

Et j’ai ajouté leur coordonnées dans la table des données de foot, en utilisant la fonction left_join(). Pour plus d’infos sur les jointures, vous pouvez consulter cet article , et celui là.

data_foot<- left_join(data_foot, centroid_europe)
head(data_foot)

    ##   country score      long      lat
    ## 1 Austria   769 14.126478 47.58550
    ## 2 Belgium  1465  4.640646 50.63981
    ## 3  Cyprus   495 33.006004 34.91667
    ## 4 Denmark   419 10.027994 55.98126
    ## 5 Finland    18 26.274670 64.49885
    ## 6  France  3300  2.536185 46.18701 

Gestion de leaflet

Pour ajouter les scores sur la carte, j’ai utilisé la fonction addLabelOnlyMarkers()

leaflet() %>% 
         fitBounds(-20,65,20,40) %>% 
         addProviderTiles(providers$CartoDB.Positron) %>%  
         addPolygons(data=Autre,weight = 2, color="white",fillOpacity=0.65)  %>% 
         addPolygons(data=Europe_Ouest,weight = 2, color="orange",fillOpacity=0.35) %>% 
         addLabelOnlyMarkers(data=data_foot,
                            label=~as.character(score), 
                            labelOptions = labelOptions(noHide = T, direction = 'center', textOnly = T,textsize="13px")) 

Là, j’ai trouvé que ça manquait un peu de visibilité, et je me suis dit que ça serait mieux avec des cercles de couleurs qui seraient d’autant plus gros que la valeur du score est importante. Pour ajouter cela, l’article “Les bases de la cartographie dynamique avec R Leaflet” d’Aline Deschamps m’a été très utile. J’ai alors utilisé la fonction`addCircle()`, et j’ai un peu tâtonné pour régler la dimension des rayons des cercles.

leaflet() %>% 
     fitBounds(-20,65,20,40) %>% 
     addProviderTiles(providers$CartoDB.Positron) %>%  
     addPolygons(data=Autre,weight = 2, color="white",fillOpacity=0.65)  %>% 
     addPolygons(data=Europe_Ouest,weight = 2, color="orange",fillOpacity=0.35) %>% 
        addLabelOnlyMarkers(data=data_foot,
                        label=~as.character(score), 
                        labelOptions = labelOptions(noHide = T, direction = 'center', textOnly = T,textsize="12px"))  %>% 
    addCircleMarkers(data=data_foot, radius=~sqrt(score)/4,weight = 1, color = "#a500a5", fillOpacity = 0.5) 

Le rendu final, me convient assez. Néanmoins, j’aurais bien voulu avoir les mers et océans en bleu plutôt qu’en gris, j’ai essayé plein de chose et je n’ai pas réussi. Donc si vous savez comment faire, dites le moi en commentaire !

Si cet article vous a plu, ou vous a été utile, et si vous le souhaitez, vous pouvez soutenir ce blog en faisant un don sur sa page Tipeee 🙏

13 réponses

  1. Merci Claire pour cet article. je me suis essayé, sauf que je me suis heurté à la fonction “st_read” qui n’a pas fonctionné chez moi. Donc je n’ai pas pu paramétrer à ma convenance. Peut-on contourner le problème?
    Avez-vous une idée de l’écriture des opérateurs de la physique (divergence, rotationel, gradient…) en langage r ?

    merci encore pour tout.

  2. Bonjour Claire

    Merci pour ce tutoriel ! Je suis vraiment un débutant sur R et cet article tombe bien, car j’aimerai faire une carte. J’espère y arriver

  3. Bonjour Claire,

    Merci beaucoup pour ce tutoriel, très clair.
    Je suis étudiante en cartographie et cela m’a permis de me remettre
    en tête des éléments abordés trop rapidement en cours.

    Je rencontre cependant un problème que vous ne semblez pas avoir sur vos captures d’écran. Lors de l’affichage des Labels, celui de la France
    est attiré vers le Sud, au niveau de l’Espagne ; je crois comprendre que cela vient du calcul du centroïde , qui prend en compte les outre-mer et donc qui se décale forcément.
    Avez vous rencontré cette difficulté ?

    Bien cordialement

  4. Bonsoir,
    Je rencontre un problème à l’étape ajout sur la carte leaflet : Don’t know how to get path data from object of class data.frame.
    Je pense que j’ai loupé l’étape importation dans R du fichier shp. En fait j’ai ouvert comme vous disiez le fichier dans Excel et je l’ai enregistré avec le nom Monde. Ensuite je l’ai enregistré dans R avec le code suivant:
    Monde<-read.csv2("Monde.csv",h=T,sep=";")

    Je vous remercie par avance pour votre aide.
    Bien cordialement

    1. Bonjour,
      votre commentaire m’a permis de me rendre compte que les lignes de code de l’importation étaient passées à la trappe…c’est rectifié !
      Merci
      Bonne continuation

  5. Bonjour Claire,

    Tout d’abord merci Claire pour cet article.
    Je suis étudiante en statistique et j’essaye de construire ma première carte avec R.
    Je me trouve face à une problématique, où j’ai des coordonnées géographiques en degrés qui ressemblent à ceci : 48°08’57”78.

    Y’a t-il un moyen de faire une carte avec ces coordonnées sans passer par la conversion en décimaux ?

    En vous remerciant par avance.

    1. Bonjour,

      je ne sais pas bien je me perds tout le temps dans ces conversions….
      Bon courage, et n’hésitez pas à partager votre solution avec un nouveau commentaire.

  6. Bonjour,

    Avec le package sf, il y a une fonction qui s’appelle st_centroid(objet sf) qui permet de calculer directement le centroide d’une géométrie. Quant aux labels, on peut les insérer directement dans les addCircleMarkers. Je ne sais plus par contre si il y a encore la possibilité de ne pas cacher les labels comme vous l’avez fait avec l’argument noHide = TRUE. Cela permettrait d’économiser quelques lignes

    Bien cordialement

    1. Bonjour Yoann,

      merci pour votre commentaire.
      Je connais vraiment mal ce package alors c’est vraiment utile de partager ces informations.
      Bien à vous

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Bonjour !

vous venez souvent ?

Identifiez-vous pour avoir accès à toutes les fontionnalités !

Aide mémoire off'R ;)

Enregistrez vous pour recevoir gratuitement mes fiches “aide mémoire” (ou cheat sheets) qui vous permettront de réaliser facilement les principales analyses biostatistiques avec le logiciel R et pour être informés des mises à jour du site.