171 lines
6.7 KiB
Markdown
171 lines
6.7 KiB
Markdown
|
+++
|
||
|
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()
|
||
|
```
|