Réaliser une carte avec R (7)

Suite aux parties 1, 2, 3, 4, 5, et 6, nous allons à présent voir quelques réglages et décorations pour finaliser nos cartes.

Vous pouvez télécharger le code source complet du notebook R de ce tutoriel ici et le fichier contenant uniquement le code R ici.

Empêcher l’expansion des limites

Si l’on trace une carte de Kyūshū, ici avec le thème theme_classic() pour conserver les axes, on s’aperçoit que ggplot2 étend les limites de la carte au-delà des limites spécifiées avec xlim et ylim. Dans l’exemple ci-dessous, on s’attendrait à ce que la carte s’arrête sur l’axe vertical à 34° et 31°, or ce n’est pas le cas.

require(rgdal)
require(ggplot2)
require(ggthemes)
jpn0 <- readOGR(dsn = path.expand("~/repos/cartes/jpn/adm/jpn"), layer = "JPN_adm0")
## OGR data source with driver: ESRI Shapefile 
## Source: "/home/thomas/repos/cartes/jpn/adm/jpn", layer: "JPN_adm0"
## with 1 features
## It has 24 fields
jpn0F <- fortify(jpn0)
xlims <- c(128.5,132.25)
ylims <- c(31,34)
kyushu <- ggplot(data = jpn0F) +
  geom_polygon(aes(x = long, y = lat, group = group), fill = "grey", color = "black", size = .25) +
  coord_fixed(xlim = xlims, ylim = ylims) +
  theme_classic()
kyushu

Pour empêcher cette extension et forcer la carte à respecter précisément les limites indiquées il faut rajouter deux commandes:

kyushu <- kyushu +
  scale_x_continuous(expand = c(0,0)) +
  scale_y_continuous(expand = c(0,0))
kyushu

Les cartes sauvegardées avec ggsave() ont en général une bande blanche inutile en hauteur ou en largeur car ggsave() n’adapte pas les dimensions au rapport hauteur:largeur de la carte. Il suffit d’utiliser la fonction plot_crop() du module knitr sur le fichier sauvegardé pour découper automatiquement l’image en supprimant les blancs inutiles.

require(knitr)
ggsave("kyushu.pdf", kyushu)
plot_crop("kyushu.pdf")
## [1] "'kyushu.pdf'"

Insertion d’un carton

Il est utile pour les cartes zoomant sur une petite région de rajouter dans un coin un carton indiquant la localisation de la région étudiée à l’intérieur d’une plus grande zone. Commençons donc par préparer une carte de Kyūshū avec assez d’espace pour accueillir un carton dans le coin en bas à gauche. Rajoutons également un cadre autour de toute la carte.

xlims <- c(127.5,132.25)
ylims <- c(30.5,34)
kyushu <- ggplot(data = jpn0F) +
  geom_polygon(aes(x = long, y = lat, group = group), fill = "grey", color = "black", size = .25) +
  coord_fixed(xlim = xlims, ylim = ylims) +
  theme_classic() +
  theme(panel.border = element_rect(fill = NA, colour = 'black', size=0.5)) +
  scale_x_continuous(expand = c(0,0)) +
  scale_y_continuous(expand = c(0,0))
kyushu

Préparons ensuite une carte de l’Asie avec un cadre autour.

require(mapdata)
asia <- ggplot() +
  borders("worldHires", fill = "grey", colour = "black", xlim = c(110,150), ylim = c(20,50), size = .25) +
  coord_fixed(xlim = c(110,150), ylim = c(20,50)) +
  theme_map() +
  theme(panel.border = element_rect(fill = NA, colour = 'black', size=0.5), panel.background = element_rect(fill = 'white', colour = NA)) +
  scale_x_continuous(expand = c(0,0)) +
  scale_y_continuous(expand = c(0,0))
asia

Indiquons sur cette carte la localisation et l’étendue de notre carte de Kyūshū.

require(raster)
kyushuExt <- as(extent(xlims,ylims), "SpatialPolygons")
kyuAsia <- asia + geom_polygon(data = kyushuExt, aes(x = long, y = lat), fill = NA, color = "black", size = .75)
kyuAsia

Insérons maintenant notre carte de l’Asie comme carton dans la carte de Kyūshū. Il est nécessaire de charger les modules ggmap et grid et d’utiliser la fonction ggplotGrob() à l’intérieur de insert(). Les options xmin, xmax, ymin et ymax règlent la taille et la position du carton, et il faut malheureusement les règler à la main et à tâtons pour obtenir le résultat voulu.

require(ggmap)
require(grid)
kyushuAsia <- kyushu +  inset(ggplotGrob(kyuAsia), xmin = min(xlims), xmax = 129.5, ymin = min(ylims), ymax = 32)
kyushuAsia

Ajoutons l’indication du Nord et une échelle avec le module ggsn.

require(ggsn)
kyushuAsia + 
  north(data = fortify(kyushuExt), symbol = 3, location = "topleft", scale = .08) + 
  scalebar(data = fortify(kyushuExt), dist = 40, dd2km = TRUE, model = 'WGS84', st.size = 3, st.dist = .035, location = "bottomright", st.bottom = FALSE, anchor = c(x = 132.05, y = 30.6))

Déplacer des polygones

On peut vouloir déplacer des polygones sur une carte. Pour la France, on peut vouloir afficher les DOM-TOM et la métropole sur une même carte, et pour le Japon on peut vouloir afficher Okinawa ailleurs qu’à sa position réelle afin d’éviter d’allonger inutilement la carte verticalement.

On pourrait utiliser la technique vue ci-dessus pour les cartons, mais puisqu’il s’agit en fait de cartes indépendantes superposées, on perd alors la possibilité d’appliquer une même visualisation à tous les polygones en une seule fois. Il peut donc être préférable dans certains cas de tout simplement déplacer certains polygones en modifiant directement leurs coordonnées.

Pour réaliser une carte du Japon où les îles du département d’Okinawa sont affichées non pas à leurs coordonnées mais en haut à gauche, commençons par faire deux sous-ensembles de polygones: 1. ceux n’appartenant pas à Okinawa; 2. ceux appartenant à Okinawa. Pour ces derniers, nous excluons certaines iles trop isolées et trop petites pour qu’il y ait un intérêt à les afficher.

jpn2 <- readOGR(dsn = path.expand("~/repos/cartes/jpn/adm/jpn"), layer = "JPN_adm2")
## OGR data source with driver: ESRI Shapefile 
## Source: "/home/thomas/repos/cartes/jpn/adm/jpn", layer: "JPN_adm2"
## with 1811 features
## It has 11 fields
hondo <- subset(jpn2, NAME_1 != "Okinawa")
oki <- subset(jpn2, NAME_1 == "Okinawa" & !(NAME_2 %in% c("Minami Daito","Unknown5","Unknown8")))

Ensuite, nous modifions avec une boucle les polygones d’Okinawa en augmentant leur longitude et latitude.

for(i in 1:length(oki@polygons)) {
  for(j in 1:length(oki@polygons[[i]]@Polygons)) {
    oki@polygons[[i]]@Polygons[[j]]@coords[,1] <- oki@polygons[[i]]@Polygons[[j]]@coords[,1] + 6
    oki@polygons[[i]]@Polygons[[j]]@coords[,2] <- oki@polygons[[i]]@Polygons[[j]]@coords[,2] + 17.5
  }
}

On peut alors recombiner tous nos polygones avec la fonction rbind() et afficher notre carte.

jpn <- rbind(hondo, oki)
jpnF <- fortify(jpn)
jpMap <- ggplot() +
  geom_polygon(data = jpnF, aes(x = long, y = lat, group = group), fill = "grey") +
  coord_fixed(xlim = c(min(jpnF$long), 146), ylim = c(27,max(jpnF$lat))) +
  scale_x_continuous(expand = c(0,0)) +
  scale_y_continuous(expand = c(0,0)) +
  theme_classic() +
  theme(panel.border = element_rect(fill = NA, colour = 'black', size=0.5))
jpMap

On peut également rajouter une ligne de démarcation.

border <- data.frame(
  long <- c(129, 131, 136, 136),
  lat <- c( 40.5, 40.5, 44, 45)
)
jpMap + 
  geom_path(data = border, aes(x = long, y = lat), color = "black", size = 0.5)

À suivre…

Ce billet peut être cité de la façon suivante: Thomas Pellard, « Réaliser une carte avec R (7) », Cipanglossia, 2 juillet 2017, http://cipanglo.hypotheses.org/512.

Laisser un commentaire

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