Consums en el municipio de Valencia

Consum
Valencia
Autor/a
Afiliación

Gerard Sanchis Beneyto

Universitat de València

Fecha de publicación

30 de marzo de 2025

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.

Este proyecto se va a centrar en los Supermecados Consum en la ciudad de Valencia. Vamos a ver los puntos geograficos, que se obtendran utilizando una query a la pagina web de OpenStreetMaps (OSM).

Uno de los principales de OSM es su caracter colaborativo, esto implica que haya una gran cantidad de datos, aunque por otra parte una de las desventajas es la falta de información en algunos datos y los datos que pueden estar repetidos.

Por eso en esta práctica pretendemos demostrar los errores que tendremos y tambien tecnicas para poder solucionarlos, y obtener puntos con mayor calidad.

Descripción

Primero descargamos las librerias que vamos a utilizar

Warning: package 'purrr' was built under R version 4.4.3
── 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.4     ✔ tidyr     1.3.1
✔ purrr     1.0.4     
── 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.12.2, GDAL 3.9.3, PROJ 9.4.1; sf_use_s2() is TRUE
Data (c) OpenStreetMap contributors, ODbL 1.0. https://www.openstreetmap.org/copyright
Warning: package 'dbscan' was built under R version 4.4.3

Adjuntando el paquete: 'dbscan'

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

    as.dendrogram

Una vez cargadas las librerias, vamos a definir el bounding box. En nuestro caso sera la ciudad de Valencia. Asi solo obtendremos la información de nuestro municipio.

# Municipio de Valencia con MapSpain
val <- mapSpain::esp_get_munic() %>% filter(LAU_CODE == "46250")

#Creamos el boundin box
bbox_val <- sf::st_bbox(val)

Ahora procedemos a cargar los datos de la pagina web de OSM usando el bounding box creado anteriormente.

# Supermercados Consum en Valencia
q <- bbox_val %>%
  osmdata::opq(timeout = 2000) %>%
  osmdata::add_osm_feature("name", "Consum") %>%
  osmdata::add_osm_feature("shop", "supermarket")

En nuestri caso hemos filtrado por tienda y dentro de tienda el nombre Consum.

El siguiente paso es obtener los datos en formato simple feature (sf). Existen muchos formatos, pero a nosotros nos interesa en formato sf.

# Formato sf

consum_sf <- osmdata::osmdata_sf(q)

Ahora aunque tenemos una lista, solo interesa los osm_points, que es donde se ecuentran las ubicaciones de los supermercados.

# Puntos OSM
consum_sf <- consum_sf$osm_points
class(consum_sf)
[1] "sf"         "data.frame"
dim(consum_sf)
[1] 200  48

Ahora representamos los datos con “leaflet” por lo que obtenemos el CRS.

# CRS
consum_sf <- st_transform(consum_sf,crs = st_crs(val))

# Representacion
consum_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'

Ahora vemos, como hay puntos que estan superpuestos, otros que cuenta cada puerta del supermecado como un supermercado distinto, y el mas claro que hay puntos representados que estan fuera del municipio de Valencia.

Tratamiento

Para corregir estos errores voy a proceder a usar este metodo, no tiene porque ser el mejor o el único, pero bajo mi criterio considero que es el adecuado. Para solucionar el problema de las puertas y los puntos superpuestos, utilizare DBSCAN. Es un algoritmo de agrupación basado en el ruido.

# Cordenadas de los puntos
cords <- sf::st_coordinates(consum_sf)

# DBSCAN
a <- dbscan(cords, eps = 0.003, minPts = 1)
consum_sf$cluster <- data.frame(a$cluster)

# Punto medio de cada cluster para agrupar los puntos
consum_sf1 <- consum_sf %>%
  group_by(cluster) %>%
  summarise(geometry = st_centroid(st_combine(geometry)))

# Grafico

ggplot() +
  geom_sf(data = val)+
  geom_sf(data = consum_sf1)+
  theme_void()+
  labs(title = "Consums al aplicar DBSCAN")

# Segundo grafico
consum_sf1 %>%
  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'

Ahora podemos apreciar como pasamos de tener 200 observaciones a tener solo 71. El siguiente paso es eliminar los Consums de fuera de Valencia, para ello utilizaremos “st_diference”. Obviamente a partir de ahora vamos a seguir con el nuevo data frame de 71 observaciones.

# Puntos fuera de Valencia

consums_fuera <- sf::st_difference(consum_sf1,val)
Warning: attribute variables are assumed to be spatially constant throughout
all geometries
dim(consums_fuera)
[1] 23  9

Por tanto, hay un total de 23 Consums fuera del municipio de Valencia, estos puntos no nos interesan, por lo que los vamos a eliminar.

consums_val <- sf::st_intersection(consum_sf1,val)
Warning: attribute variables are assumed to be spatially constant throughout
all geometries
dim(consums_val)
[1] 48  9

Vemos como hemos pasado de tener 200 observaciones, a finalmente solo tener 48 Consums en el municipio de Valencia.

Output

Una vez finalizado el tratamiento de los datos, procedo a mostrar esta figura donde se puede apreciar como se han corregido los errores. Primero muestro el grafico con leaflet, donde se observa bien la correción, y a posterior otro gráfico donde tambien se aprecia la corrección de errores.

# Gráfico 1 (leaflet)
consums_val %>%
  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'

Seguimos con el otro gráfico

# Grafico 2
ggplot()+
  geom_sf(data = val)+
  geom_sf(data = consums_val)+
  theme_void()+
  labs(title = "Consums en el municipio de Valencia")

Ahora tenemos un fichero de datos de los Consums en el municipio de Valencia libre de errores. Recordar que los datos han sido obtenidos de OpenStreetMap. Hemos aplicado DBSCAN y transformaciones del paquete “sf”.

sf::st_write(consums_val, "consums_valencia.gpkg")

El/los fichero(s) generados con este procedimiento/técnica/metodología se puede descargar de aquí.



Proyectos de Innovación Educativa Emergente PIEE-2737007 y PIEE-3325394