Streetmaps

Cómo hacer bonitos callejeros

Resumen

Cómo hacer bonitos callejeros con R y ggplot2

Publicación
MPVD

El título original es mucho más feo ya que incluye al final “y PowerPoint”: “Create a streetmap of your favorite city with ggplot2 and powerpoint”. En este caso vamos a intentar no usar esa herramienta por no ser software libre.

El propósito del autor era crear mapas/callejeros como el de este cartel:

Para este tutorial se utilizan dos paquetes de R: osmdata y ggplot2. Con osmdata se extraen las calles de OpenStreetMap, una base de datos libre con licencia abierta. Ni siquiera requiere de una clave para trabajar con su API. Para crear las visualizaciones y trabajar con los datos se utiliza tidyverse.

El autor no había trabajado mucho con ggplot2 y se inspiró especialmente en Dominic Royé y su detallado trabajo de datos OpenStreetMap con R.

Se puede empezar por la ciudad en la que estás, en la que vives, en la que naciste o una que te gusta. En su caso empezó por Freiburg, en el sur de Alemania. Para elegir la ciudad tan solo hay que ajustar la longitud y latitud de los puntos de inicio.

Lo primero es instalar las librerías necesarias, tidyverse y osmdata:

library(tidyverse)
library(osmdata)

Antes de trabajar con R hay que entender cómo almacena OpenStreetMap los datos de las calles. OpenStreetMap describe las cosas físicas como “características” o “rasgos”, del inglés “features”. Estas características se almacenan como pares de clave-valor. Por ejemplo hay highways que son vías principales que pueden conectar tanto la ciudad en sí como la ciudad con otras.

Para obtener todas las etiquetas de una característica espacial vía osmdata introducimos la siguiente función:

available_tags("highway")

De la misma manera, se pueden obtener todas las características con la función available_features():

available_features()

Para obtener las coordenadas de la ciudad que elijamos se puede usar la función getbb(). Por ejemplo, con Murcia:

getbb("Murcia Spain")

Esto nos da las coordenadas de la ciudad. el valor de la x da la longitud mientras que la y da la altitud.

Ahora queremos exportar las carreteras del sistema de coordenadas. Para ello primero pasamos la salida de la función getbb a la función opq.

A continuación pasamos esta salida a la función add_osm_feature. La función tiene dos argumentos. Con la clave especificamos la clave de la característica; con el valor especificamos la etiqueta de la característica.

En este caso primero extraemos las principales calles de la ciudad y las pasamos a la función osmdata_sf para insertarlo luego en ggplot2.

streets <- getbb("Murcia Spain")%>%
  opq()%>%
  add_osm_feature(key = "highway",
		  value = c("motorway", "primary",
			    "secondary", "tertiary")) %>%
  osmdata_sf()
streets

Los datos los hemos almacenado en la variable streets. Este objeto tiene diferentes objetos hijxs. osm_lines son especialmente interesantes para el mapa las líneas de osm_lines mientras que los puntos hablan de lugares.

Ahora obtenemos también las calles más pequeñas y el río de Murcia, el Segura, de la misma base de datos:

small_streets <- getbb("Murcia Spain")%>%
  opq()%>%
  add_osm_feature(key = "highway",
		  value = c("residential", "living_street",
			    "unclassified",
			    "service", "footway")) %>%
  osmdata_sf()

river <- getbb("Murcia Spain")%>%
  opq()%>%
  add_osm_feature(key = "waterway", value = "river") %>%
  osmdata_sf()

Y creamos nuestro primer mapa:

ggplot() +
  geom_sf(data = streets$osm_lines,
	  inherit.aes = FALSE,
	  color = "black",
	  size = .4,
	  alpha = .8) +
  coord_sf(xlim = c(-1.38, -0.85),
	   ylim = c(37.71, 38.11),
	   expand = FALSE)

Primero se añade la geometría geom_sf a la función ggplot. Para los datos añadimos las calles almacenadas en la variable streets$osm_lines. Se puede determinar la anchura de las calles con size. Para que las calles no estén completamente negras se ha creado una pequeña transparencia con el nivel alpha.

Con la función coord_sf se puede determinar el eje de las X y de las Y exactamente. Es mejor jugar con los valores hasta que has definido los límites.

Con expand = FALSE nos aseguramos de que se muestren las coordenadas correctamente.

Ahora se añaden calles pequeñas y ríos:

ggplot() +
  geom_sf(data = streets$osm_lines,
	  inherit.aes = FALSE,
	  color = "black",
	  size = .4,
	  alpha = .8) +
  geom_sf(data = small_streets$osm_lines,
	  inherit.aes = FALSE,
	  color = "black",
	  size = .4,
	  alpha = .6) +
  geom_sf(data = river$osm_lines,
	  inherit.aes = FALSE,
	  color = "black",
	  size = .2,
	  alpha = .5) +
  coord_sf(xlim = c(-1.38, -0.85),
	   ylim = c(37.71, 38.11),
	   expand = FALSE)

En vez de negro se pueden resaltar las calles en color:

ggplot() +
  geom_sf(data = streets$osm_lines,
	  inherit.aes = FALSE,
	  color = "steelblue",
	  size = .4,
	  alpha = .8) +
  geom_sf(data = small_streets$osm_lines,
	  inherit.aes = FALSE,
	  color = "black",
	  size = .4,
	  alpha = .6) +
  geom_sf(data = river$osm_lines,
	  inherit.aes = FALSE,
	  color = "black",
	  size = .2,
	  alpha = .5) +
  coord_sf(xlim = c(-1.38, -0.85),
	   ylim = c(37.71, 38.11),
	   expand = FALSE)

There’s one more thing that’s disturbing, though. The x- and y-axis. To remove them we can add the function theme_void():

ggplot() + geom_sf(data = streets$osm_lines, inherit.aes = FALSE, color = “steelblue”, size = .4, alpha = .8) + geom_sf(data = small_streets$osm_lines, inherit.aes = FALSE, color = “black”, size = .4, alpha = .6) + geom_sf(data = river$osm_lines, inherit.aes = FALSE, color = “black”, size = .2, alpha = .5) + coord_sf(xlim = c(7.77, 7.92), ylim = c(47.94, 48.06), expand = FALSE) + theme_void() Next, we can adjust the colors of the visualization. I want to create not only a white streetmap, but also one with a dark background:

ggplot() + geom_sf(data = streets$osm_lines, inherit.aes = FALSE, color = “#7fc0ff”, size = .4, alpha = .8) + geom_sf(data = small_streets$osm_lines, inherit.aes = FALSE, color = “#ffbe7f”, size = .2, alpha = .6) + geom_sf(data = river$osm_lines, inherit.aes = FALSE, color = “#ffbe7f”, size = .2, alpha = .5) + coord_sf(xlim = c(7.77, 7.92), ylim = c(47.94, 48.06), expand = FALSE) + theme_void() + theme( plot.background = element_rect(fill = “#282828”) ) Now that we’ve created both visualizations, we can make a poster out of it. To do so I first exported the visualizations as a png file. Make sure that you execute the function right after you have created your streetmap.

ggsave(“map.png”, width = 6, height = 6) Next, I created a Powerpoint file and resized it. Then I imported the png file and enlarged it. You might also need to crop the png first. As text I used the font Lato. I recommend that you search the internet for photos of streetmaps and use these examples as a guide. There are already countless beautiful designs that you can recreate relatively easily in Powerpoint.

The examples from this tutorial can be found here. Feel free to share your own streetmaps on Twitter, I’m curious what you create.

Adolfo Antón Bravo
Adolfo Antón Bravo
periodismo como código

Algunos de mis intereses son la Web Semántica, el Periodismo, la Visualización y la Ciencia de Datos.