A lo largo de este trabajo, se buscará comprender la accidentalidad en Medellín y utilizar los datos abiertos publicados por la Alcaldía de Medellín en el portal web GEOMEDELLÍN. El objetivo final de este trabajo es predecir la accidentalidad en Medellín y agrupar los barrios de la ciudad de acuerdo a su accidentalidad. Sin embargo, antes de comenzar a trabajar formalmente con los datos se realizará una limpieza rápida de los mismos, la cuál se irá puliendo conforme sea necesario.
El primer paso consiste en cargar el dataset. Previamente se combinaron en Excel los datos anuales de 2014 a 2018, se crearon algunas columnas auxiliares y se unificó la escritura de algunos registros.
setwd("~/Google Drive File Stream/Mi unidad/Especialización en Analítica/Analítca Predictiva [AP]/Trabajo Final AP")
Data <- read.csv("Datos/Consolidado Final.csv", sep=";", stringsAsFactors = TRUE)
head(Data)Originalmente se contaba con un dataset con 228693 filas y 28 columnas. En equipo se analizaron una a una las columnas de nuestro dataset y se optó por eliminar aquellas cuya información está duplicada o que no aportan datos valiosos. La columna hora fue eliminada dado que al analizarla notamos que solo contiene horas en la tarde, lo que nos hace creer que se trata de un error de imputación.
Delete <- c("OBJECTID","X", "Y", "RADICADO", "HORA", "BARRIO", "COMUNA", "DIRECCION_ENC", "MES_NOMBRE")
Data <- Data[ ,!(names(Data) %in% Delete)]
head(Data)Luego de esta eliminación de variables, nuestro dataset tiene dimensiones 228693x19.
Ahora ajustaremos el tipo de variable según los datos que contiene:
La columna que contiene las fechas es de tipo factor, por tanto, cambiamos la clase de la columna a Date:
Data$FECHA<-as.Date(Data$FECHA)
summary(Data$FECHA)## Min. 1st Qu. Median Mean 3rd Qu. Max.
## "2014-01-01" "2015-04-07" "2016-06-27" "2016-06-25" "2017-09-13" "2018-12-31"
Data$DIRECCION <- as.character(Data$DIRECCION)
Data$MES <- as.factor(Data$MES)
summary(Data)## ID FECHA DIA PERIODO
## Min. : 1 Min. :2014-01-01 Min. : 1.0 Min. :2014
## 1st Qu.: 57174 1st Qu.:2015-04-07 1st Qu.: 8.0 1st Qu.:2015
## Median :114347 Median :2016-06-27 Median :16.0 Median :2016
## Mean :114347 Mean :2016-06-25 Mean :15.7 Mean :2016
## 3rd Qu.:171520 3rd Qu.:2017-09-13 3rd Qu.:23.0 3rd Qu.:2017
## Max. :228693 Max. :2018-12-31 Max. :31.0 Max. :2018
##
## CLASE DIRECCION CBML CB
## Choque :152433 Length:228693 : 19757 : 19757
## Otro : 25179 Class :character 1019 : 5078 1019 : 5086
## Atropello : 22210 Mode :character 517 : 4436 517 : 4438
## Caída Ocupante: 21116 1507 : 4140 1507 : 4148
## Volcamiento : 7722 1012 : 4122 1012 : 4123
## Incendio : 29 1105 : 3751 1105 : 3757
## (Other) : 4 (Other):187409 (Other):187384
## TIPO_GEOCOD GRAVEDAD
## Malla vial :152937 HERIDO :126222
## No Ubicada : 19267 MUERTO : 1374
## Malla vial cruce invertido : 10882 SOLO DAÑOS:101097
## EPM sin Interior : 4541
## EPM con Interior : 2104
## Malla vial aproximada: CR 65-93: 479
## (Other) : 38483
## DISENO DIA_NOMBRE MES X_MAGNAMED
## Tramo de via :166952 DOMINGO :22210 8 : 20383 Min. :820000
## Interseccion : 34819 JUEVES :34221 9 : 19874 1st Qu.:832265
## Lote o Predio: 16841 LUNES :32778 5 : 19833 Median :834127
## Glorieta : 5431 MARTES :35390 3 : 19756 Mean :832876
## : 1284 MIÉRCOLES:34970 10 : 19625 3rd Qu.:835218
## Paso Elevado : 1074 SÁBADO :32826 7 : 19453 Max. :845503
## (Other) : 2292 VIERNES :36298 (Other):109769
## Y_MAGNAMED LONGITUD LATITUD COMUNA.REAL
## Min. :1172269 Min. :-75.70 Min. :6.152 LA CANDELARIA:43733
## 1st Qu.:1180453 1st Qu.:-75.59 1st Qu.:6.226 LAURELES :23856
## Median :1182934 Median :-75.58 Median :6.248 CASTILLA :21216
## Mean :1182940 Mean :-75.59 Mean :6.248 :19931
## 3rd Qu.:1185135 3rd Qu.:-75.57 3rd Qu.:6.268 EL POBLADO :17152
## Max. :1193451 Max. :-75.47 Max. :6.343 GUAYABAL :15223
## (Other) :87582
## BARRIO.REAL
## : 19939
## La Candelaria : 5086
## Caribe : 4438
## Campo Amor : 4148
## Perpetuo Socorro : 4123
## Los Conquistadores: 3757
## (Other) :187202
En el summary anterior se hizo notable que nuestro dataset contiene varios missing values en las columnas relacionadas con las comunas y los barrios. Primero revisemos aquellos registros con CBML pero sin dato en la variable BARRIO.REAL.
unique((Data$CBML[Data$BARRIO.REAL=="" & Data$CBML!=""]))## [1] Inst_16 Inst_14 AUC1 50 16 60 11 10 Inst_3
## [10] Inst_19 0 SN01 AUC2 Inst_18
## 697 Levels: 0 10 1001 10010020001 10010120002 10010160014 ... SN01
Se consultó en los datos de la Alcaldía a qué barrio correspondían los anteriores CBML y se asignaron:
Data$BARRIO.REAL[Data$CBML=="Inst_18"] <- "Cerro Nutibara"
Data$COMUNA.REAL[Data$CBML=="Inst_18"] <- "BELEN"
Data$BARRIO.REAL[Data$CBML=="Inst_16"] <- "La Alpujarra"
Data$COMUNA.REAL[Data$CBML=="Inst_16"] <- "LA CANDELARIA"
Data$BARRIO.REAL[Data$CBML=="Inst_19"] <- "Parque Juan Pablo II"
Data$COMUNA.REAL[Data$CBML=="Inst_19"] <- "GUAYABAL"
Data$BARRIO.REAL[Data$CBML=="Inst_3"] <- "Cementerio Universal"
Data$COMUNA.REAL[Data$CBML=="Inst_3"] <- "CASTILLA"
Data$BARRIO.REAL[Data$CBML=="Inst_14"] <- "U.D. Atanasio Girardot"
Data$COMUNA.REAL[Data$CBML=="Inst_14"] <- "LAURELES"
Data$BARRIO.REAL[Data$CBML=="AUC1"] <- "Cabecera Urbana San Cristobal"
Data$COMUNA.REAL[Data$CBML=="AUC1"] <- "SAN CRISTOBAL"
Data$BARRIO.REAL[Data$CBML=="AUC2"] <- "Cabecera San Antonio de Prado"
Data$COMUNA.REAL[Data$CBML=="AUC2"] <- "SAN ANTONIO DE PRADO"
Data$BARRIO.REAL[Data$CBML=="SN01"] <- "Juan XXIII La Quiebra"
Data$COMUNA.REAL[Data$CBML=="SN01"] <- "SAN JAVIER"
Data$BARRIO.REAL[Data$CBML=="60"] <- "Cabecera Urbana San Cristobal"
Data$COMUNA.REAL[Data$CBML=="60"] <- "SAN CRISTOBAL"
Data$BARRIO.REAL[Data$CBML=="16"] <- "Diego Echavarría"
Data$COMUNA.REAL[Data$CBML=="16"] <- "BELEN"
Data$BARRIO.REAL[Data$CBML=="10"] <- "La Alpujarra"
Data$COMUNA.REAL[Data$CBML=="10"] <- "LA CANDELARIA"
Data$BARRIO.REAL[Data$CBML=="0"] <- "La Florida"
Data$COMUNA.REAL[Data$CBML=="0"] <- "SAN ANTONIO DE PRADO"Además, eliminamos 1685 registros, de los cuales no tenemos información confiable sobre su ubicación.
Data<-Data[Data$TIPO_GEOCOD!="No Ubicada" & Data$DIRECCION!="CR 999 CL 999",]
#write.csv(Data, file="Datos/Consolidado2.csv", row.names = F)Revisemos los registros que quedan con COMUNA.REAL vacía que sí tienen una dirección coherente
DComuna <- Data[Data$COMUNA.REAL=="",]
sort(unique(DComuna$DIRECCION))## [1] "CL 103 CR 102" "CL 103 EE CR 103 EE"
## [3] "CL 104 CR 104 B" "CL 12 A sur CR 52"
## [5] "CL 12 A Sur CR 52" "CL 12 C Sur CR 50 C"
## [7] "CL 12 C Sur CR 50 EE" "CL 12 sur CR 49"
## [9] "CL 12 Sur CR 49" "CL 12 sur CR 50"
## [11] "CL 12 Sur CR 50" "CL 12 Sur CR 50 A"
## [13] "CL 12 Sur CR 50 B" "CL 12 Sur CR 50 C"
## [15] "CL 12 Sur CR 51" "CL 83 CR 67 A"
## [17] "Km 3 + 940 Vía Medellín Santa Elena" "Santa Elena KM 0"
## [19] "Santa Elena KM 1" "Santa Elena KM 13"
## [21] "Santa Elena KM 14" "Santa Elena KM 15"
## [23] "Santa Elena KM 2" "Santa Elena KM 3"
## [25] "Santa Elena KM 5" "Santa Elena KM 7"
## [27] "Santa Elena KM 9" "Tramo 7 Kilometro 0"
## [29] "Tramo 7 Kilometro 1" "Tramo 7 Kilometro 10"
## [31] "Tramo 7 Kilometro 11" "Tramo 7 Kilometro 12"
## [33] "Tramo 7 Kilometro 13" "Tramo 7 Kilometro 14"
## [35] "Tramo 7 Kilometro 15" "Tramo 7 Kilometro 16"
## [37] "Tramo 7 Kilometro 17" "Tramo 7 Kilometro 2"
## [39] "Tramo 7 Kilometro 3" "Tramo 7 Kilometro 4"
## [41] "Tramo 7 Kilometro 5" "Tramo 7 Kilometro 6"
## [43] "Tramo 7 Kilometro 7" "Tramo 7 Kilometro 8"
## [45] "Tramo 7 Kilometro 9" "Tramo 8 Kilometro 0"
## [47] "Tramo 8 Kilometro 1" "Tramo 8 Kilometro 10"
## [49] "Tramo 8 Kilometro 11" "Tramo 8 Kilometro 12"
## [51] "Tramo 8 Kilometro 15" "Tramo 8 Kilometro 17"
## [53] "Tramo 8 Kilometro 2" "Tramo 8 Kilometro 20"
## [55] "Tramo 8 Kilometro 3" "Tramo 8 Kilometro 4"
## [57] "Tramo 8 Kilometro 5" "Tramo 8 Kilometro 6"
## [59] "Tramo 8 Kilometro 7" "Tramo 8 Kilometro 8"
## [61] "Tramo 8 Kilometro 9" "Tramo 8 KM 1"
## [63] "Tramo 8 KM 10" "Tramo 8 KM 11"
## [65] "Tramo 8 KM 12" "Tramo 8 KM 2"
## [67] "Tramo 8 KM 3" "Tramo 8 KM 5"
## [69] "Tramo 8 KM 6" "Tramo 8 KM 7"
## [71] "Tramo 8 KM 8" "Tramo 8 KM 9"
## [73] "Vía Las Palmas KM 2 + 400" "Vía Las Palmas KM 5 + 930 Mts"
## [75] "Vía Las Palmas Km 6 + 770 mts" "Via Las Palmas km 8 + 300"
## [77] "Via Las Palmas Km 8 + 620 mts " "Via Las Palmas Km 9 + 200 mts"
## [79] "Vía Las Palmas KM 9 + 210 mts" "Vía Las Palmas Km 9 + 30"
## [81] "VIA PALMAS KM 6 + 840 MTS" "VIA PALMAS KM 8 + 200"
## [83] "VIA PALMAS KM 9 +350 MTS" "Via Santa Elena Km 11 + 940"
Al parecer varias direcciones se repiten muchas veces, notemos que de 492 tenemos 84 valores únicos. Note que en los registros con dirección “Tramo 8 …” hay valores con la misma dirección escrita de dos maneras, solucionamos esto:
DComuna$DIRECCION <- gsub("KM", "Kilometro", DComuna$DIRECCION)
DComuna$DIRECCION <- gsub("sur", "Sur", DComuna$DIRECCION)
Data$DIRECCION <- gsub("KM", "Kilometro", Data$DIRECCION)
Data$DIRECCION <- gsub("sur", "Sur", Data$DIRECCION)
sort(unique(DComuna$DIRECCION))## [1] "CL 103 CR 102"
## [2] "CL 103 EE CR 103 EE"
## [3] "CL 104 CR 104 B"
## [4] "CL 12 A Sur CR 52"
## [5] "CL 12 C Sur CR 50 C"
## [6] "CL 12 C Sur CR 50 EE"
## [7] "CL 12 Sur CR 49"
## [8] "CL 12 Sur CR 50"
## [9] "CL 12 Sur CR 50 A"
## [10] "CL 12 Sur CR 50 B"
## [11] "CL 12 Sur CR 50 C"
## [12] "CL 12 Sur CR 51"
## [13] "CL 83 CR 67 A"
## [14] "Km 3 + 940 Vía Medellín Santa Elena"
## [15] "Santa Elena Kilometro 0"
## [16] "Santa Elena Kilometro 1"
## [17] "Santa Elena Kilometro 13"
## [18] "Santa Elena Kilometro 14"
## [19] "Santa Elena Kilometro 15"
## [20] "Santa Elena Kilometro 2"
## [21] "Santa Elena Kilometro 3"
## [22] "Santa Elena Kilometro 5"
## [23] "Santa Elena Kilometro 7"
## [24] "Santa Elena Kilometro 9"
## [25] "Tramo 7 Kilometro 0"
## [26] "Tramo 7 Kilometro 1"
## [27] "Tramo 7 Kilometro 10"
## [28] "Tramo 7 Kilometro 11"
## [29] "Tramo 7 Kilometro 12"
## [30] "Tramo 7 Kilometro 13"
## [31] "Tramo 7 Kilometro 14"
## [32] "Tramo 7 Kilometro 15"
## [33] "Tramo 7 Kilometro 16"
## [34] "Tramo 7 Kilometro 17"
## [35] "Tramo 7 Kilometro 2"
## [36] "Tramo 7 Kilometro 3"
## [37] "Tramo 7 Kilometro 4"
## [38] "Tramo 7 Kilometro 5"
## [39] "Tramo 7 Kilometro 6"
## [40] "Tramo 7 Kilometro 7"
## [41] "Tramo 7 Kilometro 8"
## [42] "Tramo 7 Kilometro 9"
## [43] "Tramo 8 Kilometro 0"
## [44] "Tramo 8 Kilometro 1"
## [45] "Tramo 8 Kilometro 10"
## [46] "Tramo 8 Kilometro 11"
## [47] "Tramo 8 Kilometro 12"
## [48] "Tramo 8 Kilometro 15"
## [49] "Tramo 8 Kilometro 17"
## [50] "Tramo 8 Kilometro 2"
## [51] "Tramo 8 Kilometro 20"
## [52] "Tramo 8 Kilometro 3"
## [53] "Tramo 8 Kilometro 4"
## [54] "Tramo 8 Kilometro 5"
## [55] "Tramo 8 Kilometro 6"
## [56] "Tramo 8 Kilometro 7"
## [57] "Tramo 8 Kilometro 8"
## [58] "Tramo 8 Kilometro 9"
## [59] "Vía Las Palmas Kilometro 2 + 400"
## [60] "Vía Las Palmas Kilometro 5 + 930 Mts"
## [61] "Vía Las Palmas Kilometro 9 + 210 mts"
## [62] "Vía Las Palmas Km 6 + 770 mts"
## [63] "Via Las Palmas km 8 + 300"
## [64] "Via Las Palmas Km 8 + 620 mts "
## [65] "Via Las Palmas Km 9 + 200 mts"
## [66] "Vía Las Palmas Km 9 + 30"
## [67] "VIA PALMAS Kilometro 6 + 840 MTS"
## [68] "VIA PALMAS Kilometro 8 + 200"
## [69] "VIA PALMAS Kilometro 9 +350 MTS"
## [70] "Via Santa Elena Km 11 + 940"
Ahora revisemos cuantos registros tenemos por dirección:
Direc <- as.data.frame(table(DComuna$DIRECCION))
Direc[order(-Direc$Freq),]Al revisar los datos con dirección “CL 12 Sur CR 50” notamos que en el Dataset ya está identificado a que BARRIO y COMUNA corresponde.
unique(Data[Data$DIRECCION=="CL 12 Sur CR 50",c("LONGITUD","LATITUD","COMUNA.REAL","BARRIO.REAL")])Así que solo reemplazamos:
Data$BARRIO.REAL[Data$DIRECCION=="CL 12 Sur CR 50"] <- "Santa María de los Ángeles"
Data$COMUNA.REAL[Data$DIRECCION=="CL 12 Sur CR 50"] <- "EL POBLADO"Realizamos este procedimiento con las demás direcciones y modificamos los registros con coincidencias:
unique(Data[Data$DIRECCION=="CL 12 Sur CR 49",c("LONGITUD","LATITUD","COMUNA.REAL","BARRIO.REAL")])Data$BARRIO.REAL[Data$DIRECCION=="CL 12 Sur CR 49"] <- "La Aguacatala"
Data$COMUNA.REAL[Data$DIRECCION=="CL 12 Sur CR 49"] <- "EL POBLADO"unique(Data[Data$DIRECCION=="CL 12 Sur CR 50 C",c("LONGITUD","LATITUD","COMUNA.REAL","BARRIO.REAL")])Data$BARRIO.REAL[Data$DIRECCION=="CL 12 Sur CR 50 C"] <- "Guayabal"
Data$COMUNA.REAL[Data$DIRECCION=="CL 12 Sur CR 50 C"] <- "GUAYABAL"unique(Data[Data$DIRECCION=="CL 12 A Sur CR 52",c("LONGITUD","LATITUD","COMUNA.REAL","BARRIO.REAL")])Data$BARRIO.REAL[Data$DIRECCION=="CL 12 A Sur CR 52"] <- "La Colina"
Data$COMUNA.REAL[Data$DIRECCION=="CL 12 A Sur CR 52"] <- "GUAYABAL"unique(Data[Data$DIRECCION=="CL 12 Sur CR 51" |Data$DIRECCION=="CL 12 Sur CR 50 A" ,c("LONGITUD","LATITUD","COMUNA.REAL","BARRIO.REAL")])Data$BARRIO.REAL[Data$DIRECCION=="CL 12 Sur CR 51"] <- "Guayabal"
Data$COMUNA.REAL[Data$DIRECCION=="CL 12 Sur CR 51"] <- "GUAYABAL"Ahora tenemos solo 269 registros sin comuna. Estos registros fueron corregidos manualmente en Excel asignando la comuna y barrio más cercanos, adicionalmente a los registros cuyas coordenadas se ubican sobre la VIA LAS PALMAS se les asignó como BARRIO y COMUNA: “VIA LAS PALMAS”. A partir de este nuevo dataset se crearan nuevas tablas que permitan trabajar por una parte, la predicción y por otra el agrupamiento, el análisis descriptivo de los datos se evidenciará a lo largo del trabajo.
Este documento contiene solo el pre-procesamiento de los datos necesario para lograr los objetivos propuestos en el trabajo. En el repositorio de Github Accidentalidad-AP se encuentra el material adicional y los informes adicionales relacionados con la predicción y el agrupamiento.