Cartes minimalistes

#R #programmation #données #minimalisme #tutoriel #méthodologie

10 septembre 2015

 
JPEG - 225.5 kio

Il y a quelques jours j’ai relayé sur twitter ces images vues sur le site imgur, sans explication ni mention d’auteur. Piqué par une question de Matthew Champion qui me demandait comment j’avais fait ces cartes (ce n’était pas le cas), je me suis pris au jeu de les reproduire avec mon langage de programmation favori, R.

Par Arthur Charpentier

statisticien, économiste, animateur du blog Freakonometrics

Le logiciel R peut être installé, librement et gratuitement, depuis un des dépôts du CRAN (Comprehensive R Archive Network), ou, pour un éditeur plus convivial, via RStudio. Une des richesses de R, c’est sa (vaste) communauté d’utilisateurs, qui partagent des librairies de fonctions (appelées packages), par exemple en cartographie. Ces librairies proposent divers outils comme des fonctions ou des bases de données.

Pour installer un package, on emploie la commande
install.packages("maps",dependencies=TRUE,repos='http://cran.us.r-project.org')

Cette instruction va installer sur notre disque dur les divers objets du package maps. Ces fonctions doivent ensuite être chargées en mémoire, avec l’instruction :
library(maps)

1. Les villes

Le package maps contient, entre autres choses, une base de la localisation des principales villes du monde, dont on peut afficher un extrait de quelques lignes ainsi :
data("world.cities")
tail(world.cities[,c(1,2,4,5)])

name country.etc lat long
43640 az-Zubarah Qatar 26.12 51.17
43641 az-Zubayr Iraq 30.39 47.71
43642 az-Zulfi Saudi Arabia 26.30 44.80
43643 az-Zuwaytinah Libya 30.95 20.12
43644 s-Gravenhage Netherlands 52.07 4.30
43645 s-Hertogenbosch Netherlands 51.68 5.30

Les quatre colonnes de données affichées sont : le nom de la ville (1), son pays (2), sa latitude (4) et sa longitude (5). (La base contient d’autres éléments, comme par exemple la population, champ numéro 3.)

Pour obtenir le premier graphique, on emploie la fonction plot(), qui trace des points, en indiquant les longitude (world.cities$lon) et latitude (world.cities$lon) de chaque ville, avec des points pleins (option pch=19) et pas trop gros (cex=.7) — n’oublions pas qu’il y a 43 645 points à représenter sur la “carte” —, sans dessiner ni axe ni libellés :

plot(world.cities$lon,world.cities$lat,pch=19,cex=.7,axes=FALSE,xlab="",ylab="")

PNG - 94.6 kio

L’image est un peu trop dense à notre goût, on va la simplifier en affichant moins de points. Par exemple, en se limitant aux villes de plus de 100 000 habitants. Le plus simple est de filtrer le contenu pour n’en retenir qu’une sous-base :
world.cities.sub = subset(world.cities,pop>100000)
et de reprendre le code précédent
plot(world.cities.sub$lon,world.cities.sub$lat,pch=19,cex=.7,axes=FALSE,xlab="",ylab="")

Cette fois, seules 4 251 villes sont représentées.

PNG - 88.1 kio

2. Les aéroports

Dans la plupart des situations, les données nécessaires pour créer une carte ne se trouvent pas dans un package, et il convient de les trouver sur un site.

C’est le cas pour la localisation des aéroports. Les bases de données proposées par le site openflights.org en référencent près de 7 000. Une base plus petite (probablement uniquement les aéroports internationaux) se trouve sur le site Natural Earth. Il faut télécharger, puis importer la base sous R.

loc="http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_airports.zip"
download.file(loc,destfile="data/aeroports.zip").
Ce fichier au format zip doit être décompressé :
unzip("data/aeroports.zip", exdir="data/aeroports/")

On obtient ainsi un ensemble de fichiers, qui composent un shapefile ; ils contiennent des objets géoréférencés, comme des lignes, des polygones ou des points. Pour importer ce shapefile dans R, il convient d’installer le package dédié :
install.packages("maptools",repos='http://cran.us.r-project.org')

on charge ensuite les fonctions en mémoire, et on utilise la fonction readShapePoints() (la base des aéroports est une collection de points géographiques).
library(maptools)
shape <- readShapePoints("data/aeroports/ne_10m_airports.shp")

plot(shape,pch=19,cex=.7)

PNG - 81.1 kio

3. Les ports maritimes

Tant qu’on est sur un format de points, le processus est toujours le même. La seule difficulté est de trouver les bases localisant des points intéressants.

Autre exemple, les ports se trouvent aussi sur Natural Earth :

loc="http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_ports.zip"
download.file(loc,destfile="data/ports.zip")
unzip("data/ports.zip", exdir="data/ports/")
shape <- readShapePoints("data/ports/ne_10m_ports.shp")
plot(shape,pch=19,cex=.7)

JPEG - 66.1 kio

4. Les rivières

Une base de données des rivières sur trouve sur github.com/jjrom/hydre. Ces données sont un peu plus difficiles à récupérer, car elles ne sont pas au format zip mais en 7 fichiers à télécharger individuellement.

Cette fois-ci, ce qu’on veut visualiser n’est pas constitué de points, mais de lignes. On importe la base avec la fonction readShapeLines().

shape <- readShapeLines("GRDC_687_rivers.shp")

Cet objet est un peu plus complexe que le précédent. Chaque “rivière” est une collection de lignes. Il y en a ici 687. La troisième rivière de la liste est décrite par l’objet shape@lines[[3]], qui est une liste composée de lignes, correspondant à autant de tronçons de rivière que nécessaire. Ainsi, le cinquième tronçon de la troisième rivière est caractérisé par les points
shape@lines[[3]]@Lines[[5]]

## An object of class « Line »
## Slot « coords » :
## [,1] [,2]
## [1,] -161.9773 61.56081
## [2,] -162.0067 61.55999
## [3,] -162.0303 61.56082
## [4,] -162.0411 61.56194
## [5,] -162.0697 61.56777
## [6,] -162.0817 61.57639
## [7,] -162.0855 61.58250
## [8,] -162.0864 61.58860
## [9,] -162.0783 61.59749
## [10,] -162.0725 61.60139
## [11,] -162.0650 61.60500
## [12,] -162.0378 61.61361
## [13,] -162.0269 61.61583
## [14,] -162.0125 61.61694
## [15,] -161.9892 61.62110
## [16,] -161.9745 61.62838

Visuellement, on va relier ces points par des segments ; l’opération est plus lourde, car on traite des centaines de milliers de coordonnées. La commande à utiliser est :
plot(shape,col="blue")

JPEG - 150.6 kio

5. Les routes

Pour les routes, on a compris. Il suffit de trouver la base, de l’importer, de la lire, et de la visualiser. Avec là encore un simple appel de la fonction plot() pour garder une forme minimaliste.

La base est sur Natural Earth à l’adresse http://www.naturalearthdata.com/htt... ; les fonctions readShapeLines et plot(shape,pch=19,lwd=.7) nous permettent de tracer la carte.

JPEG - 107 kio

(Un lecteur nous signale qu’il y a sur notre carte des “routes” reliant l’Islande, la Norvège et la Grande-Bretagne ; ce sont probablement des ferry.)

6. Les lacs

Les lacs se trouvent eux aussi sur le site Natural Earth. Cette fois, les objets sont des polygones, c’est-à-dire une collection de sommets reliés entre eux ; on emploie la commande readShapePoly pour les importer.
shape <- readShapePoly("data/lacs/ne_10m_lakes.shp")

Nous obtenons 1 353 lacs. L’objet shape@polygons[[3]] contient le (ou les) polygones décrivant le troisième lac. Le premier de ces polygones est décrit par :
plot(shape@polygons[[3]]@Polygons[[1]]@coords)

JPEG - 65.6 kio

On peut fermer ce polygone et le remplir en bleu :
plot(shape@polygons[[3]]@Polygons[[1]]@coords)
polygon(shape@polygons[[3]]@Polygons[[1]]@coords,col="light blue")

JPEG - 78.8 kio

C’est ce que l’on va faire, avec tous nos polygones de lacs.
plot(shape,col="blue",border="blue")

PNG - 25 kio

* * *

Le code complet de cet article est disponible sur le github de visionscarto. On verra notamment comment choisir une autre projection géographique que l’on souhaite, avec le package mapproj, pour obtenir une carte telle que celle-ci.

PNG - 54.1 kio