# Consolidación de geometrías administrativas
es <- ne_countries(country = "Spain", scale = "medium", returnclass = "sf") %>% st_union()
galicia <- esp_get_ccaa("Galicia") %>% st_union()
pontevedra_geo <- esp_get_prov("Pontevedra") %>% st_union()
# Obtención del contorno municipal de Vilagarcía
municipio_geo <- opq("Vilagarcía de Arousa, Spain") %>%
add_osm_feature(key = "admin_level", value = "8") %>%
osmdata_sf()
municipio_sf <- st_union(municipio_geo$osm_multipolygons)
# Normalización de sistemas de coordenadas (CRS) y filtrado
filtrar_puntos <- function(puntos, mascara) {
puntos <- st_transform(puntos, crs = st_crs(mascara))
puntos[st_intersects(puntos, mascara, sparse = FALSE), ]
}
# Aplicación del filtro a los niveles de estudio
osm_es_pescaderia_points <- filtrar_puntos(osm_es_pescaderia_points, es)
osm_es_hoteles_points <- filtrar_puntos(osm_es_hoteles_points, es)
osm_es_marinas_points <- filtrar_puntos(osm_es_marinas_points, es)
osm_galicia_pescaderia_points <- filtrar_puntos(osm_galicia_pescaderia_points, galicia)
osm_galicia_hoteles_points <- filtrar_puntos(osm_galicia_hoteles_points, galicia)
osm_galicia_marinas_points <- filtrar_puntos(osm_galicia_marinas_points, galicia)
osm_pontevedra_pescaderia_points <- filtrar_puntos(osm_pontevedra_pescaderia_points, pontevedra_geo)
osm_pontevedra_hoteles_points <- filtrar_puntos(osm_pontevedra_hoteles_points, pontevedra_geo)
osm_pontevedra_marinas_points <- filtrar_puntos(osm_pontevedra_marinas_points, pontevedra_geo)
osm_vilagarcia_pescaderia_points <- filtrar_puntos(osm_vilagarcia_pescaderia_points, municipio_sf)
osm_vilagarcia_hoteles_points <- filtrar_puntos(osm_vilagarcia_hoteles_points, municipio_sf)
osm_vilagarcia_marinas_points <- filtrar_puntos(osm_vilagarcia_marinas_points, municipio_sf)Datos sobre Galicia
Input
Se ha obtenido un conjunto de datos sobre los hoteles, pescaderías y marinas (puertos deportivos) para Galicia, la provincia de Pontevedra y el municipio de Vilagarcía de Arousa. La fuente de los datos es OpenStreetMap, accedidos desde la librería osmdata en R utilizando las claves tourism=hotel, shop=seafood y leisure=marina.
Enlace de la fuente: OpenStreetMap
Descripción
Al representar gráficamente los conjuntos de datos originales obtenidos directamente de la API de Overpass (OSM), se identificaron dos problemas críticos que afectaban la calidad del análisis:
Redundancia de Nodos: Muchos establecimientos estaban representados por múltiples puntos o nodos que definían su área, lo que inflaba artificialmente el conteo de establecimientos.
Dispersión Espacial: Existían registros que, debido al cuadro delimitador (bbox), se situaban ligeramente fuera de los límites oficiales de las zonas de estudio (Galicia, Pontevedra o Vilagarcía).
Tratamiento
Para resolver estos problemas, se aplicó el siguiente flujo:
1. Eliminación de puntos fuera del área seleccionada
Se obtuvo la geometría de cada territorio con las librerías rnaturalearth y mapSpain. Sin embargo, para el caso de Vilagarcía de Arousa se utilizó directamente osmdata para obtener una geometría precisa a nivel municipal.
Para obtener el contorno de cada lugar como conjunto, usamos la función st_union de la librería sf. Posteriormente, aseguramos que coincidan los sistemas de coordenadas (CRS) mediante st_transform. Finalmente, se filtraron los puntos dentro del territorio seleccionado utilizando st_intersects().
2. Reducción de redundancia (DBSCAN)
Se utilizó la librería dbscan para identificar agrupaciones espaciales en los datos.
Aplicación de DBSCAN: Se ejecutó el algoritmo con un radio de vecindad (
eps = 0.001) y un mínimo de un punto por clúster (minPts = 1), lo que permitió detectar agrupaciones densas de puntos que pertenecen a un mismo edificio o puerto.Extracción de puntos representativos: Una vez identificados los clústeres, se seleccionó un único punto representativo (centroide) por agrupación, reduciendo la redundancia y mejorando la precisión del análisis.
Automatización del proceso: Se diseñó una función para aplicar estos pasos a cada conjunto de datos, optimizando el flujo de trabajo.
#| label: procesamiento-dbscan
# Función para simplificar clústeres de puntos
simplificar_puntos <- function(sf_points) {
if (is.null(sf_points) || nrow(sf_points) == 0) return(sf_points)
coords <- st_coordinates(sf_points)
clustering <- dbscan(coords, eps = 0.001, minPts = 1)
sf_points$cluster <- clustering$cluster
sf_points %>%
group_by(cluster) %>%
summarise(geometry = st_centroid(st_combine(geometry)), .groups = "drop")
}
# Ejecución de la limpieza en cadena
list_df <- list(
osm_es_pescaderia_points, osm_es_hoteles_points, osm_es_marinas_points,
osm_galicia_pescaderia_points, osm_galicia_hoteles_points, osm_galicia_marinas_points,
osm_pontevedra_pescaderia_points, osm_pontevedra_hoteles_points, osm_pontevedra_marinas_points,
osm_vilagarcia_pescaderia_points, osm_vilagarcia_hoteles_points, osm_vilagarcia_marinas_points
)
resultados <- lapply(list_df, simplificar_puntos)
# Actualización de variables con datos limpios
osm_es_pescaderia_points <- resultados[[1]]
osm_es_hoteles_points <- resultados[[2]]
osm_es_marinas_points <- resultados[[3]]
osm_galicia_pescaderia_points <- resultados[[4]]
osm_galicia_hoteles_points <- resultados[[5]]
osm_galicia_marinas_points <- resultados[[6]]
osm_pontevedra_pescaderia_points <- resultados[[7]]
osm_pontevedra_hoteles_points <- resultados[[8]]
osm_pontevedra_marinas_points <- resultados[[9]]
osm_vilagarcia_pescaderia_points <- resultados[[10]]
osm_vilagarcia_hoteles_points <- resultados[[11]]
osm_vilagarcia_marinas_points <- resultados[[12]]Output
Se han obtenido archivos espaciales optimizados que eliminan la redundancia de nodos y aseguran la precisión geográfica dentro de los límites administrativos.
El fichero generado con este procedimiento se puede descargar de aquí.

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