Mejora del dataset de aparcamientos de València con información de barrios
datos_espaciales
OSM
Valencia
Autor/a
Afiliación
Pablo Senabre Catalá
Universitat de Valencia
Fecha de publicación
1 de abril de 2025
Input
El estacionamiento es un elemento clave en la planificación urbana, ya que incide directamente en la movilidad y en la calidad de vida de los ciudadanos. En esta práctica, nos centramos en analizar los aparcamientos del municipio de València, con el objetivo de estudiar su distribución a lo largo de los distintos barrios y de comprender mejor cómo se integran en el tejido urbano.
Para obtener los datos, hemos utilizado OpenStreetMap (OSM), una fuente de información geográfica abierta, gratuita y continuamente actualizada por la comunidad. La extracción se ha realizado mediante una consulta en RStudio que recoge todos los elementos con la etiqueta amenity=parking dentro del área de València. El conjunto resultante incluye, entre otros, los siguientes campos:
osm_id: Identificador único de cada aparcamiento en OSM.
name: Nombre del aparcamiento (si se ha registrado).
geometry: Ubicación geográfica de cada aparcamiento.
Es importante destacar que la etiqueta amenity=parking abarca una amplia variedad de instalaciones, lo que incluye:
Aparcamientos a nivel de superficie: Zonas abiertas o áreas en la vía pública destinadas al estacionamiento.
Garajes o estacionamientos de varios pisos (multi-storey): Estructuras destinadas a estacionar vehículos en múltiples niveles.
Estacionamientos subterráneos (underground): Instalaciones ubicadas por debajo del nivel del suelo.
De esta forma, se incluyen todos los tipos de aparcamientos registrados en OSM, permitiendo así un análisis global de la infraestructura de estacionamiento en la ciudad.
Sin embargo, los datos originales de OSM no indican a qué barrio pertenece cada aparcamiento. Para enriquecer el dataset, se ha incorporado un segundo conjunto de datos que contiene los límites oficiales de los barrios de València, obtenido desde el portal de datos abiertos del Ayuntamiento o de la Generalitat Valenciana. Esta integración posibilita asignar a cada aparcamiento su correspondiente barrio, lo que facilita un análisis espacial más detallado y útil para la toma de decisiones urbanísticas.
Descripción
A continuación, se detallan los pasos seguidos para obtener y preparar los datos de aparcamientos en València, combinando información de OSM con los límites oficiales de los barrios:
── 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
Definimos el área geográfica de interés, utilizando la función getbb para obtener el bounding box de València, y realizamos la consulta a OSM para extraer los aparcamientos (elementos etiquetados como amenity=parking):
# Definición del bounding box y consulta a OSMvalencia_bb<-getbb("Valencia, Spain")query_parking<-opq(bbox =valencia_bb)%>%add_osm_feature(key ="amenity", value ="parking")osm_parking<-osmdata_sf(query_parking)# Extraemos aparcamientos como puntos y polígonosparking_points<-osm_parking$osm_points%>%select(any_of(c("osm_id", "name", "geometry")))parking_polygons<-osm_parking$osm_polygons%>%select(any_of(c("osm_id", "name", "geometry")))
Para delimitar el área de estudio, obtenemos el límite administrativo de València desde OSM, filtrando por boundary=administrative, admin_level=8 y name=València.
# Límite administrativo de Valènciavalencia_admin<-opq(bbox =getbb("Valencia, Spain"))%>%add_osm_feature(key ="boundary", value ="administrative")%>%add_osm_feature(key ="admin_level", value ="8")%>%add_osm_feature(key ="name", value ="València")%>%osmdata_sf()if(!is.null(valencia_admin$osm_multipolygons)&&nrow(valencia_admin$osm_multipolygons)>0){valencia_boundary<-valencia_admin$osm_multipolygons}elseif(!is.null(valencia_admin$osm_polygons)&&nrow(valencia_admin$osm_polygons)>0){valencia_boundary<-valencia_admin$osm_polygons}else{stop("No se encontró el límite administrativo de València.")}
Realizamos una intersección espacial para conservar solo aquellos aparcamientos que se encuentran dentro del límite administrativo y combinamos ambos conjuntos (puntos y polígonos):
# Filtrar aparcamientos dentro del límite de Valènciaparking_points_valencia<-st_intersection(parking_points, valencia_boundary)
Warning: attribute variables are assumed to be spatially constant throughout
all geometries
Warning: attribute variables are assumed to be spatially constant throughout
all geometries
# Combinar y eliminar duplicadosall_parkings<-rbind(parking_points_valencia, parking_polygons_valencia)%>%distinct(osm_id, .keep_all =TRUE)
Antes de incorporar la información de los barrios, es interesante visualizar la distribución de los aparcamientos tal como se obtendrían de OSM:
# Definir la extensión geográfica de Valenciavalencia_bb<-getbb("Valencia, Spain")# Consulta OSM para obtener aparcamientos (amenity=parking)query_parkings<-opq(bbox =valencia_bb)%>%add_osm_feature(key ="amenity", value ="parking")# Extraer los datos en formato sf (se extraen solo los puntos)osm_parkings<-osmdata_sf(query_parkings)parkings_points<-osm_parkings$osm_points# Visualizar los aparcamientos en un mapa interactivoleaflet(parkings_points)%>%addProviderTiles("CartoDB.Positron")%>%addCircleMarkers( radius =4, color ="blue", popup =~paste("OSM ID:", osm_id))%>%setView(lng =-0.3763, lat =39.4699, zoom =12)
Tratamiento
Posteriormente, cargamos el dataset de barrios (en formato GeoJSON o Shapefile) descargado de la fuente pública y aseguramos que ambos datasets tengan el mismo sistema de coordenadas (CRS):
# Cargar el dataset de barriosbarrios<-st_read("data/000136/districtes-distritos.geojson", quiet =TRUE)# Asegurar el mismo CRSall_parkings<-st_transform(all_parkings, st_crs(barrios))
Realizamos la unión espacial para asignar a cada aparcamiento el barrio correspondiente:
# Unión espacial: asignar barrio a cada parkingparkings_with_barrios<-st_join(all_parkings, barrios["nombre"])parkings_barrios<-parkings_with_barrios%>%filter(!is.na(nombre))
A continuación, se cuenta el número de aparcamientos por barrio y se unen estos datos al dataset de barrios para la construcción del mapa coroplético:
# Contar aparcamientos por barrioparking_counts<-parkings_barrios%>%st_set_geometry(NULL)%>%group_by(nombre)%>%summarize(n_parkings =n())# Unir la cuenta al dataset de barriosbarrios_parking<-left_join(barrios, parking_counts, by ="nombre")# Agrupar los barrios con aparcamientos para el coropléticobarrios_union<-barrios_parking%>%filter(!is.na(n_parkings))%>%group_by(nombre)%>%summarise(geometry =st_union(geometry), n_parkings =first(n_parkings))
Además, se crea una paleta “YlOrRd” para el coroplético y se convierten las geometrías de los aparcamientos a puntos (centroides) para la capa de marcadores:
# Paleta "YlOrRd" para el choropleticopal<-colorNumeric(palette ="YlOrRd", domain =barrios_union$n_parkings, na.color ="transparent")# Convertir a puntos (centroides) para la capa de marcadoresparkings_barrios_points<-st_centroid(parkings_barrios)
Warning: st_centroid assumes attributes are constant over geometries
También se genera un gráfico de barras con ggplot2 para visualizar la distribución de aparcamientos por barrio:
# Gráfico de barrasplot_parking<-parking_counts%>%ggplot(aes(x =reorder(nombre, -n_parkings), y =n_parkings, fill =n_parkings))+geom_bar(stat ="identity")+coord_flip()+labs(title ="Número de Aparcamientos por Barrio", x ="Barrio", y ="Número de Parkings")+scale_fill_gradient(low ="yellow", high ="red")+theme_minimal()
Output
El resultado final es un conjunto de datos enriquecido y visualizaciones interactivas que permiten analizar la distribución de los aparcamientos en València por barrio. Se obtienen las siguientes mejoras:
Mapa coroplético: Los barrios se colorean con la paleta “YlOrRd” según el número de aparcamientos.
Resaltado y etiquetas: Al pasar el ratón sobre un barrio, se resalta su contorno y aparece el nombre.
Marcadores con clúster: Los aparcamientos se muestran como marcadores agrupados (convertidos a centroides) con popups enriquecidos.
Herramientas interactivas: Se incluyen un buscador por nombre de barrio, un minimapa y una herramienta de medición.
Gráfico de barras: Se representa la distribución de aparcamientos por barrios.
El siguiente código genera el mapa interactivo final.
mapa<-leaflet()%>%addProviderTiles("CartoDB.Positron")%>%# Capa coroplética con resaltado y etiquetasaddPolygons(data =barrios_union, fillColor =~pal(n_parkings), fillOpacity =0.7, color ="black", weight =1, highlightOptions =highlightOptions( color ="blue", weight =2, bringToFront =TRUE), label =~nombre, popup =~paste("<strong>Barrio:</strong>", nombre,"<br><strong>Parkings:</strong>", n_parkings), group ="Barrios (Choropleth)")%>%# Capa de marcadores con clústeraddMarkers(data =parkings_barrios_points, clusterOptions =markerClusterOptions(), popup =~paste("<strong>Parking OSM ID:</strong>", osm_id,"<br><strong>Barrio:</strong>", nombre,ifelse(is.na(name), "", paste("<br><strong>Nombre:</strong>", name))), group ="Parkings (Markers)")%>%# Buscador por nombre de barrioaddSearchFeatures( targetGroups ="Barrios (Choropleth)", options =searchFeaturesOptions(propertyName ="nombre", zoom =14, hideMarkerOnCollapse =TRUE))%>%# Minimapa y herramienta de mediciónaddMiniMap(tiles =providers$CartoDB.Positron, toggleDisplay =TRUE)%>%addMeasure(position ="topleft", primaryLengthUnit ="meters", primaryAreaUnit ="sqmeters", activeColor ="#3D535D", completedColor ="#7D4479")%>%# Leyenda, barra de escala y control de capasaddLegend("bottomright", pal =pal, values =barrios_union$n_parkings, title ="Nº de Parkings", opacity =0.7)%>%addScaleBar(position ="bottomleft")%>%addLayersControl(overlayGroups =c("Barrios (Choropleth)", "Parkings (Markers)"), options =layersControlOptions(collapsed =FALSE))%>%setView(lng =-0.3763, lat =39.4699, zoom =12)# Mostrar el mapa interactivo y el gráfico de barrasmapa
plot_parking
El fichero generado con este procedimiento puede descargarse desde aquí.
Proyectos de Innovación Educativa Emergente PIEE-2737007 y PIEE-3325394