Data & policies & politics

Este post presenta una simulación del funcionamiento del sistema de transporte público Puma Katari, en La Paz Bolivia. La simulación seleccionó una de las 7 rutas,  estimó los tiempos de salida y llegada de los buses en sus 21 paradas y  las distancias recorridas. Con ello se construyó un funcionamiento numérico de laboratorio de los buses para 1 mes. Los intervalos de partida se basaron en datos oficiales.

¿Para qué simular?

  • Para demostrar que si se generaran los datos, no en laboratorio sino de verdad, podría medirse la eficiencia del sistema de transporte en tiempo real.
  • Para mostrar que las aplicaciones de conectar datos y buses  son numerosas; vincular  google maps con el servicio, por ejemplo.

Antecedentes de Los Puma Katari

Para más información: La Paz Bus

Estructura de la simulación

La simulación se basó en 4 momentos y se realizó en R, cuyo código se libera aquí:

1. Elegir la ruta y la dirección

La Paz Bus, opera en 7 rutas. De estas se eligió la ruta Chasquipampa. De esta ruta se eligió la dirección que parte de la parada de nombre "Mercado Camacho" y termina en la parada de nombre "Calle 63" de la zona de Chasquipampa. La ruta completa es de 13 kilómetros apróximadamente y tiene 21 paradas. El siguiente gráfico muestra la ruta, paradas y dirección seleccionada.

2. Recopilar la frecuencia de salidas

La freceuencia de salida de esta ruta está disponible en la página de La Paz Bus. Entre el 3 de abril de 2017 y el 1 de mayo del mismo año, periodo de la simulación, las frecuencias de salida derivaron en 167 recorridos a la ruta por día y 4676 recorridos por mes.

Esta fue la primera traducción a una función en R que se concatenó con otras para construir la base de datos. La función siguiente permitió automatizar la frecuencia de partidas.

intervalos.partida <- function(x) {
    if (hour(x) >= 7 & hour(x) < 11) incremento <- 10 * 60
    if (hour(x) >= 11 & hour(x) <= 13) incremento <- 5 * 60
    if (hour(x) >= 13 & hour(x) <= 17) incremento <- 10 * 60
    if (hour(x) >= 17 & hour(x) <= 23) incremento <- 5 * 60
    if (hour(x) >= 23) incremento <- 30 * 60
    if (hour(x) >= 0 & hour(x) <= 4) incremento <- 30 * 60
    if (hour(x) >= 4 & hour(x) < 6) incremento <- 10 * 60
    if (hour(x) ==  6) incremento <- 60 * 60
    
    incremento
 }

Aquí la prueba de funcionamiento de la función

(hora_actual <- as.POSIXct("2018-08-07 20:06:25"))
[1] "2018-08-07 20:06:25 GMT"
intervalos.partida(hora_atual) # prueba de la función
[1] 300 # 300 segundos

Cómo se ve en la fórmula desde las 17:00 a las 23:00 los buses parten cada 5 minutos (300 segundos)

3. Tomar los tiempos de recorrido de los buses en "condiciones normales"

Las condiciones normales de funcionamiento de los buses suceden por una combinación de horas que no son pico, mañanas entre 7 y  8 por ejemplo y  días sin manifestaciones sociales que interrumpan el tráfico y por tanto los tiempos  de recorrido de los buses.

Estos tiempos en "condiciones normales" se tomaron utilizando los buses 5 veces en días diferentes para luego tener un promedio. Por tanto, estos tiempos no son simulados, son verdaderos bajo una selección arbitraria de horas y días que se suponen normales.

Los tiempos que se computaron fueron:

  • Entre parada y parada, es decir, tiempo en ruta.
  • Entre llegada a una parada y salida de la misma, es decir, tiempo para recoger pasajeros.

El siguiente gráfico muestra los tiempos recolectados

Estos tiempos se tradujeron a una segunda función, que se resume por fines explicativos:

temp <- list()
tiempos.paradas <- function(x) {
  if (x == 1) {
    temp[[1]] <- 0
    temp[[2]] <- 0
  }  
  if (x == 2) {
    temp[[1]] <- hms("00:02:56") *# de la parada 1 a 2*
    temp[[2]] <- hms("00:00:24") *# tiempo en la parada 2 para recoger pasajeros*
  }
  if (x == 3) {
    temp[[1]] <- hms("00:02:29")
    temp[[2]] <- hms("00:00:19")
  }
 } # cierro el corchete aquí para el ejemplo

Prueba de la función de tiempos "normales"

tiempos.paradas(3)
[[1]]
[1] "2M 29S"
[[2]]
[1] "19S"

4. Realizar variaciones a los tiempos normales

Una primera variación consistió en introducir dos conflictos sociales en el mes, que duren dos días cada uno y  atrasen a los buses entre 45 y 120 minutos en ciertas horas y paradas, es decir, la alteración dependió del día hora y en qué parte de la ciudad/ruta se desarrollan los conflictos. Las variaciones se hicieron con una distribución uniforme. La selección de los días y horas para introducir a los conflictos simulados responden a la experiencia de vivir en la ciudad de las marchas. La tercera función es la siguiente:

conflicto <- function(x, y) {
  marcha <- 0

  if((day(x) == 3|day(x) == 4|day(x) == 13|day(x) == 14) &
     hour(x) >= 11 & hour(x) <= 12 &
     y == 3) {
    marcha <- runif(1, 45*60, 120*60) *# atraso de 45 minutos a 2 horas*
  }

  marcha
}

Ahora la prueba de la función: a una hora de navidad

fecha_hora <- as.POSIXct("2018-12-24 23:00:00")
parada <- 3
conflicto(fecha_hora, parada)
[1] 0 # Resultado: no hubieron conflictos en vísperas de navidad de este año

Ahora la prueba de la función cuando está programado el conflicto

fecha_hora <- as.POSIXct("2018-04-3 11:00:00")
parada <- 3
conflicto(fecha_hora, parada)
[1] 6319.477 # 6319 segundos o 105 minutos de atraso

La segunda variación se produce  que ver con horas pico y paradas mas concurridas que otras. Las horas pico afectan más directamente a