Puma Katari & Big Data

5 minute read

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 <- lubridate::now())
[1] "2018-08-07 20:06:25 GMT"
intervalos.partida(hora_atual)
[1] 300 *# 300 segundos*

Cómo se ve en la fóumula 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:

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")
  }
  if (x == 4) {
    temp[[1]] <- hms("00:04:02")
    temp[[2]] <- hms("00:00:11")
  }
  if (x == 5) {
    temp[[1]] <- hms("00:02:48")
    temp[[2]] <- hms("00:00:21")
  }
  if (x == 6) {
    temp[[1]] <- hms("00:01:30")
    temp[[2]] <- hms("00:00:10")
  }
  if (x == 7) {
    temp[[1]] <- hms("00:01:11")
    temp[[2]] <- hms("00:00:10")
  }
  if (x == 8) {
    temp[[1]] <- hms("00:02:53")
    temp[[2]] <- hms("00:00:12")
  }
  if (x == 9) {
    temp[[1]] <- hms("00:03:08")
    temp[[2]] <- hms("00:00:12")
  }
  if (x == 10) {
    temp[[1]] <- hms("00:02:38")
    temp[[2]] <- hms("00:00:23")
  }
  if (x == 11) {
    temp[[1]] <- hms("00:02:49")
    temp[[2]] <- hms("00:00:32")
  }
  if (x == 12) {
    temp[[1]] <- hms("00:02:14")
    temp[[2]] <- hms("00:00:13")
  }
  if (x == 13) {
    temp[[1]] <- hms("00:02:16")
    temp[[2]] <- hms("00:00:14")
  }
  if (x == 14) {
    temp[[1]] <- hms("00:01:16")
    temp[[2]] <- hms("00:00:11")
  }
  if (x == 15) {
    temp[[1]] <- hms("00:02:15")
    temp[[2]] <- hms("00:00:12")
  }
  if (x == 16) {
    temp[[1]] <- hms("00:01:52")
    temp[[2]] <- hms("00:00:15")
  }
  if (x == 17) {
    temp[[1]] <- hms("00:02:10")
    temp[[2]] <- hms("00:00:17")
  }
  if (x == 18) {
    temp[[1]] <- hms("00:01:18")
    temp[[2]] <- hms("00:00:11")
  }
  if (x == 19) {
    temp[[1]] <- hms("00:01:19")
    temp[[2]] <- hms("00:00:15")
  }
  if (x == 20) {
    temp[[1]] <- hms("00:01:12")
    temp[[2]] <- hms("00:00:07")
  }
  if (x == 21) {
    temp[[1]] <- hms("00:00:88")
    temp[[2]] <- 0
  }

  temp
}

Prueba de la función de tiempos “normales”

tiempos.paradas(20)
[[1]]
[1] "1M 12S"
[[2]]
[1] "7S"

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 siguiente2

    
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

    
*# primero en un día sin conflicto*
x <- (lubridate::now())
"2018-08-07 20:08:15 GMT"
conflicto(x, 3)
[1] 0 *#no hay atrasos por conflictos sociales*

*# ahora en día, hora y parada conflictiva*
y <- "2018-04-03 11:20:00" %>% as.POSIXct()
conflicto(y, 3)
[1] 3798.8 *#1 hora y tres minutos de atraso!*

La segunda variación tiene que ver con horas pico y paradas mas concurridas que otras. Las horas pico

  1. En La Paz hay manifestaciones como hay cafés en Italia 

  2. Los afectaran a toda la ruta pero usualmente los manifestantes se localizan cerca de una de las paradas, ya que mientras más concurrida la parada o la zona, más eficiente sienten bloquear la ruta porque el número de personas afectadas es mayor. 

Updated: