Datos de/sobre paradas accesibles de Metro en Madrid

Autor/a
Afiliación

Mireia Doménech Rodríguez

Universidad de Valencia

Fecha de publicación

1 de abril de 2026

Input

El Consorcio Regional de Transportes de Madrid (CRTM) provee un ecosistema de datos abiertos esencial para la planificación de la movilidad metropolitana. En este proyecto, trabajamos con un conjunto de datos técnicos estructurados bajo el estándar internacional GTFS (General Transit Feed Specification), que detalla la arquitectura de la red de Metro de Madrid.

Para ello , se ha obtenido un conjunto de datos de la infraestructura ferroviaria de Metro de la ciudad de Madrid durante el año 2026. Estos datos , han sido extraídos del Portal de Datos Abiertos del Consorcio Regional de Transportes de Madrid (CRTM). La base de datos original se compone de diversos archivos tipo texto comprimidos en una sola carpeta . Este dataset trasciende la simple ubicación de paradas, integrando una jerarquía compleja que abarca desde los accesos de calle hasta la ubicación exacta de los andenes y las trazas de los itinerarios.

Nuestra finalidiad es lograr la división entre estaciones de Metro 100% accesibles y/o con ascensor funcionable.

Resumen de la base de datos :

  • Tema : Transporte público .

  • Cobertura geográfica : Comunidad de Madrid , España.

  • Fecha de lanzamiento : 2026 .

  • Frecuencia de actualización : Según cambios en la red (ISO 19139 Metadata Standard).

  • Fuente de los datos: Consorcio Regional de Transportes de Madrid (CRTM)

  • Régimen de Uso: Licencia abierta CRTM (reutilización permitida con cita de fuente) .

Descripción

Se procede a la configuración del entorno en R, cargando las librerías especializadas para el procesamiento de geometrías vectoriales (sf) y la gestión de datos (tidyverse) entre otras.

::: Aquí podemos descargar el dataset en formato txt :::

paradas <- read_csv("../data/2526020013/stops.txt")

Seguidamente , obetenemos la localización de las estaciones de la red mediante un proceso de consulta a la base de datos de OpenStreetMap (OSM), filtrando específicamente aquellas entidades etiquetadas con la combinación de claves railway=station y station=subway. Esta descarga y filtrado se realiza utilizando el paquete osmdata en R, acotando el ámbito geográfico al área metropolitana de Madrid mediante un bounding box específico.

bbox_madrid <- getbb("Madrid, Spain")

metro_madrid_query <- opq(bbox = bbox_madrid, timeout = 1000) %>%
  add_osm_feature(key = "railway", value = "station") %>%
  add_osm_feature(key = "station", value = "subway")

osm_metro_data <- osmdata_sf(metro_madrid_query)
puntos_metro_osm <- osm_metro_data$osm_points


puntos_metro_osm %>%
  leaflet::leaflet() %>%
  leaflet::addTiles() %>%
  leaflet::addCircles()

Al realizar una primera exploración de los datos obtenidos de OpenStreetMap, se identifica una fragmentación excesiva de la información: una sola estación de metro aparece representada por múltiples nodos independientes (accesos de calle, ascensores, andenes y salidas de emergencia). Esta dispersión requiere un tratamiento posterior para consolidar la geometría y evitar la duplicación de registros, garantizando que cada parada de la red se contabilice de forma única en nuestra base de datos.

Finalmente, el objeto generado incluye una estructura de datos muy densa, con decenas de columnas procedentes de las etiquetas de OSM (como name, railway, station, wheelchair, operator o wikidata). Sin embargo, al inspeccionar el dataframe, se observa que la gran mayoría de estas variables presentan una alta tasa de valores nulos (NA). Esto evidencia que, aunque la plataforma permite una descripción exhaustiva de cada punto (idiomas, detalles técnicos, accesos), en la práctica la información cargada por los usuarios es dispar e incompleta.

Por este motivo, resulta necesario realizar una selección crítica de las variables, conservando únicamente aquellas que aporten un valor real al análisis de accesibilidad y descartando el “ruido” de metadatos vacíos que solo añaden complejidad innecesaria al procesamiento de la información.

Tratamiento

El dataset original (stops.txt) contiene una estructura técnica diseñada para la interoperabilidad de sistemas de transporte (estándar GTFS), lo que implica la presencia de múltiples variables que no aportan valor directo a un análisis de accesibilidad física y geográfica. Por este motivo, procedemos a una limpieza selectiva y normalización de los datos.

paradas <- paradas %>%
select(stop_id, stop_name,stop_desc,stop_lat, stop_lon, location_type, parent_station, wheelchair_boarding) %>%
mutate(stop_name = toupper(stop_name))

head(paradas)
# A tibble: 6 × 8
  stop_id     stop_name stop_desc stop_lat stop_lon location_type parent_station
  <chr>       <chr>     <chr>        <dbl>    <dbl>         <dbl> <chr>         
1 par_4_1     PLAZA DE… Paseo de…     40.5    -3.69             0 est_90_21     
2 acc_4_1_1   PLAZA DE… Paseo de…     40.5    -3.69             2 est_90_21     
3 acc_4_1_10… ASCENSOR  Plaza de…     40.5    -3.69             2 est_90_21     
4 acc_4_1_10… INTERCAM… Paseo de…     40.5    -3.69             2 est_90_21     
5 acc_4_1_10… ASCENSOR  Paseo de…     40.5    -3.69             2 est_90_21     
6 acc_4_1_4   PASEO CA… Plaza de…     40.5    -3.69             2 est_90_21     
# ℹ 1 more variable: wheelchair_boarding <dbl>

Tras analizar el dataset original stops.txt, identificamos una limitación crítica: la información de accesibilidad en las estaciones principales (location_type 1) es inconsistente o inexistente (valores 0 o NA), a pesar de que muchas de ellas cuentan con infraestructura funcional. Para solventar este problema, desarrollamos un algoritmo de herencia de atributos basado en dos niveles de detección.

Metodología de Detección en “Nodos Hijo”

El principio fundamental de este proceso es que una estación debe considerarse accesible si al menos una de sus bocas de acceso o andenes dispone de la infraestructura necesaria. Para ello, se han creado dos bloques lógicos de clasificación:

A. Identificación de Infraestructura Física (Presencia de Ascensor)

En este primer bloque, el objetivo es localizar la existencia de elevadores, independientemente de su catalogación oficial. Para ello, realizamos un escaneado masivo de todos los registros del dataset (1.050 puntos), aplicando minería de texto en las columnas stop_name (nombre) y stop_desc (descripción). Buscamos los patrones de cadena "ascensor" o "elevador".

B. Validación de Accesibilidad Total (Silla de Ruedas + Ascensor)

Este segundo bloque es más restrictivo y garantiza que la estación sea plenamente funcional para Personas con Movilidad Reducida (PMR). Para ello cruzamos la existencia de la infraestructura detectada en el paso anterior con dos validadores adicionales: el valor oficial 1 en la columna wheelchair_boarding y la presencia de términos clave como "PMR", "rampa" o "accesible". * ¿Por qué lo hacemos? Existen casos donde un ascensor puede dar acceso solo a un vestíbulo pero no al andén. Al exigir una doble validación (infraestructura + confirmación de accesibilidad), generamos un indicador de “Accesibilidad Total” mucho más fiable para el usuario final.

El paso final y más importante es la vinculación jerárquica. Dado que un usuario busca una “estación” y no un “código de acceso técnico”, el algoritmo identifica el ID de la estación padre (parent_station) de cada boca accesible detectada.

De esta forma, si detectamos un ascensor en una de las tres bocas de una parada, esa información “asciende” automáticamente a la estación principal. Esto nos permite rescatar estaciones que el sistema marcaba como no accesibles, transformando un dato administrativo incompleto en una herramienta de consulta real, precisa y segura.

#BLOQUE 1: IDENTIFICACIÓN DE INFRAESTRUCTURA (ASCENSORES)
paradas_con_ascensor_ids <- paradas %>%
  mutate(nombre_min = tolower(paste(stop_name, stop_desc))) %>%
  filter(str_detect(nombre_min, "ascensor|elevador")) %>%
  pull(parent_station) %>%
  unique()

#BLOQUE 2: IDENTIFICACIÓN DE ACCESIBILIDAD TOTAL (ASCENSOR + SILLA)
paradas_accesibles_total_ids <- paradas %>%
  mutate(nombre_min = tolower(paste(stop_name, stop_desc))) %>%
  filter((str_detect(nombre_min, "ascensor|rampa|pmr|accesible")) | 
    (wheelchair_boarding == 1)) %>%
  pull(parent_station) %>%
  unique()

#CONSOLIDACIÓN FINAL DEL DATASET
paradas_finales <- paradas %>%
  filter(location_type == 1) %>%
  mutate(
    stop_name = toupper(stop_name),
    tiene_ascensor = stop_id %in% paradas_con_ascensor_ids,
    es_accesible_total = stop_id %in% paradas_accesibles_total_ids)

Una vez completada la fase de auditoría y mejora de datos, el flujo de trabajo requiere la división del dataset en dos estructuras independientes. Esta separación permite que la visualización posterior no sea una mera representación de puntos, sino una herramienta capaz de distinguir entre la infraestructura física (el objeto) y el estado operativo (la función de la estación).

Output

# --- CAPA 1: INFRAESTRUCTURA FÍSICA (UBICACIÓN EXACTA) ---
# Extracción de los puntos de acceso que albergan elevadores
puntos_ascensores_fisicos <- paradas %>%
  mutate(nombre_min = tolower(paste(stop_name, stop_desc))) %>%
  filter(str_detect(nombre_min, "ascensor|elevador")) %>%
  select(stop_name, stop_lat, stop_lon, parent_station)

# --- CAPA 2: AUDITORÍA DE RED (ESTADO LÓGICO DE ESTACIONES) ---
# Dataset consolidado mediante la lógica de herencia de accesibilidad
estaciones_estado_red <- paradas_finales

La segmentación de los datos en estos dos bloques responde a objetivos analíticos diferenciados:

  • Capa 1: El primer bloque se enfoca en la utilidad métrica sobre la trama urbana. A diferencia de un mapa convencional que sitúa el marcador en el centro geográfico de una estación, este filtro selecciona las coordenadas específicas de los accesos de calle. Mediante la búsqueda de los términos “ascensor” o “elevador”, se elimina el ruido visual de las bocas de metro compuestas únicamente por escaleras, permitiendo identificar el punto exacto de la acera donde se sitúa la infraestructura de elevación.

  • Capa 2: El segundo bloque representa la visión estratégica de la red de transporte. En este caso, el foco no reside en la ubicación de cada puerta individual, sino en el veredicto de accesibilidad de la estación como un nodo completo. Para ello, se utiliza el dataset procesado mediante la lógica de “herencia de atributos”, donde la estación principal hereda la condición de “Accesible” si se ha detectado infraestructura funcional en al menos uno de sus nodos dependientes (accesos).

Esta distinción técnica resuelve el desajuste entre los datos administrativos y la realidad física, proporcionando una base sólida para la creación de mapas que sirven tanto para el inventario técnico como para la guía de movilidad ciudadana.

library(leaflet)

leaflet() %>%
  addProviderTiles(providers$CartoDB.Positron) %>%
  addCircleMarkers(data = estaciones_estado_red, 
                   lng = ~stop_lon, lat = ~stop_lat, 
                   radius = 4, color = "grey", fillOpacity = 0.5,
                   label = ~stop_name) %>%
  addCircleMarkers(data = puntos_ascensores_fisicos,
                   lng = ~stop_lon, lat = ~stop_lat,
                   radius = 6, color = "#007bff", fillOpacity = 0.9,
                   popup = ~paste0("<b>UBICACIÓN ASCENSOR:</b><br>", stop_name)) %>%
  addLegend(position = "bottomright", 
            colors = c("grey", "#007bff"), 
            labels = c("Estación (Centro)", "Punto Exacto Ascensor"),
            title = "Infraestructura")

Este primer mapa interactivo utiliza una lógica de capas diferenciadas para resolver el problema de la imprecisión geográfica en el transporte público. El gráfico superpone círculos grises y azules sobre una base cartográfica clara con el objetivo de separar la información teórica de la práctica. Los círculos grises representan el centro administrativo de la parada y han sido configurados con un tamaño menor y cierta transparencia para funcionar únicamente como una referencia visual que permita al usuario ubicarse en el entorno general de la estación. Por otro lado, los círculos azules marcan la coordenada exacta de la acera donde el algoritmo ha detectado un elevador, utilizando un color vibrante para que el ojo identifique rápidamente la solución a su movilidad.

El motivo fundamental de este diseño es corregir el error de desplazamiento que presentan los datos oficiales. En estaciones grandes o con múltiples transbordos, el punto genérico del Metro suele estar situado a cientos de metros de la entrada accesible real. Al mostrar ambos puntos de forma simultánea, el usuario puede visualizar la distancia entre el nombre de la estación y la puerta específica por la que puede entrar sin barreras. Además, mediante el uso de pop-ups interactivos en los puntos azules, se proporciona la dirección exacta solo cuando se solicita la información, lo que permite transformar un mapa de transporte teórico en una herramienta de navegación práctica que se mantiene limpia y profesional.

paleta_semaforo <- colorFactor(
  palette = c("#28a745", "#ffc107", "#dc3545"), 
  domain = c("ACCESIBLE (TOTAL)", "SOLO ASCENSOR DETECTADO", "NO ACCESIBLE / SIN DATOS"))

leaflet(estaciones_estado_red) %>%
  addProviderTiles(providers$CartoDB.Positron) %>% 
  addCircleMarkers(
    lng = ~stop_lon, lat = ~stop_lat,
    radius = 8,
    color = ~case_when(
      es_accesible_total == TRUE ~ "#28a745",   
      tiene_ascensor == TRUE ~ "#ffc107",       
      TRUE ~ "#dc3545"),
    stroke = TRUE,      
    weight = 2,
    fillOpacity = 0.8,
    label = ~stop_name,
    popup = ~paste0(
      "<b>ESTACIÓN:</b> ", stop_name, 
      "<br><b>Estado Final:</b> ", 
      ifelse(es_accesible_total, "Accesible Total (Silla + Ascensor)", 
      ifelse(tiene_ascensor, "Infraestructura de Ascensor Detectada", "No Accesible / Sin Datos Oficiales")))) %>%
  addLegend(
    position = "bottomright",
    colors = c("#28a745", "#ffc107", "#dc3545"),
    labels = c("Accesibilidad Total Confirmada", "Ascensor Detectado (Auditoría)", "Sin Garantía de Accesibilidad"),
    title = "Estado de la Red de Metro")

El segundo mapa interactivo se ha diseñado bajo una lógica de auditoría semafórica para ofrecer un diagnóstico rápido del estado de accesibilidad en toda la red de Metro. A diferencia del mapa anterior, este gráfico no busca la precisión del acceso individual, sino el veredicto operativo de la estación como un nodo completo de transporte. Mediante el uso de un código de colores (verde, amarillo y rojo) sobre un fondo cartográfico claro, se permite que el usuario identifique de un solo vistazo qué paradas son seguras para su trayecto y cuáles presentan barreras o falta de información.

La elección de estos colores responde a la jerarquía de datos obtenida mediante el proceso de limpieza y herencia de atributos. Las estaciones en verde representan la accesibilidad total confirmada, donde tanto el dato oficial como la infraestructura detectada coinciden. Los puntos amarillos señalan aquellas estaciones que nuestro algoritmo ha “rescatado” al detectar un ascensor físico en sus accesos, a pesar de que la ficha técnica principal no lo reflejaba. Por último, los puntos rojos marcan las estaciones que no ofrecen garantías de accesibilidad o carecen de datos fiables. El motivo de utilizar este sistema visual es transformar una base de datos compleja en una herramienta de decisión inmediata, permitiendo al ciudadano planificar su ruta basándose en el estado real de la infraestructura y no solo en la información administrativa.