+++ title = "Acceso a datos de OpenStreetMap con R" date = 2021-01-09T00:00:00+01:00 lastmod = 2021-01-14T01:41:34+01:00 draft = false subtitle = "Cómo acceder a datos de OpenStreetMap" math = true diagram = true publication_types = "" publication = "MPVD" featured = true projects = ["periodismodatos"] abstract_short = "Cómo acceder a datos de OpenStreetMap con R" authors = ["adolfo_anton"] abstract = "Cómo acceder a datos de OpenStreetMap con R" [image] caption = "[Orion aveugle cherchant le soleil](https://commons.wikimedia.org/wiki/File:Orion_aveugle_cherchant_le_soleil.jpg), Nicolas Poussin / Public domain" focal_point = "BottomLeft" placement = 3 preview_only = false +++ Cuando Christian Burkhart creó su mapa del callejero con R se fijó mucho en el trabajo de Dominique Royé con las librerías que trabajan con datos de OpenStreetMap como el de las [estaciones de servicio de Europa](https://dominicroye.github.io/en/2018/accessing-openstreetmap-data-with-r/). Para ello utilizó `POI` (_Point of Interest_, puntos de interés en la terminología de las representaciones espaciales de datos, puntos geográficos al fin y al cabo). Para obtener los datos se utiliza una pasarela de la API. ## Instalación de paquetes {#instalación-de-paquetes} Lo primer paso es instalar las librerías necesarias como las librerías `tidyverse`, que es una colección de distintas librerías entre las que se incluye `dplyr` para la manipulación de datos o `ggplot2` para la visualización; `sf` que es el nuevo estándar para trabajar con datos espaciales y es compatible con `ggplot` y `dplyr`. Finalmente `ggmap` nos ayuda a crear mapas. ```R if(!require("osmdata")) install.packages("osmdata") if(!require("tidyverse")) install.packages("tidyverse") if(!require("ggmap")) install.packages("ggmap") if(!require("sf")) install.packages("sf") ``` ## Se activan las librerías {#se-activan-las-librerías} Y se activan las librerías: ```R library(tidyverse) library(osmdata) library(sf) library(ggmap) ``` ## Hacer una consulta {#hacer-una-consulta} Antes de hacer una consulta hay que saber lo que se puede filtrar. Para ello se puede probar con la función `available_features()` que devuelve las características espaciales o `features` de OSM, algo común en el idioma de la representación espacial geográfica. Para no cargar mucho la consulta incluimos la función en la función `head()`: ```R head(available_features()) ``` Estas son las cinco primeras `features` que devueve la consulta. Se pueden ver las etiquetas de cualquiera de ellas a través de la función `available_tags()`: ```R head(available_tags("tourism")) ``` ## La primera consulta: dónde están las peluquerías en Murcia {#la-primera-consulta-dónde-están-las-peluquerías-en-murcia} Para construir una consulta se usa el operador `%>%` que ayuda a encadenar varias funciones sin asignar el resultado a un nuevo objeto. Su uso está muy extendido entre la colección de librerías de `tidyverse`. Este [tutorial de datacamp](https://www.datacamp.com/community/tutorials/pipe-r-tutorial) lo explica más. En la primera parte de la consulta tenemos que indicar el lugar para el que queremos extraer información. Eso se consigue con la función `getbb()` que crea unos límites para un lugar según un nombre dado. La función principal es `opq()` que crea la consulta final. Se filtra la información que se busca con la función `add_osm_feature()`. En esta primera consulta se buscan los cines de Madrid, con `amenity` como `feature` y `cinema` como `tag`. Se pueden obtener los resultados espaciales en varios formatos. la función `osmdata_*()` envía la consulta al servidor y según si el sufijo es `sf`, `sp` o `xml` devuelve una característica simple (de `single feature`), espacial (de `spatial`) o en formato `XML`. ```R consulta <- getbb("Murcia Spain") %>% opq() %>% add_osm_feature("shop", "hairdresser") str(consulta) ``` ```R pelus <- osmdata_sf(consulta) pelus ``` El resultado es una lista de diferentes objetos espaciales. En nuestro caso solo nos interesan los puntos `osm_points`. ## Visualizar {#visualizar} Lo bueno de los objetos `sf` es que para ggplot ya existe una función geométrica llamada `geom_sf()`. De fondo se puede añadir un mapa con la librería `ggmap` y la función `get_map()` que descarga un mapa para un lugar dado. También podría ser una dirección, latitud/longitud o `bounding box`. El argumento del tipo de mapa permite indicar el estilo o tipo de mapa. Más información sobre esto se puede encontrar en la ayuda `?get_map` Cuando se hace un gráfico con `ggplot` se suele empezar con la función `ggplot()`. En este caso se empieza con `ggmap()` que incluye el objeto con el mapa de fondo. Entonces se añaden los puntos de las peluquerías de Murcia con `geom_sf()`. Es importante indicar con el argumento `inherit.aes = FALSE` que use los `aesthetic mappings` del objeto espacial `osm_points`. Además, se cambia el color, relleno, transparencia tipo y tamaño de los círculos. ```R murcia_se_peina <- get_map(c(left = -1.18, bottom = 37.91, right = -1.05, top = 38.04), maptype = "watercolor") ggmap(murcia_se_peina) + geom_sf(data = pelus$osm_points, inherit.aes = FALSE, colour = "#238443", fill = "#004529", alpha = .5, size = 4, shape = 21) + labs(x = "", y = "") ``` ## Dónde hay una zapatería {#dónde-hay-una-zapatería} ```R q_murcia_shoes <- getbb("Murcia Spain") %>% opq() %>% add_osm_feature("shop", "shoes") str(q_murcia_shoes) ``` ```R murcia_shoes <- osmdata_sf(q_murcia_shoes) murcia_shoes ``` ```R murcia_shoes <- get_map(getbb("Murcia Spain"), maptype = "watercolor", source = "stamen") ggmap(murcia_shoes) + geom_sf(data = q_murcia_shoes$osm_points, inherit.aes = FALSE, colour = "#238443", fill = "#004529", alpha = .5, size = 4, shape = 21) + labs(x = "", y = "") ``` ## Mercadona {#mercadona} En vez de obtener un `bounding box` con la función `getbb()` se puede crear sabiendo los puntos oeste, sur, este y norte. En la consulta hay dos características: el nombre y la tienda para filtrar supermercados de esta marca en particular. Según el area o volumen de la consulta se puede alargar el tiempo de espera. Por defecto el límite se establece en 25 segundos antes del `timeout`. Lo que nos interesa son los puntos donde hay supermercados por lo que se usa la geometría a través de `geom_sf()`. La función `theme_void()` borra todo menos los puntos. Se crean los límites: ```R m <- c(-10, 30, 5, 46) ``` Se hace la consulta: ```R q <- m %>% opq (timeout = 25*100) %>% add_osm_feature("name", "Mercadona") %>% add_osm_feature("shop", "supermarket") mercadona <- osmdata_sf(q) mercadona ``` Y el mapa final: ```R ggplot(mercadona$osm_points)+ geom_sf(colour = "#08519c", fill = "#08306b", alpha = 5, size = 1, shape = 21) + theme_void() ```