ACT5 - VCD

Enunciados

Valentina Cabrera

  1. Realice un análisis descriptivo completo y actualizado a julio 31 2024, incluyendo graficos, tablas y georreferenciación de la base de datos Accidentalidad_en_Barranquilla.csv. Deben entregar un script .R con los códigos usados.

  2. Realice una exploración y un análisis descriptivo completo (incluyendo tablas de resumen y gráficos) de la base de datos disponible en este enlace. Incluya gráficos que presenten los datos sobre un mapa de Colombia, para visualizar la distribución geográfica de los precios de los combustibles en el país (2018-2024).

Desarrollo

Librerías

library("readr") 
library("DT") 
library("ggplot2") 
library("dplyr") 
library("VIM") 
library("naniar") 
library("minqa") 
library("mice") 
library("tidyverse") 
library("hrbrthemes") 
library("gridExtra") 
library("missForest") 
library("outliers") 
library("EnvStats") 
library("sf") 
library("leaflet") 
library("stringr")

Punto 1

Base de datos

data <- read_csv("C:/Users/valcd/Downloads/Accidentalidad_en_Barranquilla_20240826.csv") 
datatable(   data[1:10, ],   caption = "Base de datos: Accidentalidad en Barranquilla",   options = list(     scrollX = TRUE,     scrollY = "450px",     paging=FALSE ) )

Análisis: características de la base de datos

Esta base de datos, proporcionada por la Alcaldía Distrital de Barranquilla, contiene información relacionada con los accidentes de tránsito que han ocurrido en la ciudad desde 2018 hasta el 30 de junio de 2024, según los informes policiales de accidente de tránstito (IPAT). Cada una de las columnas, proporciona información específica sobre cada evento, como por ejemplo la fecha y lugar dónde ocurrió, la cantidad de heridos, gravedad del suceso, etc.

En este caso, contamos con 25610 observaciones, las cuales representan cada accidente, y con 11 variables las cuales están nombradas como

names(data)
 [1] "FECHA_ACCIDENTE"                  "HORA_ACCIDENTE"                  
 [3] "GRAVEDAD_ACCIDENTE"               "CLASE_ACCIDENTE"                 
 [5] "SITIO_EXACTO_ACCIDENTE"           "CANT_HERIDOS_EN _SITIO_ACCIDENTE"
 [7] "CANT_MUERTOS_EN _SITIO_ACCIDENTE" "CANTIDAD_ACCIDENTES"             
 [9] "AÑO_ACCIDENTE"                    "MES_ACCIDENTE"                   
[11] "DIA_ACCIDENTE"                   
summary(data)
 FECHA_ACCIDENTE    HORA_ACCIDENTE     GRAVEDAD_ACCIDENTE CLASE_ACCIDENTE   
 Length:25610       Length:25610       Length:25610       Length:25610      
 Class :character   Class :character   Class :character   Class :character  
 Mode  :character   Mode  :character   Mode  :character   Mode  :character  
                                                                            
                                                                            
                                                                            
                                                                            
 SITIO_EXACTO_ACCIDENTE CANT_HERIDOS_EN _SITIO_ACCIDENTE
 Length:25610           Min.   : 1.000                  
 Class :character       1st Qu.: 1.000                  
 Mode  :character       Median : 1.000                  
                        Mean   : 1.472                  
                        3rd Qu.: 2.000                  
                        Max.   :42.000                  
                        NA's   :15626                   
 CANT_MUERTOS_EN _SITIO_ACCIDENTE CANTIDAD_ACCIDENTES AÑO_ACCIDENTE     
 Min.   :1.000                    Min.   :1           Length:25610      
 1st Qu.:1.000                    1st Qu.:1           Class :character  
 Median :1.000                    Median :1           Mode  :character  
 Mean   :1.036                    Mean   :1                             
 3rd Qu.:1.000                    3rd Qu.:1                             
 Max.   :2.000                    Max.   :2                             
 NA's   :25358                                                          
 MES_ACCIDENTE      DIA_ACCIDENTE     
 Length:25610       Length:25610      
 Class :character   Class :character  
 Mode  :character   Mode  :character  
                                      
                                      
                                      
                                      

También podemos observar que de las 11 variables, 3 de ellas, cant_heridos_en_sitio_accidente, cant_muertos_en_sitio_accidente y cantidad_accidentes, son numéricas y las 8 restantes son categóricas.

Análisis: variable según su tipo

Numéricas:

  • cant_heridos_en_sitio_accidente

    summary(data$`CANT_HERIDOS_EN _SITIO_ACCIDENTE`)
       Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
      1.000   1.000   1.000   1.472   2.000  42.000   15626 

    Lo que podemos mencionar sobre esta variable es que el promedio de personas heridas es aproximadamente 1 por accidente, sin embargo, se nota que hay casos en donde esto varió y hubo un alto número de personas afectadas, como es visible en la gráfica la cual cuenta con una gran cantidad de datos atípicos.

  • cant_muertos_en_sitio_accidente

    summary(data$`CANT_MUERTOS_EN _SITIO_ACCIDENTE`)
       Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
      1.000   1.000   1.000   1.036   1.000   2.000   25358 

    Lo que podemos mencionar sobre esta variable es que el promedio de personas muertas es 1 por accidente, sin embargo, se nota que estos valores varían entre 1 y 2 dada la existencia del dato atípico.

  • cantidad_accidentes

    summary(data$CANTIDAD_ACCIDENTES)
       Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
          1       1       1       1       1       2 

    Lo que podemos mencionar sobre esta variable es que el promedio de accidentes por hora específica en cada fecha es 1, sin embargo, se nota que estos valores varían entre 1 y 2 dada la existencia del dato atípico

Categóricas:

  • fecha_accidente

    frec_fecha<- data %>%   count(data$FECHA_ACCIDENTE) %>% arrange(desc(n))
    datatable(frec_fecha)

    Es decir, el día que hubo mayor cantidad de accidentes fue el 8 de junio del año 2018.

  • hora_accidente

    frec_hora<- data %>%   count(data$HORA_ACCIDENTE) %>% arrange(desc(n))
    datatable(frec_hora)

    Es decir que, según los datos recolectados, los accidentes tendían a ocurrir en su mayoría en horas de la tarde, más específicamente a las 3pm y 4pm.

  • gravedad_accidente

    Esta es una variable que cuenta con 3 posibles casos:

    [1] "Con heridos" "Solo daños"  "Con muertos"
    factor_gravedad<-as.factor(data$GRAVEDAD_ACCIDENTE) 
    frec_gravedad<-summary(factor_gravedad)  
    barplot(frec_gravedad,col = "lightblue", main = "Frecuencia del tipo de gravedad del
    accidente") 

    A partir de este diagrama de barras, se puede observar que la mayoría de los accidentes no tuvieron consecuencias graves para las personas, ya que en su mayoría solo se reportaron daños materiales. Además, el número de fallecidos es significativamente menor en comparación con los otros dos casos: Con heridos y Solo daños.

  • clase_accidente

    Esta variable cuenta con 6 posibles casos:

    [1] "Atropello"      "Choque"         "Caida Ocupante" "Volcamiento"   
    [5] "Otro"           "Incendio"      
    factor_clase<-as.factor(data$CLASE_ACCIDENTE) 
    frec_clase<-summary(factor_clase)  
    barplot(frec_clase, las = 2, col = "lightblue", main = "Frecuencia de cada clase de
    accidente") 

    A partir de esta gráfica, se puede observar claramente que la mayor cantidad de accidentes se debe, de manera significativa, al tipo Choque. El resto de las clases de accidentes se distribuye casi de manera proporcional entre las demás categorías, considerando la frecuencia de Atropello ligeramente mayor.

  • año_accidente

    frec_año<-table(data$AÑO_ACCIDENTE) 
    barplot(frec_año, col = "lightblue", main = "Frecuencia de año de ocurrencia del
    accidente") 

    Se puede observar que desde el año 2018 hasta el año actual, la tendencia de ocurrencia de accidentes ha disminuido. El año con el mayor número de accidentes registrados fue 2018, mientras que 2020 tuvo la menor frecuencia. A su vez, siguiendo la idea del principio, se nota que a partir del 2021, se mantiene un patrón de descenso continuo en la frecuencia de accidentes en la ciudad de Barranquilla.

  • mes_accidente

    frec_mes<-table(data$MES_ACCIDENTE) 
    print(frec_mes)
    
        April    August  December  February   January      July      June     March 
         2010      1918      2189      2477      2349      1932      2103      2446 
          May  November   October September 
         2121      1995      2090      1980 
    barplot(frec_mes,las =2, col = "lightblue", main = "Frecuencia de mes de ocurrencia del
    accidente") 

    Se puede observar que la cantidad de accidentes por mes es bastante similar, con valores cercanos a aproximadamente 2000. El mes con el mayor número de accidentes acumulados es febrero, con 2477 accidentes, mientras que el mes con el menor número es agosto, con 1918 registros.

  • dia_accidente

    frec_dia<-table(data$DIA_ACCIDENTE) 
    print(frec_dia)
    
     Fri  Mon  Sat  Sun  Thu  Tue  Wed 
    3920 3774 3735 2577 3756 4009 3839 
    barplot(frec_dia,las =2, col = "lightblue", main = "Frecuencia de día de ocurrencia del
    accidente") 

    En este gráfico, se puede observar que la frecuencia de accidentes es bastante parecida entre la mayoría de los días de la semana, con la excepción notable del domingo, que tiene una frecuencia visiblemente menor. Según los registros de este estudio, el día con la mayor cantidad de accidentes es el martes, con 4009 incidentes, mientras que, como ya se mencionó, el domingo tiene la menor cantidad, con 2577 accidentes.

Filtrado de la base de datos

Para esta sección, vamos a filtrar la base de datos con diferentes casos y, a su vez, haremos uso de la función table para explorar los datos.

  1. Accidentes de tipo choque ocurridos en los años 2018 y 2019

    Haremos un breve análisis de este subconjunto usando las variables dia_accidente, gravedad_accidente y mes_accidente.

    filtro1 <- data %>%   filter(CLASE_ACCIDENTE == "Choque" & AÑO_ACCIDENTE %in% c(2018, 2019))
    frec_diafiltro1 <- table(filtro1$DIA_ACCIDENTE) 
    print(frec_diafiltro1)
    
     Fri  Mon  Sat  Sun  Thu  Tue  Wed 
    1680 1602 1577 1002 1626 1727 1668 

    Al analizar este nuevo subconjunto con respecto a los días de la semana, podemos observar que el viernes sigue siendo el día con mayor cantidad de accidentes, en este caso, solo de tipo Choque.

    frec_gravedadfiltro1 <- table(filtro1$GRAVEDAD_ACCIDENTE) 
    print(frec_gravedadfiltro1)
    
    Con heridos Con muertos  Solo daños 
           2725          46        8111 

    Durante los años 2018 y 2019, los accidentes clasificados como Choque resultaron mayoritariamente en daños materiales. Además, es importante destacar que la frecuencia de Con muertos en estos accidentes fue significativamente menor en comparación con el número de Con heridos y Solo daños.

    frec_mesfiltro1 <- table(filtro1$MES_ACCIDENTE) 
    print(frec_mesfiltro1)
    
        April    August  December  February   January      July      June     March 
          940       919       931       874       885       856       849       930 
          May  November   October September 
          911       909       916       962 

    Podemos observar que los accidentes de tipo Choque durante los años 2018 y 2019 se distribuyeron de manera casi uniforme a lo largo de los 12 meses. La cantidad de incidentes por mes se aproxima a los 900. En comparación con la base de datos original, el mes con la menor cantidad de choques acumulados es junio, con 849 incidentes, mientras que el mes con la mayor frecuencia es septiembre, con 962 incidentes.

  2. Accidentes ocurridos los días sábado y domingo en el primer trimestre de cada año sin muertos

    Haremos un breve análisis de este subconjunto usando las variables año_accidente y clase_accidente.

    filtro2 <- data %>%   filter(DIA_ACCIDENTE %in% c("Sat", "Sun") &           MES_ACCIDENTE %in% c("January", "February", "March") &           GRAVEDAD_ACCIDENTE %in% c("Con heridos", "Solo daños"))
    frec_añofiltro2 <- table(filtro2$AÑO_ACCIDENTE) 
    print(frec_añofiltro2)
    
    2018 2019 2020 2021 2022 2023 2024 
     344  346  287  275  292  107  105 

    En este subconjunto de datos, se puede observar un comportamiento similar al de la base de datos principal, con una ligera tendencia a la disminución de accidentes a lo largo de los años. Sin embargo, se destaca que en 2019 y 2022, la frecuencia de accidentes es ligeramente superior en comparación con el año anterior. El año con la mayor cantidad de accidentes, según los filtros establecidos, fue 2019, con 346 registros, mientras que el año con la menor cantidad fue 2024, con 105 registros.

    frec_clasefiltro2 <- table(filtro2$CLASE_ACCIDENTE) 
    print(frec_clasefiltro2)
    
         Atropello Caida Ocupante         Choque       Incendio           Otro 
               107             13           1619              2              8 
       Volcamiento 
                 7 

    Para este resultado, se puede mencionar que la cantidad de accidentes de tipo Choque, según los filtros establecidos, es significativamente mayor en comparación con las demás clases de accidente. La cantidad de accidentes de esta clase es de 1619, mientras que la clase con la menor frecuencia es Incendio, con solo 2 registros. Este subconjunto, analizado desde la variable de clase_accidente, refleja el mismo comportamiento que la base de datos original, ya que la distribución de los accidentes en otras clases es relativamente igual, siendo la frecuencia de Atropello ligeramente superior.

  3. Accidentes ocurridos entre 2019 y 2021 en febrero

    Haremos un breve análisis de este subconjunto usando las variables dia_accidente, gravedad_accidente y clase_accidente.

    filtro3 <- data %>%   filter(AÑO_ACCIDENTE %in% c(2019, 2020, 2021) &           MES_ACCIDENTE == "February")
    frec_diafiltro3 <- table(filtro3$DIA_ACCIDENTE) 
    print(frec_diafiltro3)
    
    Fri Mon Sat Sun Thu Tue Wed 
    196 203 213 118 182 179 179 

    Durante el mes de febrero en los años 2019, 2020 y 2021, se puede afirmar que el día con la mayor cantidad de accidentes fue el sábado, con 213 incidentes. Por otro lado, el domingo registró la menor cantidad de accidentes, con 118 registros, siendo este el único valor significativamente distante de los demás días, que se mantienen cerca de los 200 registros.

    frec_gravedadfiltro3 <- table(filtro3$GRAVEDAD_ACCIDENTE) 
    print(frec_gravedadfiltro3)
    
    Con heridos Con muertos  Solo daños 
            372           4         894 

    Se puede decir que la mayor parte de los accidentes, según el filtro establecido, resultó en daños materiales, ya que la categoría Solo daños es la que cuenta con la mayor cantidad de incidentes, alcanzando 894 registros. Esto es significativamente más alto en comparación con las categorías Con heridos y Con muertos.

    frec_clasefiltro3 <- table(filtro3$CLASE_ACCIDENTE) 
    print(frec_clasefiltro3)
    
         Atropello Caida Ocupante         Choque           Otro    Volcamiento 
                52              4           1205              4              5 

    Este subconjunto, al igual que los anteriormente analizados, muestra una alta frecuencia en la clase de accidente Choque, que es significativamente mayor en comparación con las demás clases. Además, se observa que, nuevamente, la categoría Atropello tiene una frecuencia ligeramente superior a las otras, mientras que las demás clases de accidente presentan una distribución de datos más uniforme.

  4. Accidentes de tipo atropello ocurridos en octubre y diciembre ocurridos a las 6 am y 6 pm

    Haremos un breve análisis de este subconjunto usando las variables dia_accidente y gravedad_accidente.

    filtro4 <- data %>% filter(data$CLASE_ACCIDENTE == "Atropello" &                               data$MES_ACCIDENTE == c("October", "December") &                              data$HORA_ACCIDENTE == c("06:00:00:am", "06:00:00:pm"))
    frec_diafiltro4 <- table(filtro4$DIA_ACCIDENTE) 
    print(frec_diafiltro4)
    
    Thu Wed 
      1   1 

    En este caso, se puede observar que solo 2 registros cumplen con los filtros establecidos. De estos, uno ocurrió un martes y el otro un jueves.

    frec_gravedadfiltro4 <- table(filtro4$GRAVEDAD_ACCIDENTE) 
    print(frec_gravedadfiltro4)
    
    Con heridos 
              2 

    En cuanto a la gravedad de los accidentes, ambos registros resultaron en la categoría Con heridos, lo que explica que su frecuencia sea de 2.

  5. Accidentes ocurridos a las 3, 4 y 5, de la mañana y tarde, en los años 2022 y 2023

    Haremos un breve análisis de este subconjunto usando las variables mes_accidente, gravedad_accidente y clase_accidente.

    filtro5 <- data %>%   filter(HORA_ACCIDENTE %in% c("03:00:00:am", "04:00:00:am", "05:00:00:am",                                  "03:00:00:pm", "04:00:00:pm", "05:00:00:pm") &          AÑO_ACCIDENTE %in% c(2022, 2023))
    filtro5_mañana <- filtro5 %>%   filter(HORA_ACCIDENTE %in% c("03:00:00:am", "04:00:00:am",
                                                                 "05:00:00:am")) 
    filtro5_tarde <- filtro5 %>%   filter(HORA_ACCIDENTE %in% c("03:00:00:pm", "04:00:00:pm",
                                                                "05:00:00:pm")) 
    frec_mesf5mañana <- table(filtro5_mañana$MES_ACCIDENTE) 
    print(frec_mesf5mañana) 
    
        April    August  December  February   January      July      June     March 
            6         5         4         4         1         4         7         5 
          May  November September 
            2         4         2 
    frec_mesf5tarde <- table(filtro5_tarde$MES_ACCIDENTE) 
    print(frec_mesf5tarde)
    
        April    August  December  February   January      July      June     March 
           31        14         8        30        24        27        28        37 
          May  November   October September 
           19         8         6         7 

    Podemos observar una clara diferencia en la cantidad de accidentes entre la mañana y la tarde por mes en los años estudiados. A partir de estos datos, se puede afirmar que, al comparar las horas seleccionadas, era más probable que ocurrieran accidentes durante la tarde que en la mañana. Esto se evidencia en que la frecuencia más alta en el grupo de horas de la mañana es de 7 accidentes, mientras que en la tarde alcanza los 37.

    frec_gravedadf5mañana <- table(filtro5_mañana$GRAVEDAD_ACCIDENTE) 
    print(frec_gravedadf5mañana) 
    
    Con heridos Con muertos  Solo daños 
             26           6          12 
    frec_gravedadf5tarde <- table(filtro5_tarde$GRAVEDAD_ACCIDENTE) 
    print(frec_gravedadf5tarde)
    
    Con heridos Con muertos  Solo daños 
            114           5         120 

    Nuevamente, se observa una gran diferencia en las frecuencias de los tipos de consecuencias, excluyendo la categoría Con muertos, ya que para los dos grupos son prácticamente iguales. Según los resultados, se puede inferir que la cantidad de accidentes es mayor en la tarde dentro del grupo de horas escogidas, dado que la cantidad de registros por categoría de gravedad es significativamente mayor en la tarde comparado con la mañana.

    frec_clasef5mañana <- table(filtro5_mañana$CLASE_ACCIDENTE) 
    print(frec_clasef5mañana) 
    
      Atropello      Choque        Otro Volcamiento 
              3          38           1           2 
    frec_clasef5tarde <- table(filtro5_tarde$CLASE_ACCIDENTE) 
    print(frec_clasef5tarde)
    
         Atropello Caida Ocupante         Choque           Otro 
                16              1            221              1 

    Para ambos grupos, los accidentes de tipo Choque fueron los más frecuentes. Sin embargo, al igual que en los análisis previos, la frecuencia es significativamente mayor en el grupo de horas de la tarde.

    frec_cantidadf5mañana <- table(filtro5_mañana$CANTIDAD_ACCIDENTES) 
    print(frec_cantidadf5mañana) 
    
     1 
    44 
    frec_cantidadf5tarde <- table(filtro5_tarde$CANTIDAD_ACCIDENTES) 
    print(frec_cantidadf5tarde)
    
      1 
    239 

    Finalmente, podemos corroborar que en efecto la cantidad de accidentes del grupo de la tarde es significativamente mayor al de la mañana.

Identificación de valores NA

Para identificar la existencia de los datos Not Available en la base de datos, vamos a contarlos y graficarlos.

Primeramente, calculemos cuántos hay por columna.

cantidad_na <- sapply(data, function(x) sum(is.na(x))) 
for (columna in names(cantidad_na)) {  
  cat(columna, ":", cantidad_na[[columna]], "NA's \n") }
FECHA_ACCIDENTE : 0 NA's 
HORA_ACCIDENTE : 0 NA's 
GRAVEDAD_ACCIDENTE : 0 NA's 
CLASE_ACCIDENTE : 0 NA's 
SITIO_EXACTO_ACCIDENTE : 0 NA's 
CANT_HERIDOS_EN _SITIO_ACCIDENTE : 15626 NA's 
CANT_MUERTOS_EN _SITIO_ACCIDENTE : 25358 NA's 
CANTIDAD_ACCIDENTES : 0 NA's 
AÑO_ACCIDENTE : 0 NA's 
MES_ACCIDENTE : 0 NA's 
DIA_ACCIDENTE : 0 NA's 

Es decir, que de las 11 variables, solo 2, cant_heridos_en_sitio_accidente y cant_muertos_en_sitio_accidente, cuentan con datos faltantes. Nótese que, para la última mencionada, de las 25610 observaciones, 25318 son NA.

Ahora, veamos esto gráficamente.

gg_miss_var(data, show_pct = TRUE)

Para este gráfico, haremos un renombre temporal de las variables por cuestiones de estética.

data1 <- rename(data, fecha = FECHA_ACCIDENTE, hora = HORA_ACCIDENTE, grave = GRAVEDAD_ACCIDENTE, clase = CLASE_ACCIDENTE, sitio = SITIO_EXACTO_ACCIDENTE, hurt = `CANT_HERIDOS_EN _SITIO_ACCIDENTE`, dead = `CANT_MUERTOS_EN _SITIO_ACCIDENTE`, cantidad = CANTIDAD_ACCIDENTES, año = AÑO_ACCIDENTE, mes = MES_ACCIDENTE, dia = DIA_ACCIDENTE)
md.pattern(data1)

      fecha hora grave clase sitio cantidad año mes dia  hurt  dead      
83        1    1     1     1     1        1   1   1   1     1     1     0
9901      1    1     1     1     1        1   1   1   1     1     0     1
169       1    1     1     1     1        1   1   1   1     0     1     1
15457     1    1     1     1     1        1   1   1   1     0     0     2
          0    0     0     0     0        0   0   0   0 15626 25358 40984

En la primera gráfica, se muestra el porcentaje de datos que faltan en cada variable. Por ejemplo, alrededor del 55% de los datos en la variable cant_heridos_en_sitio_accidente son faltantes, y casi el 100% de los datos en cant_muertos_en_sitio_accidente también son NA.

La segunda gráfica confirma esta información, mostrando cuántos datos faltan en total por cada columna, lo que ayuda a entender mejor cuáles son las variables con más datos faltantes, tal como se calculó anteriormente.

Ahora, debido a que el porcentaje de NA’s de la variable cant_muertos_en_sitio_accidente es notablemente significativo, se puede borrar la columna.

data2 <- data[, -which(names(data) == "CANT_MUERTOS_EN _SITIO_ACCIDENTE")] 
datatable(
  data2[1:10, ],   caption = "Base de datos: Accidentalidad en Barranquilla",   options =list(     scrollX = TRUE,     scrollY = "450px",     paging=FALSE ) )

Por otra parte, cant_heridos_en_sitio_accidente puede considerarse una variable de tipo factor debido a que sus valores no son continuos, por lo tanto, realizar una imputación sobre ella no es realmente necesario. Esto se debe a que los NA’s en esta variable reflejan adecuadamente la información sobre las consecuencias del accidente. De hecho, observamos que los NA’s aparecen cuando la variable gravedad_accidente toma los valores Con muertos o Solo daños, lo que indica que la ausencia de datos en cant_heridos_en_sitio_accidente va de la mano con gravedad_accidente.

Detección de datos atípicos

Dado que las variables numéricas en este conjunto de datos pueden ser vistas y trabajadas como factores, la detección de valores atípicos no es la estrategia más efectiva. En vez de buscar anomalías, se optará por calcular tablas de frecuencias para analizar cómo se distribuyen las diferentes categorías. Este método proporcionará una visión clara de la distribución de los valores en estas variables discretas, facilitando un análisis más pertinente y ajustado a la naturaleza de los datos.

  • cant_heridos_en_sitio_accidente

    frec_heridos <- data2 %>%   count(data2$`CANT_HERIDOS_EN _SITIO_ACCIDENTE`) %>% arrange(desc(n)) 
    datatable(frec_heridos)

    Es evidente que hay una gran diferencia entre las frecuencias de los distintos valores que toma cant_heridos_en_sitio_accidente.

  • cantidad_accidentes

    frec_accidentes <- data2 %>%   count(data2$CANTIDAD_ACCIDENTES) %>% arrange(desc(n)) 
    datatable(frec_accidentes)

    Es muy notable la significante diferencia entre los 2 valores que toma la variable cantidad_accidentes.

Punto 2

Para este ejercicio, hay que, en primer lugar, unir todas las bases de datos para convertirlas en una sola.

#AÑO2023
d1<-read_csv("C:/Users/valcd/Downloads/precios_t12023.csv")
Rows: 66700 Columns: 7
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (6): BANDERA, NOMBRE COMERCIAL, PRODUCTO, FECHA REGISTRO, DEPARTAMENTO, ...
dbl (1): VALOR PRECIO

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
d2<-read_csv("C:/Users/valcd/Downloads/precios_t22023.csv")
Rows: 74112 Columns: 7
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (6): BANDERA, NOMBRE COMERCIAL, PRODUCTO, FECHA REGISTRO, DEPARTAMENTO, ...
dbl (1): VALOR PRECIO

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
d3<-read_csv("C:/Users/valcd/Downloads/precios_t32023.csv")
Rows: 62339 Columns: 7
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (6): BANDERA, NOMBRE COMERCIAL, PRODUCTO, FECHA REGISTRO, DEPARTAMENTO, ...
dbl (1): VALOR PRECIO

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
d4<-read_csv("C:/Users/valcd/Downloads/precios_t42023.csv")
Rows: 64792 Columns: 7
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (6): BANDERA, NOMBRE COMERCIAL, PRODUCTO, FECHA REGISTRO, DEPARTAMENTO, ...
dbl (1): VALOR PRECIO

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Base de datos

data23 <- bind_rows(d1,d2,d3,d4)
datatable(
  data23[1:10, ],
  caption = "Base de datos: Combustibles en Colombia",
  options = list(
    scrollX = TRUE,
    scrollY = "450px",
    paging=FALSE
)
)

Análisis: características de la base de datos

Esta base de datos, proporcionada por la página oficial de SICOM (sistema de información de la cadena de distribución de combustibles del Ministerio de Minas y Energía), brinda información relacionada con los precios de los combustibles distribuidos alrededor de Colombia durante el año 2023. Cada una de las columnas, ofrece información específica, como por ejemplo la empresa, el tipo de combustible y el precio de este.

En este caso, contamos con 267943 observaciones y con 7 variables las cuales están nombradas como

names(data23)
[1] "BANDERA"          "NOMBRE COMERCIAL" "PRODUCTO"         "FECHA REGISTRO"  
[5] "DEPARTAMENTO"     "MUNICIPIO"        "VALOR PRECIO"    
summary(data23)
   BANDERA          NOMBRE COMERCIAL     PRODUCTO         FECHA REGISTRO    
 Length:267943      Length:267943      Length:267943      Length:267943     
 Class :character   Class :character   Class :character   Class :character  
 Mode  :character   Mode  :character   Mode  :character   Mode  :character  
                                                                            
                                                                            
                                                                            
 DEPARTAMENTO        MUNICIPIO          VALOR PRECIO     
 Length:267943      Length:267943      Min.   :       0  
 Class :character   Class :character   1st Qu.:    9350  
 Mode  :character   Mode  :character   Median :   10880  
                                       Mean   :   12023  
                                       3rd Qu.:   13849  
                                       Max.   :14750147  

A su vez, podemos observar que de las 7 variables, solo 1, valor precio, es de tipo numérica.

Análisis: variable según tipo

Numéricas:

  • valor precio

    summary(data23$`VALOR PRECIO`)
        Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
           0     9350    10880    12023    13849 14750147 
    boxplot(data23$`VALOR PRECIO`,main="Precio del combustible")

    La variable muestra la presencia de valores extremos significativamente alejados de la mayoría de los datos. Según el análisis realizado, los precios del combustible en cada ubicación se concentran principalmente en el rango de 9000 a 14000 pesos, aproximadamente. En consecuencia, el valor extremo superior observado, 14750147, se destaca claramente como un dato atípico en comparación con el resto de los precios registrados.

Categóricas:

  • bandera

    unique(data23$BANDERA)
     [1] "TERPEL"              "TEXACO"              "PRIMAX"             
     [4] "ZEUSS "              "BIOMAX"              "PETROMIL "          
     [7] "ESSO"                "PETROBRAS"           "BRIO "              
    [10] "PUMA"                "PLUS MAS"            "ECOS"               
    [13] "OCTANO"              "AYATAWACOOP"         "DISCOWACOOP"        
    [16] "COOMULPINORT"        "DISCOM"              "P Y B"              
    [19] "PETRODECOL"          "PETRDECOL"           "SAVE"               
    [22] "PROXXON"             "ZAPATA Y VELASQUEZ "
    frec_bandera<- data23 %>%
      count(data23$BANDERA) %>% arrange(desc(n))
    datatable(frec_bandera)

    Es decir que, entre todas las comercializadoras, Terpel es la que más distribuye los diferentes tipos de combustible en el país.

  • producto

    factor_producto<-as.factor(data23$PRODUCTO)
    frec_producto <- summary(factor_producto) 
    barplot(frec_producto,col = "lightblue", main = "Frecuencia del tipo de combustible") 

    Se observa que la distribución del combustible tipo Extra es considerablemente inferior en comparación con los otros dos tipos. Además, es relevante mencionar que las frecuencias de Diesel y Gasolina Motor no difieren significativamente entre sí y que, entre ambos, el combustible más comercializado en Colombia durante el año 2023 fue la Gasolina Motor, con un total de 127338 registros.

  • departamento

    frec_departamento<- data23 %>%
      count(data23$DEPARTAMENTO) %>% arrange(desc(n))
    datatable(frec_departamento)

    Por lo tanto, podemos afirmar que el departamento en donde más se comercializó los 3 tipos de combustible durante el 2023 fue en Nariño, con 31054 registros.

Identificación de valores NA

Primeramente, calculemos de manera matemática la cantidad de datos faltantes.

cantidad_na_23 <- sapply(data23, function(x) sum(is.na(x)))
for (columna in names(cantidad_na_23)) {
  cat(columna, ":", cantidad_na_23[[columna]], "NA's \n")
}
BANDERA : 0 NA's 
NOMBRE COMERCIAL : 0 NA's 
PRODUCTO : 0 NA's 
FECHA REGISTRO : 0 NA's 
DEPARTAMENTO : 0 NA's 
MUNICIPIO : 0 NA's 
VALOR PRECIO : 0 NA's 

Es decir que la base de datos no contiene ningún dato de tipo NA.

Detección de datos atípicos

Hagamos uso de la herramienta boxplot para identificar la existencia de outliers.

ggplot(data23, aes(x = PRODUCTO, y = `VALOR PRECIO`)) +
  geom_boxplot() +
  scale_y_continuous(limits = c(0, 30000), labels = scales::comma) +
  labs(x = "Tipo de Producto", y = "Valor Precio", title = "Boxplot de Precio por Tipo de Producto") +
  theme_classic()
Warning: Removed 33 rows containing non-finite outside the scale range
(`stat_boxplot()`).

A partir de esto, observamos que hay una evidente existencia de datos atípicos en la variable valor precio. Por tanto, se procederá a realizar la imputación de estos.

Verifiquemos la normalidad de la variable

ks.test(data23$`VALOR PRECIO`, "pnorm", mean = mean(data23$`VALOR PRECIO`, na.rm = TRUE), sd = sd(data23$`VALOR PRECIO`, na.rm = TRUE))
Warning in ks.test.default(data23$`VALOR PRECIO`, "pnorm", mean =
mean(data23$`VALOR PRECIO`, : ties should not be present for the one-sample
Kolmogorov-Smirnov test

    Asymptotic one-sample Kolmogorov-Smirnov test

data:  data23$`VALOR PRECIO`
D = 0.42971, p-value < 2.2e-16
alternative hypothesis: two-sided

Al hacer la prueba de Kolmogorov-Smirnov, se obtuvo un \(p\) valor inferior a 0.05, esto indica que los datos no siguen una distribución normal. Es decir, la imputación debe realizarse haciendo uso de la mediana.

Q1 <- quantile(data23$`VALOR PRECIO`, 0.25, na.rm = TRUE)
Q3 <- quantile(data23$`VALOR PRECIO`, 0.75, na.rm = TRUE)

IQR <- Q3 - Q1

lim_inf <- Q1 - 1.5 * IQR
lim_sup <- Q3 + 1.5 * IQR

mediana <- median(data23$`VALOR PRECIO`, na.rm = TRUE)

data23$`VALOR PRECIO` <- ifelse(data23$`VALOR PRECIO` < lim_inf | data23$`VALOR PRECIO` > lim_sup, mediana, data23$`VALOR PRECIO`)

Ahora, observemos que en efecto se realizaron cambios en data23.

summary(data23$`VALOR PRECIO`)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   3500    9350   10880   11856   13750   20597 

Filtrado de la base de datos

Para este ejercicio, vamos a filtrar la base según un solo tipo de combustible: Gasolina Motor y luego procederemos a analizarla con respecto a las diferentes columnas.

data23_1 <- data23 %>% filter(data23$PRODUCTO == "GASOLINA MOTOR")
datatable(
  data23_1[1:10, ],
  caption = "Base de datos: Combustibles de Gasolina Motor",
  options = list(
    scrollX = TRUE,
    scrollY = "450px",
    paging=FALSE
)
)

Debido a que existen varios tipos de valores en BANDERA, vamos a analizarlo con los 4 de mayor frecuencia encontrados con la base original, con el fin de observar si hubo algún cambio en el comportimiento. Estos son Terpel, Primax, Biomax y Texaco.

empresa <- data23_1 %>% filter(data23_1$BANDERA %in% c("TERPEL", "PRIMAX", "BIOMAX", "TEXACO"))
frec_empresa <- table(empresa$BANDERA, empresa$PRODUCTO)
barplot(frec_empresa,
        beside = TRUE,  # Agrupa las barras
        col = c("lightblue", "lightgreen", "lightcoral", "lightpink"),
        legend.text = TRUE,
        main = "Frecuencia de empresas por Gasolina Motor",
        xlab = "Empresa",
        ylab = "Frecuencia",
        las = 1)

Es posible observar que, una vez más, la bandera Terpel es la que más comercializó combustible, en este caso de tipo Gasolina Motor, mientras que la que menos lo hizo fue Texaco. Por otro lado, se evidencia un cambio en el comportamiento entre Biomax y Primax pues para este producto, Biomax presenta una mayor frecuencia de comercialización. Sin embargo, al analizar los tres tipos de combustibles conjuntamente, Primax es la que se distribuyó con mayor frecuencia.

Realizaremos esto mismo con los 4 valores de DEPARTAMENTO con mayor frecuencia.

departamento <- data23_1 %>% filter(data23_1$DEPARTAMENTO %in% c("NARIÑO", "ANTIOQUIA", "NORTE DE SANTANDER", "VALLE DEL CAUCA"))
frec_dpto <- table(departamento$DEPARTAMENTO, departamento$PRODUCTO)
barplot(frec_dpto,
        beside = TRUE,  # Agrupa las barras
        col = c("lightblue", "lightgreen", "lightcoral", "lightpink"),
        legend.text = TRUE,
        main = "Frecuencia de departamentos por Gasolina Motor",
        xlab = "Empresa",
        ylab = "Frecuencia",
        las = 1)

Observamos que este subconjunto tiene el mismo comportamiento de la base de datos original para estos 4 departamentos.

Ahora, veamos cómo se comporta el precio de este tipo de combustible por departamento.

result <- data23_1 %>%
  group_by(DEPARTAMENTO) %>%    
  summarise(precio_promedio = mean(`VALOR PRECIO`, na.rm = TRUE)) %>%
  arrange((precio_promedio)) 


datatable(result)

Creemos un rango para definir el nivel en el que se encuentra el promedio, esto servirá más adelante para realizar el mapa.

rangos <- result %>%
  mutate(rango_precio = cut(precio_promedio,
                            breaks = c(10000, 12000, 14000, 16000),
                            labels = c("Bajo", "Medio", "Alto"),
                            right = FALSE)) %>%
  arrange(rango_precio)
datatable(rangos)

Se puede concluir que la mayoría de departamentos se encuentra en el rango establecido Medio, pues de los 32, solo NARIÑO y CESAR son de tipo BAJO, y en el caso de tipo ALTO solo encontramos a SAN ANDRES, GUAVIARE, VAUPES, GUAINIA y AMAZONAS.