Estaciones de Policía en Valencia

VALENCIA
GPKG
POLICIA
Autor/a
Afiliación

Gemma Alpuente

Universitat de València

Fecha de publicación

10 de mayo de 2024

Input

OpenStreetMaps (OSM) es un proyecto colaborativo que busca crear un mapa del mundo de código abierto y gratuito. Los datos en OpenStreetMaps son creados y mantenidos por una comunidad global de mapeadores voluntarios, quienes contribuyen con información geoespacial detallada, como carreteras, edificios, lugares de interés y más. Estos datos pueden ser utilizados por cualquier persona para diversos propósitos, desde la navegación hasta el análisis geoespacial, y se distribuyen bajo una licencia abierta que permite su uso y redistribución libremente.

Esta ficha se centra en las Estaciones de Policía en el municipio de Valencia, como puntos geográficos a estudiar. Aunque podemos obtener los datos de la página web de OpenStreetMaps, nosotros utilizaremos una query para importarlos y poder trabajar con ellos.

A priori la herramienta de OSM parece ventajosa dada su amplia cobertura y actualización continua, con gran flexibilidad y detalles. Sin embargo, su carácter colaborativo y abierto también implica una calidad variable en los datos, falta de estandarización o desigualdades, entre otros errores.

Con esta práctica pretendemos demostrar cómo a partir de datos geográficos importados de OpenStreetMaps es muy probable encontrar errores, además de mostrar técnicas que puedan ayudarnos a solucionar este problema y así obtener finalmente datos de mayor valor o calidad.

Descripción

Cargamos las librerías necesarias:

── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
Linking to GEOS 3.11.2, GDAL 3.8.2, PROJ 9.3.1; sf_use_s2() is TRUE
Data (c) OpenStreetMap contributors, ODbL 1.0. https://www.openstreetmap.org/copyright

Attaching package: 'dbscan'

The following object is masked from 'package:stats':

    as.dendrogram

Antes de construir la consulta o query con la que importaremos la base de datos, es necesario definir el lugar (bounding box) de donde queremos extraer la información. En este caso, es el municipio de Valencia.

# Extraemos el municipio con el paquete 'mapSpain'
val_mun <- mapSpain::esp_get_munic() %>% filter(LAU_CODE == "46250") 

# Transformamos a bounding box
bbox_val_mun <- sf::st_bbox(val_mun) 

Ahora sí, pasamos a construir la consulta con la que obtendremos nuestra base de datos.

# Estaciones de Policía en Valencia
q <- bbox_val_mun %>%
  osmdata::opq(timeout = 1000) %>% 
  osmdata::add_osm_feature(key = "amenity", value = "police")

Los datos espaciales resultantes de la consulta pueden obtenerse en distintos formatos: simple feature, en formato espacial (spatial) o en XML. A nosotros nos interesará tenerlos en simple feature (sf).

# Obtenemos los datos en formato sf
estaciones_policia_sf <- osmdata::osmdata_sf(q) 

Vemos que el resultado es una lista de diferentes objetos espaciales. En nuestro caso, solamente nos fijaremos en los ‘osm_points’, que corresponden con las ubicaciones de las estaciones de policía.

# Extraemos los puntos 
estaciones_policia_sf <- estaciones_policia_sf$osm_points 

# Características de los datos 
class(estaciones_policia_sf) # Objeto sf 
[1] "sf"         "data.frame"
dim(estaciones_policia_sf) # 479 observaciones y 23 variables
[1] 479  23

Para poder representar los datos extraídos con ‘leaflet’, necesitaremos cambiar el CRS previamente:

# Cambiamos el CRS
estaciones_policia_sf  <- st_transform(estaciones_policia_sf,crs = st_crs(val_mun))

# Representación de los datos 
estaciones_policia_sf %>%
  leaflet::leaflet() %>%
  leaflet::addTiles() %>%
  leaflet::addCircles()
Warning: sf layer has inconsistent datum (+proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs).
Need '+proj=longlat +datum=WGS84'

Al representar los datos podemos detectar claramente un par de problemas. En primer lugar, que muchos de los puntos representados aparecen superpuestos en el gráfico, lo que es indicador de que algunas localizaciones están repetidas en la base de datos. Y en segundo lugar, que muchos de los puntos representados se encuentran fuera del municipio de Valencia.

Tratamiento

La primera de las problemáticas, la solucionaremos con DBSCAN, un algoritmo de agrupamiento espacial basado en la densidad de aplicaciones con ruido.

# Obtenemos las coordenadas de los puntos
coords <- sf::st_coordinates(estaciones_policia_sf) 

# Aplicación del Método DBSCAN
res <- dbscan(coords, eps = 0.001, minPts = 1)
estaciones_policia_sf$cluster <- data.frame(res$cluster)

# Cálculo del punto medio de cada clúster
estaciones_policia_sf2 <- estaciones_policia_sf %>%
  group_by(cluster) %>%
  summarise(geometry = st_centroid(st_combine(geometry)))

# Representación
ggplot() +
  geom_sf(data = val_mun) +
  geom_sf(data = estaciones_policia_sf2) +
  theme_void() +
  labs(title = "Estaciones de Policía en Valencia (tras DBSCAN)")

# Representación con leaflet
estaciones_policia_sf2 %>%
  leaflet::leaflet() %>%
  leaflet::addTiles() %>%
  leaflet::addCircles()
Warning: sf layer has inconsistent datum (+proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs).
Need '+proj=longlat +datum=WGS84'

Pasamos de tener 459 observaciones en la base de datos inicial, a solamente 55. Era importantísimo corregir estas duplicaciones.

Ahora, pasamos a solucionar el segundo de los problemas. Con la función “st_difference” del paquete “sf”, obtendremos los puntos fuera del municipio de Valencia. Fijémonos en que utilizamos los datos tras la clusterización, para así seguir trabajando sin las duplicaciones. Son 27 observaciones en total las que se encuentran fuera del municipio de Valencia y aparecen en nuestra base de datos.

# Detección de los Outliers
estaciones_out <- sf::st_difference(estaciones_policia_sf2,val_mun)
Warning: attribute variables are assumed to be spatially constant throughout
all geometries
dim(estaciones_out)
[1] 27  9

Como estas observaciones no nos interesan, las eliminaremos y nos quedaremos solamente con las observaciones resultado de “st_intersection”. Son 28 estaciones las que realmente pertenecen a Valencia.

# Estaciones de Policía dentro del municipio de Valencia
estaciones_in <- sf::st_intersection(estaciones_policia_sf2,val_mun)
Warning: attribute variables are assumed to be spatially constant throughout
all geometries
dim(estaciones_in)
[1] 28  9

Output

Con la siguiente figura comprobamos que han sido corregidos todos los errores:

spain <- mapSpain::esp_get_munic()
spain <- sf::st_transform(spain, crs=4326)
limites_val <- sf::st_buffer(val_mun, 15000) %>% sf::st_bbox()

ggplot() +
  geom_sf(data = spain, fill="#CEC1AD") +
  geom_sf(data = val_mun, fill="white") +
  geom_sf(data = estaciones_in, size=1) +
  coord_sf(xlim = c(limites_val["xmin"], limites_val["xmax"]), 
           ylim = c(limites_val["ymin"], limites_val["ymax"])) +
  theme_minimal() +
  theme(axis.title = element_blank(),
        panel.background = element_rect(fill="lightblue"))

Tras darnos cuenta que los datos extraídos de OpenStreetMaps contenían observaciones duplicadas y algunas fuera de la zona deseada; con la ayuda del algoritmo DBSCAN, que clusteriza los datos, y funciones del paquete “sf”, hemos conseguido tener una base de datos libre de estos errores y que contiene las Estaciones de Policía en el municipio de Valencia.

sf::st_write(estaciones_in, "estaciones_policia_valencia.gpkg")

El fichero generado con el procedimiento descrito anteriormente se puede descargar, en formato GeoPackage (gpkg), de aquí.



Proyecto de Innovación Educativa Emergente (PIEE-2737007)