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 y 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 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 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 de 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)
[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 son 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 [1] y paradas que tienen una similar demanda de pasajeros. Estos tiempos 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 depende del día hora y en qué parte de la ciudad/ruta se desarrollen los conflictos. Las variaciones se hicieron con una distribución uniforme. La selección de los días y horas responden a la experiencia de vivir en la ciudad de las marchas. La tercera función es la siguiente[2]

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 hay 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 tiene que ver con horas pico y paradas mas concurridas que otras. Las horas pico afectan más directamente a

[^1]:  En La Paz hay manifestaciones como hay cafés en Italia ↩︎