Introducción

El conjunto de datos usado en este ejercicio tiene información relativa a la cantidad de vehículos y velocidades correspondientes a diferentes calles en diferentes días de la semana. El conjuto de datos fue extraido del sitio de la Ciudad de Madrid, aforos de tráfico de la Ciudad de Madrid no permanentes.

Las mediciones realizadas atienden a la necesidad de conocer la cantidad de vehículos que circulan en un determinado punto de una calle en los diferentes días de una determinada semana. El programa R se utilizará para realizar el análisis de datos.

Preprocesamiento

Para comenzar este proyecto, todas las librerías necesarias se cargarán en R, después de eso, el conjunto de datos se ingresará en R. Finalmente, se realizará un análisis básico de las variables del conjunto de datos.

# Importar las librerías 
library(tidyverse)
library(leaflet)
library(plotly)

# Imporat lo conjunto de datos
data <- read.csv('2020_DATOS_AFOROS_NP.csv', sep =';',row.names=NULL)

# Verificar el conjunto de datos
str(data)
## 'data.frame':    147913 obs. of  67 variables:
##  $ row.names                     : chr  "1010398" "1010398" "1010398" "1010398" ...
##  $ ï..CODIGO                     : chr  "40,42262" "40,42262" "40,42262" "40,42262" ...
##  $ LATITUD                       : chr  "-3,71224" "-3,71224" "-3,71224" "-3,71224" ...
##  $ LONGITUD                      : chr  "27/01/2020" "27/01/2020" "27/01/2020" "27/01/2020" ...
##  $ FECHA                         : chr  "0:00" "1:00" "2:00" "3:00" ...
##  $ HORA                          : int  453 267 198 125 132 123 285 725 1048 949 ...
##  $ TOTAL                         : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.LIGEROS             : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.2.RUEDAS            : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.PESADOS             : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..DESCONOCIDO            : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEL_0.10                      : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEL_10.20                     : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEL_20.30                     : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEL_30.40                     : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEL_40.50                     : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEL_50.60                     : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEL_60.70                     : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEL_70.80                     : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEL_80.90                     : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEL_90.100                    : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEL_100.110                   : logi  NA NA NA NA NA NA ...
##  $ VEL_110.120                   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.LIGEROS.VEL_0.10    : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.PESADOS.VEL_0.10    : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..2.RUEDAS.VEL_0.10      : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..DESCONOCIDO.VEL_0.10   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.LIGEROS.VEL_10.20   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.PESADOS.VEL_10.20   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..2.RUEDAS.VEL_10.20     : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..DESCONOCIDO.VEL_10.20  : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.LIGEROS.VEL_20.30   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.PESADOS.VEL_20.30   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..2.RUEDAS.VEL_20.30     : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..DESCONOCIDO.VEL_20.30  : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.LIGEROS.VEL_30.40   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.PESADOS.VEL_30.40   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..2.RUEDAS.VEL_30.40     : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..DESCONOCIDO.VEL_30.40  : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.LIGEROS.VEL_40.50   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.PESADOS.VEL_40.50   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..2.RUEDAS.VEL_40.50     : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..DESCONOCIDO.VEL_40.50  : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.LIGEROS.VEL_50.60   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.PESADOS.VEL_50.60   : logi  NA NA NA NA NA NA ...
##  $ VEHIC..2.RUEDAS.VEL_50.60     : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..DESCONOCIDO.VEL_50.60  : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.LIGEROS.VEL_60.70   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.PESADOS.VEL_60.70   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..2.RUEDAS.VEL_60.70     : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..DESCONOCIDO.VEL_60.70  : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.LIGEROS.VEL_70.80   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.PESADOS.VEL_70.80   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..2.RUEDAS.VEL_70.80     : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..DESCONOCIDO.VEL_70.80  : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.LIGEROS.VEL_80.90   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.PESADOS.VEL_80.90   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..2.RUEDAS.VEL_80.90     : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..DESCONOCIDO.VEL_80.90  : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.LIGEROS.VEL_90.100  : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.PESADOS.VEL_90.100  : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..2.RUEDAS.VEL_90.100    : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..DESCONOCIDO.VEL_90.100 : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.LIGEROS.VEL_100.110 : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHICULOS.PESADOS.VEL_100.110 : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..2.RUEDAS.VEL_100.110   : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ VEHIC..DESCONOCIDO.VEL_100.110: int  NA NA NA NA NA NA NA NA NA NA ...

Con el análisis de datos inicial realizado, se puede notar que la columna 1 row.name se ingresa incorrectamente en el conjunto de datos. Por lo tanto, es necesario ajustar todas las columnas del conjunto de datos. Además, se puede ver que lo conjunto de datos tiene 147913 líneas y 67 columnas.

Para este análisis de datos del informe, se utilizarán solo las variables de la columna 2 LATITUD a la columna 6 TOTAL.

# Refinar nombres de las columnas
cn <- names(data)[-1]
colnames(data) <- cn

# Separar las columnas
data <- data[ ,2:6]

# Verificar el conjunto de datos 
str(data)
## 'data.frame':    147913 obs. of  5 variables:
##  $ LATITUD : chr  "40,42262" "40,42262" "40,42262" "40,42262" ...
##  $ LONGITUD: chr  "-3,71224" "-3,71224" "-3,71224" "-3,71224" ...
##  $ FECHA   : chr  "27/01/2020" "27/01/2020" "27/01/2020" "27/01/2020" ...
##  $ HORA    : chr  "0:00" "1:00" "2:00" "3:00" ...
##  $ TOTAL   : int  453 267 198 125 132 123 285 725 1048 949 ...

Después de la limpieza obtenemos un total de 5 variables en el conjunto de datos. Esos nombres y definiciones disponibles se ilustran en la Tabla 1 a continuación.

Tabla 1 - Descripción del conjunto de datos variables

Columna Descripción
LATITUD Latitud en coordenadas geográficas donde fue instalado el tubo neumático
LONGITUD Longitud en coordenadas geográficas donde fue instalado el tubo neumático
FECHA Fecha de la medición
HORA Hora de la medición
TOTAL Número total de vehículos

Análisis de los datos

Antes de comenzar el análisis de datos, se verificará si faltan valores en el conjunto de datos limpio.

# Verificar valores faltantes del conjunto de datos
any(is.na(data))
## [1] FALSE

No faltan valores en el conjunto de datos, por lo tanto, podemos comenzar el análisis de datos. Inicialmente, las variables del conjunto de datos deben transformarse a la clase correcta.

# Ajustar clases de variables
# Latitud y Longitud
data$LATITUD <-  as.numeric(gsub(",", ".", data$LATITUD, fixed = TRUE))
data$LONGITUD <- as.numeric(gsub(",", ".", data$LONGITUD, fixed = TRUE))
# Fecha
data$FECHA <- as.Date(data$FECHA, format = '%d/%m/%Y')

# Verificar el conjunto de datos 
summary(data)
##     LATITUD            LONGITUD          FECHA                HORA          
##  Min.   :      40   Min.   :-3.780   Min.   :2019-12-23   Length:147913     
##  1st Qu.:      40   1st Qu.:-3.707   1st Qu.:2020-01-27   Class :character  
##  Median :      40   Median :-3.691   Median :2020-02-12   Mode  :character  
##  Mean   :   44957   Mean   :-3.683   Mean   :2020-02-10                     
##  3rd Qu.:      40   3rd Qu.:-3.659   3rd Qu.:2020-02-28                     
##  Max.   :40420794   Max.   :-3.582   Max.   :2020-03-18                     
##  NA's   :328        NA's   :328                                             
##      TOTAL       
##  Min.   :   0.0  
##  1st Qu.:  61.0  
##  Median : 218.0  
##  Mean   : 374.1  
##  3rd Qu.: 516.0  
##  Max.   :4436.0  
## 

Observando el resumen del conjunto de datos, se puede notar que hay algo mal con la variable LATITUD, su máximo es 40420794, que está muy lejos del área de Madrid. Por lo tanto, esta variable necesita ser ajustada.

Más allá de eso, el conjunto de datos se filtrará para contener solo los valores de enero de 2020 a febrero de 2020 y la latitud y la longitud se redondearán a un número decimal más pequeño.

# Limpiar conjunto de datos 
data <- data %>% 
        filter(LATITUD<41) %>%
        filter(FECHA >= '2020-01-01' & FECHA <= '2020-02-29')

# Redondear el latidut and longitud
data$LATITUD <- round(data$LATITUD, 3)
data$LONGITUD <- round(data$LONGITUD, 3)

# Verificar el conjunto de datos 
str(data)
## 'data.frame':    111772 obs. of  5 variables:
##  $ LATITUD : num  40.4 40.4 40.4 40.4 40.4 ...
##  $ LONGITUD: num  -3.71 -3.71 -3.71 -3.71 -3.71 ...
##  $ FECHA   : Date, format: "2020-01-27" "2020-01-27" ...
##  $ HORA    : chr  "0:00" "1:00" "2:00" "3:00" ...
##  $ TOTAL   : int  453 267 198 125 132 123 285 725 1048 949 ...

Ahora, el conjunto de datos tiene un total de 111772 líneas y 5 columnas.

El primer gráfico creado para la parte de análisis de datos de este informe ilustrará el número total de vehículos según la fecha. Para esto, el conjunto de datos debe agruparse por fecha y se sumará la variable TOTAL.

# Agrupar por fecha
data_fecha <- data %>%
     group_by(FECHA) %>%
     summarise(Total_Vehiculos = sum(TOTAL))

# Refinar nombre de la columna FECHA
colnames(data_fecha)[1] <- 'Fecha'

# Agregar día de la semana
data_fecha$Dia_Semana <- weekdays(data_fecha$Fecha)

Figura 1 - Número de vehículos según fecha

# Plotar gráfico
Plot1 <- ggplot(data_fecha, aes(x=Fecha, label=Dia_Semana, y=Total_Vehiculos))+
         geom_line()+
         labs(y='Número de vehículos')

ggplotly(Plot1, tooltip = c('Fecha','Dia_Semana'))

Se puede notar que los fines de semana son los días con menos intensidad de tráfico de vehículos. Para continuar con el análisis de datos, el segundo gráfico ilustrará la localización de cada observación de conjunto de datos.

Para crear la Figura 2, el conjunto de datos debe agruparse según las variables LATITUD y LONGITUD.

# Agrupar por localidad
data_localidad <- data %>%
    group_by(LATITUD, LONGITUD) %>%
    summarise(Total_Vehiculos = sum(TOTAL))

# Agregar las columnas latitud y longitud
data_localidad$LatLong <-
    paste(
        'Latitud =',
        as.character(data_localidad$LATITUD),
        'Longitud =',
        as.character(data_localidad$LONGITUD)
    )

Figura 2 - Vehículos localidad según latitud y longitud

# Plotar gráfico
leaflet(data_localidad) %>%
    addTiles() %>%
    addMarkers(
        lng   = data_localidad$LONGITUD,
        lat   = data_localidad$LATITUD,
        popup = data_localidad$LatLong
    )

Finalmente, para concluir el análisis de datos de este informe, se creará un gráfico para ilustrar la intensidad del tráfico de vehículos según la ubicación.

# Refinar conjunto de dados
data_localidad$LatLong <- NULL
names(data_localidad)[1:2] <- c('latitude', 'longitude')

# Crear una paleta de colores
paleta <-
    colorNumeric(
        palette = "RdYlBu",
        domain = c(data_localidad$Total_Vehiculos),
        reverse = TRUE
    )

Figura 3 - Número de vehículos según localidad

# Plotar gráfico
leaflet(data_localidad) %>%
    addTiles() %>%
    addCircleMarkers(
        color = ~ paleta(Total_Vehiculos),
        popup = ~ paste0("Número de vehículos: ", Total_Vehiculos)
    ) %>%
    addLegend(pal = paleta,
              values = data_localidad$Total_Vehiculos,
              title = "Número de Vehículos")

Conclusion

Para concluir, las ideas obtenidas por el análisis de datos realizado por este informe son que entre el período de enero a febrero de 2020, los días de la semana Sábabo y Domingo son los que menos tráfico de vehículos tuvieron. Más allá de eso, también es posible concluir que en febrero de 2020 el tráfico de vehículos fue más intenso que en enero de 2020.

Además, la Figura 3 muestra que la parte de la ciudad de Madrid que tuvo el tráfico de vehículos más intenso entre enero y febrero de 2020 está en Autovia Toledo, cerca del Puente de Praga.