Mejora del dataset de bibliotecas públicas de València con información de barrios

datos espaciales
OSM
Valencia
Autor/a
Afiliación

María Martín Leboreiro

Universitat de Valencia

Fecha de publicación

29 de marzo de 2025

Input

Las bibliotecas públicas juegan un papel muy importante en la vida de una ciudad. No solo son espacios de estudio o lectura, sino también centros culturales y puntos de acceso a la información para toda la ciudadanía. En esta práctica, nos hemos centrado en las bibliotecas públicas del municipio de València, con el objetivo de conocer su localización y ver cómo se reparten por los distintos barrios.

Para obtener los datos hemos utilizado OpenStreetMap (OSM). Los datos que ofrece OSM son abiertos, gratuitos y bastante completos, por lo que son muy útiles para hacer análisis espaciales como el que aquí se plantea.

La información sobre las bibliotecas se ha obtenido mediante una consulta al sistema de OSM utilizando RStudio. En concreto, se han extraído los elementos que están etiquetados como amenity=library dentro del área de València. El conjunto de datos resultante incluye varios campos, entre ellos:

  • osm_id: identificador único de cada biblioteca en OpenStreetMap.
  • name: nombre de la biblioteca (aunque muchos están en blanco).
  • operator: institución que gestiona la biblioteca.
  • opening_hours: horario de apertura (presente solo en algunos casos).
  • geometry: ubicación geográfica de cada biblioteca.

Aunque los datos nos permiten situar las bibliotecas en el mapa, no indican en qué barrio se encuentra cada una. Para completar esta información, hemos descargado otro conjunto de datos que contiene los límites de los barrios de València, disponible en el portal de datos abiertos del Ayuntamiento.

Gracias a este segundo archivo, hemos podido asignar a cada biblioteca el nombre del barrio al que pertenece, combinando ambas fuentes en un único conjunto de datos. De esta forma, podemos analizar con más detalle cómo están distribuidas las bibliotecas en la ciudad y si hay zonas con más o menos acceso a este tipo de servicio.

Descripción

A continuación, se detallan los pasos seguidos para obtener y preparar los datos de bibliotecas públicas en València, combinando información de OpenStreetMap con los límites oficiales de los barrios del municipio.

Cargamos las librerías necesarias:

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

Antes de construir la consulta a OpenStreetMap, definimos el área geográfica sobre la que queremos trabajar. En este caso, seleccionamos el municipio de València utilizando el código LAU correspondiente:

# Obtenemos el municipio de València
val_mun <- mapSpain::esp_get_munic() %>%
  filter(LAU_CODE == "46250")

# Creamos la bounding box
valencia_bb <- sf::st_bbox(val_mun)

Con la bounding box definida, realizamos la consulta para obtener los datos de las bibliotecas públicas. Nos interesan aquellos elementos etiquetados como amenity=library:

# Consulta a OSM para obtener bibliotecas
bibliotecas_osm <- opq(bbox = valencia_bb) %>%
  add_osm_feature(key = "amenity", value = "library") %>%
  osmdata_sf()

# Guardamos el resultado en formato sf
bibliotecas <- bibliotecas_osm$osm_points %>%
  select(osm_id, name, operator, opening_hours, website, geometry)

Comprobamos rápidamente las dimensiones del dataset:

dim(bibliotecas)
[1] 381   6

Y lo representamos sobre un mapa interactivo para confirmar que los datos están correctamente localizados:

leaflet(bibliotecas) %>%
  addTiles() %>%
  addCircleMarkers(
    radius = 5,
    color = "blue",
    stroke = FALSE,
    fillOpacity = 0.8
  ) %>%
  setView(lng = -0.3763, lat = 39.4699, zoom = 12)

Gracias a esta visualización inicial podemos comprobar que las bibliotecas están correctamente ubicadas en la ciudad de València, aunque todavía no sabemos a qué barrio pertenece cada una. Para ello, en el siguiente apartado se incorporará un conjunto de datos con los límites oficiales de los barrios y se llevará a cabo una unión espacial.

Tratamiento

Una vez cargados los datos, el objetivo principal de este proyecto es mejorar su utilidad incluyendo información adicional sobre el barrio al que pertenece cada biblioteca. Esto puede ayudar a identificar zonas con más o menos recursos bibliotecarios, y facilitar análisis territoriales más específicos.

Unión espacial con los barrios

Para enriquecer la información de cada biblioteca, hemos realizado una unión espacial con un shapefile que contiene los límites oficiales de los barrios de València. Esto nos permite asignar automáticamente a cada biblioteca el barrio en el que se encuentra.

# Cargamos el shapefile de los barrios
barrios <- st_read("data/barris-barrios/barris-barrios.shp")
Reading layer `barris-barrios' from data source 
  `C:\Users\scorp\OneDrive - Universitat de València\01 PROFESOR\06 Innovación Educativa\2023 2024\03 Web\datasets\data\barris-barrios\barris-barrios.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 88 features and 5 fields
Geometry type: POLYGON
Dimension:     XY
Bounding box:  xmin: -0.432535 ymin: 39.27893 xmax: -0.2753685 ymax: 39.56659
Geodetic CRS:  WGS 84
# Aseguramos que ambos objetos tengan el mismo sistema de coordenadas
barrios <- st_transform(barrios, st_crs(bibliotecas))

# Realizamos la unión espacial
bibliotecas_con_barrios <- st_join(bibliotecas, barrios["nombre"])

Una vez realizado el join, observamos que algunas bibliotecas no han sido asignadas a ningún barrio, probablemente porque están justo fuera de los límites o por imprecisiones en los datos. Por eso, filtramos y nos quedamos únicamente con aquellas que sí tienen asignado un barrio.

# Eliminamos registros sin barrio asignado
bibliotecas_barrios <- bibliotecas_con_barrios %>%
  filter(!is.na(nombre))

Recuento de bibliotecas por barrio

Con los datos ya limpios, podemos comprobar cuántas bibliotecas hay en cada barrio:

bibliotecas_barrios %>%
  st_drop_geometry() %>%
  count(nombre, sort = TRUE)
                nombre  n
1          ELS ORRIOLS 71
2            EXPOSICIO 46
3          LA CARRASCA 41
4            L'AMISTAT 23
5             NATZARET 20
6        SANT FRANCESC 15
7            BENIFERRI 10
8            BENIMAMET  9
9               LA SEU  9
10           BENICALAP  7
11            TRINITAT  7
12          NA ROVELLA  5
13        TRES FORQUES  5
14          EL BOTANIC  4
15             EL GRAU  2
16           TORREFIEL  2
17               AIORA  1
18         ARRANCAPINS  1
19          BENIMACLET  1
20 CABANYAL-CANYAMELAR  1
21           CAMI REAL  1
22      CIUTAT FALLERA  1
23            EL CARME  1
24    LA CREU DEL GRAU  1
25        LA FONTSANTA  1
26          LA PETXINA  1
27           LA RAIOSA  1
28            LA TORRE  1
29       LA VEGA BAIXA  1
30             MALILLA  1
31          MARXALENES  1
32            MESTALLA  1
33             PATRAIX  1
34             RUSSAFA  1
35            SANT PAU  1

Output

Tras el proceso de mejora y limpieza, hemos obtenido un conjunto de datos espaciales mucho más claro y útil para el análisis geográfico. El mapa final muestra las bibliotecas públicas del municipio de València correctamente clasificadas por barrio, sin datos erróneos o fuera del área de estudio.

A continuación, representamos las bibliotecas limpias con los barrios delimitados:

# Agrupar los barrios para el polígono
barrios_union <- barrios %>%
  filter(nombre %in% bibliotecas_barrios$nombre) %>%  
  group_by(nombre) %>%
  summarise()


# Crear una paleta de colores por barrio
paleta_barrios <- colorFactor(
  palette = "Set3",
  domain = barrios_union$nombre
)

leaflet() %>%
  addProviderTiles("CartoDB.Positron") %>%  # Mapa base limpio
  addPolygons(
    data = barrios_union,
    fillColor = ~paleta_barrios(nombre),
    fillOpacity = 0.3,
    color = "black",
    weight = 1,
    label = ~nombre,
    highlightOptions = highlightOptions(
      weight = 2,
      color = "blue",
      bringToFront = TRUE
    )
  ) %>%
  addCircleMarkers(
    data = bibliotecas_barrios,
    radius = 5,
    color = ~paleta_barrios(nombre),
    stroke = FALSE,
    fillOpacity = 0.8,
    label = ~paste(ifelse(is.na(name), "Biblioteca sin nombre", name), "<br>Barrio:", nombre)
  ) %>%
  addLegend(
    "bottomright",
    pal = paleta_barrios,
    values = barrios_union$nombre,
    title = "Barrios"
  ) %>%
  setView(lng = -0.3763, lat = 39.4699, zoom = 12)
Warning in RColorBrewer::brewer.pal(max(3, n), palette): n too large, allowed maximum for palette Set3 is 12
Returning the palette you asked for with that many colors
Warning in RColorBrewer::brewer.pal(max(3, n), palette): n too large, allowed maximum for palette Set3 is 12
Returning the palette you asked for with that many colors
Warning in RColorBrewer::brewer.pal(max(3, n), palette): n too large, allowed maximum for palette Set3 is 12
Returning the palette you asked for with that many colors
Warning in RColorBrewer::brewer.pal(max(3, n), palette): n too large, allowed maximum for palette Set3 is 12
Returning the palette you asked for with that many colors


El fichero generado con este procedimiento puede descargarse desde aquí.



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