No se trata de una pauta para repetir sino diferentes ejemplos para daros ideas e inspiraros.
Se ha seleccionado un conjunto de datos del National Highway Traffic Safety Administration. El sistema de informes de análisis de mortalidad fue creado en los Estados Unidos por la National Highway Traffic Safety Administration para proporcionar una medida global de la seguridad en las carreteras. (Fuente Wikipedia). Los datos pertenecen al año 2020. Se trata de un conjunto de registros de accidentes que recogen datos significativos que los describen. Todos los accidentes tienen alguna víctima mortal como mínimo. El objetivo analítico que tenemos en mente es entender que hace que un accidente sea grave y que quiere decir que sea grave. https://www.nhtsa.gov/crash-data-systems/fatality-analysis-reporting-system
Queremos hacer una primera aproximación al conjunto de datos escogido y responder a las preguntas más básicas: ¿Cuánto registros tiene? ¿Cuántas variables? ¿De qué tipología son? ¿Cómo se distribuyen los valores de las variables? ¿Hay problemas con los datos, por ejemplo, campos vacíos? ¿Puedo intuir ya el valor analítico de los datos? ¿Qué primeras conclusiones puedo extraer?
El primer paso para realizar un análisis exploratorio es cargar el fichero de datos
#getwd() # ruta del directorio actual
#path = file.choose()
path = 'accident.CSV'
accidentData <- read.csv(path, row.names=NULL)
Verificamos la estructura del juego de datos principal. Vemos el número de columnas que tenemos y ejemplos de los contenidos de las filas.
structure = str(accidentData)
## 'data.frame': 35766 obs. of 81 variables:
## $ STATE : int 1 1 1 1 1 1 1 1 1 1 ...
## $ STATENAME : chr "Alabama" "Alabama" "Alabama" "Alabama" ...
## $ ST_CASE : int 10001 10002 10003 10004 10005 10006 10007 10008 10009 10010 ...
## $ VE_TOTAL : int 1 4 2 1 1 2 1 2 2 2 ...
## $ VE_FORMS : int 1 4 2 1 1 2 1 2 2 2 ...
## $ PVH_INVL : int 0 0 0 0 0 0 0 0 0 0 ...
## $ PEDS : int 0 0 0 0 0 0 1 0 0 0 ...
## $ PERSONS : int 4 6 2 5 1 3 1 2 4 3 ...
## $ PERMVIT : int 4 6 2 5 1 3 1 2 4 3 ...
## $ PERNOTMVIT : int 0 0 0 0 0 0 1 0 0 0 ...
## $ COUNTY : int 51 73 117 15 37 103 73 25 45 95 ...
## $ COUNTYNAME : chr "ELMORE (51)" "JEFFERSON (73)" "SHELBY (117)" "CALHOUN (15)" ...
## $ CITY : int 0 350 0 0 0 0 330 0 0 1500 ...
## $ CITYNAME : chr "NOT APPLICABLE" "BIRMINGHAM" "NOT APPLICABLE" "NOT APPLICABLE" ...
## $ DAY : int 1 2 2 3 4 4 7 8 9 10 ...
## $ DAYNAME : int 1 2 2 3 4 4 7 8 9 10 ...
## $ MONTH : int 1 1 1 1 1 1 1 1 1 1 ...
## $ MONTHNAME : chr "January" "January" "January" "January" ...
## $ YEAR : int 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 ...
## $ DAY_WEEK : int 4 5 5 6 7 7 3 4 5 6 ...
## $ DAY_WEEKNAME: chr "Wednesday" "Thursday" "Thursday" "Friday" ...
## $ HOUR : int 2 17 14 15 0 16 19 7 20 10 ...
## $ HOURNAME : chr "2:00am-2:59am" "5:00pm-5:59pm" "2:00pm-2:59pm" "3:00pm-3:59pm" ...
## $ MINUTE : int 58 18 55 20 45 55 23 15 0 2 ...
## $ MINUTENAME : chr "58" "18" "55" "20" ...
## $ NHS : int 0 0 0 0 0 0 0 0 0 1 ...
## $ NHSNAME : chr "This section IS NOT on the NHS" "This section IS NOT on the NHS" "This section IS NOT on the NHS" "This section IS NOT on the NHS" ...
## $ ROUTE : int 4 6 3 4 4 3 4 4 4 2 ...
## $ ROUTENAME : chr "County Road" "Local Street - Municipality" "State Highway" "County Road" ...
## $ TWAY_ID : chr "cr-4" "martin luther king jr dr" "sr-76" "CR-ALEXANDRIA WELLINGTON RD" ...
## $ TWAY_ID2 : chr "" "" "us-280" "" ...
## $ RUR_URB : int 1 2 1 1 1 1 2 1 1 1 ...
## $ RUR_URBNAME : chr "Rural" "Urban" "Rural" "Rural" ...
## $ FUNC_SYS : int 5 4 4 7 5 4 4 5 5 3 ...
## $ FUNC_SYSNAME: chr "Major Collector" "Minor Arterial" "Minor Arterial" "Local" ...
## $ RD_OWNER : int 2 4 1 2 2 1 4 2 2 1 ...
## $ RD_OWNERNAME: chr "County Highway Agency" "City or Municipal Highway Agency" "State Highway Agency" "County Highway Agency" ...
## $ MILEPT : int 0 0 49 0 0 390 0 0 0 3019 ...
## $ MILEPTNAME : chr "None" "None" "49" "None" ...
## $ LATITUDE : num 32.4 33.5 33.3 33.8 32.8 ...
## $ LATITUDENAME: chr "32.43313333" "33.48465833" "33.29994167" "33.79507222" ...
## $ LONGITUD : num -86.1 -86.8 -86.4 -85.9 -86.1 ...
## $ LONGITUDNAME: chr "-86.09485" "-86.83954444" "-86.36964167" "-85.88348611" ...
## $ SP_JUR : int 0 0 0 0 0 0 0 0 0 0 ...
## $ SP_JURNAME : chr "No Special Jurisdiction" "No Special Jurisdiction" "No Special Jurisdiction" "No Special Jurisdiction" ...
## $ HARM_EV : int 42 12 34 42 42 12 8 12 12 12 ...
## $ HARM_EVNAME : chr "Tree (Standing Only)" "Motor Vehicle In-Transport" "Ditch" "Tree (Standing Only)" ...
## $ MAN_COLL : int 0 6 0 0 0 2 0 1 1 2 ...
## $ MAN_COLLNAME: chr "The First Harmful Event was Not a Collision with a Motor Vehicle in Transport" "Angle" "The First Harmful Event was Not a Collision with a Motor Vehicle in Transport" "The First Harmful Event was Not a Collision with a Motor Vehicle in Transport" ...
## $ RELJCT1 : int 0 0 0 0 0 0 0 0 0 0 ...
## $ RELJCT1NAME : chr "No" "No" "No" "No" ...
## $ RELJCT2 : int 1 1 3 1 1 1 3 1 8 1 ...
## $ RELJCT2NAME : chr "Non-Junction" "Non-Junction" "Intersection-Related" "Non-Junction" ...
## $ TYP_INT : int 1 1 3 1 1 1 2 1 1 1 ...
## $ TYP_INTNAME : chr "Not an Intersection" "Not an Intersection" "T-Intersection" "Not an Intersection" ...
## $ WRK_ZONE : int 0 0 0 0 0 0 0 0 0 0 ...
## $ WRK_ZONENAME: chr "None" "None" "None" "None" ...
## $ REL_ROAD : int 4 1 4 4 4 1 1 1 1 1 ...
## $ REL_ROADNAME: chr "On Roadside" "On Roadway" "On Roadside" "On Roadside" ...
## $ LGT_COND : int 2 3 1 1 2 2 3 1 2 1 ...
## $ LGT_CONDNAME: chr "Dark - Not Lighted" "Dark - Lighted" "Daylight" "Daylight" ...
## $ WEATHER : int 1 2 2 10 2 1 1 1 10 10 ...
## $ WEATHERNAME : chr "Clear" "Rain" "Rain" "Cloudy" ...
## $ SCH_BUS : int 0 0 0 0 0 0 0 0 0 0 ...
## $ SCH_BUSNAME : chr "No" "No" "No" "No" ...
## $ RAIL : chr "0000000" "0000000" "0000000" "0000000" ...
## $ RAILNAME : chr "Not Applicable" "Not Applicable" "Not Applicable" "Not Applicable" ...
## $ NOT_HOUR : int 99 17 14 99 0 17 19 7 20 10 ...
## $ NOT_HOURNAME: chr "Unknown" "5:00pm-5:59pm" "2:00pm-2:59pm" "Unknown" ...
## $ NOT_MIN : int 99 18 58 99 45 0 23 21 0 3 ...
## $ NOT_MINNAME : chr "Unknown" "18" "58" "Unknown" ...
## $ ARR_HOUR : int 3 17 15 99 0 17 19 7 20 10 ...
## $ ARR_HOURNAME: chr "3:00am-3:59am" "5:00pm-5:59pm" "3:00pm-3:59pm" "Unknown EMS Scene Arrival Hour" ...
## $ ARR_MIN : int 10 26 15 99 55 19 29 28 10 7 ...
## $ ARR_MINNAME : chr "10" "26" "15" "Unknown EMS Scene Arrival Minutes" ...
## $ HOSP_HR : int 99 99 99 99 88 18 88 88 99 10 ...
## $ HOSP_HRNAME : chr "Unknown" "Unknown" "Unknown" "Unknown" ...
## $ HOSP_MN : int 99 99 99 99 88 51 88 88 99 29 ...
## $ HOSP_MNNAME : chr "Unknown EMS Hospital Arrival Time" "Unknown EMS Hospital Arrival Time" "Unknown EMS Hospital Arrival Time" "Unknown EMS Hospital Arrival Time" ...
## $ FATALS : int 3 1 1 1 1 1 1 1 1 1 ...
## $ DRUNK_DR : int 1 0 0 0 0 0 0 0 0 0 ...
Vemos que tenemos 81 variables y 35766 registros
Revisamos la descripción de las variables contenidas en el fichero y si los tipos de variables se corresponden con las que hemos cargado. Las organizamos lógicamente para darles sentido y construimos un pequeño diccionario de datos utilizando la documentación auxiliar.
HECHOS A ESTUDIAR
DIMENSIÓN GEOGRÁFICA
DIMENSIÓN TEMPORAL
DIMENSIÓN CONDICICIONES ACCIDENTE
DIMENSIÓN METEOROLOGIA
OTROS
DIMENSIÓN SERVICIO EMERGENCIAS
DIMENSIÓN FACTORES RELACIONADOS ACCIDENTE
El siguiente paso será la limpieza de datos, mirando si hay valores vacíos o nulos.
print('NA')
## [1] "NA"
colSums(is.na(accidentData))
## STATE STATENAME ST_CASE VE_TOTAL VE_FORMS PVH_INVL
## 0 0 0 0 0 0
## PEDS PERSONS PERMVIT PERNOTMVIT COUNTY COUNTYNAME
## 0 0 0 0 0 0
## CITY CITYNAME DAY DAYNAME MONTH MONTHNAME
## 0 0 0 0 0 0
## YEAR DAY_WEEK DAY_WEEKNAME HOUR HOURNAME MINUTE
## 0 0 0 0 0 0
## MINUTENAME NHS NHSNAME ROUTE ROUTENAME TWAY_ID
## 0 0 0 0 0 0
## TWAY_ID2 RUR_URB RUR_URBNAME FUNC_SYS FUNC_SYSNAME RD_OWNER
## 0 0 0 0 0 0
## RD_OWNERNAME MILEPT MILEPTNAME LATITUDE LATITUDENAME LONGITUD
## 0 0 0 0 0 0
## LONGITUDNAME SP_JUR SP_JURNAME HARM_EV HARM_EVNAME MAN_COLL
## 0 0 0 0 0 0
## MAN_COLLNAME RELJCT1 RELJCT1NAME RELJCT2 RELJCT2NAME TYP_INT
## 0 0 0 0 0 0
## TYP_INTNAME WRK_ZONE WRK_ZONENAME REL_ROAD REL_ROADNAME LGT_COND
## 0 0 0 0 0 0
## LGT_CONDNAME WEATHER WEATHERNAME SCH_BUS SCH_BUSNAME RAIL
## 0 0 0 0 0 0
## RAILNAME NOT_HOUR NOT_HOURNAME NOT_MIN NOT_MINNAME ARR_HOUR
## 0 0 0 0 0 0
## ARR_HOURNAME ARR_MIN ARR_MINNAME HOSP_HR HOSP_HRNAME HOSP_MN
## 0 0 0 0 0 0
## HOSP_MNNAME FATALS DRUNK_DR
## 0 0 0
print('Blancos')
## [1] "Blancos"
colSums(accidentData=="")
## STATE STATENAME ST_CASE VE_TOTAL VE_FORMS PVH_INVL
## 0 0 0 0 0 0
## PEDS PERSONS PERMVIT PERNOTMVIT COUNTY COUNTYNAME
## 0 0 0 0 0 0
## CITY CITYNAME DAY DAYNAME MONTH MONTHNAME
## 0 0 0 0 0 0
## YEAR DAY_WEEK DAY_WEEKNAME HOUR HOURNAME MINUTE
## 0 0 0 0 0 0
## MINUTENAME NHS NHSNAME ROUTE ROUTENAME TWAY_ID
## 0 0 0 0 0 0
## TWAY_ID2 RUR_URB RUR_URBNAME FUNC_SYS FUNC_SYSNAME RD_OWNER
## 26997 0 0 0 0 0
## RD_OWNERNAME MILEPT MILEPTNAME LATITUDE LATITUDENAME LONGITUD
## 0 0 0 0 0 0
## LONGITUDNAME SP_JUR SP_JURNAME HARM_EV HARM_EVNAME MAN_COLL
## 0 0 0 0 0 0
## MAN_COLLNAME RELJCT1 RELJCT1NAME RELJCT2 RELJCT2NAME TYP_INT
## 0 0 0 0 0 0
## TYP_INTNAME WRK_ZONE WRK_ZONENAME REL_ROAD REL_ROADNAME LGT_COND
## 0 0 0 0 0 0
## LGT_CONDNAME WEATHER WEATHERNAME SCH_BUS SCH_BUSNAME RAIL
## 0 0 0 0 0 0
## RAILNAME NOT_HOUR NOT_HOURNAME NOT_MIN NOT_MINNAME ARR_HOUR
## 0 0 0 0 0 0
## ARR_HOURNAME ARR_MIN ARR_MINNAME HOSP_HR HOSP_HRNAME HOSP_MN
## 0 0 0 0 0 0
## HOSP_MNNAME FATALS DRUNK_DR
## 0 0 0
Vemos que no hay valores nulos en los datos. También verificamos si existen campos llenos de espacios en blanco. En este caso sí encontramos el campo TWAY_ID2 con 26997 valores en blanco. Valoramos no hacer ninguna acción de eliminar registros puesto que este campo no lo utilizaremos.
Vamos a crear histogramas y describir los valores para ver los datos en general de estos atributos para hacer una primera aproximación a los datos:
if (!require('ggplot2')) install.packages('ggplot2'); library('ggplot2')
if(!require('Rmisc')) install.packages('Rmisc'); library('Rmisc')
if(!require('dplyr')) install.packages('dplyr'); library('dplyr')
if(!require('xfun')) install.packages('xfun'); library('xfun')
summary(accidentData[c("FATALS","DRUNK_DR")])
## FATALS DRUNK_DR
## Min. :1.000 Min. :0.0000
## 1st Qu.:1.000 1st Qu.:0.0000
## Median :1.000 Median :0.0000
## Mean :1.085 Mean :0.2664
## 3rd Qu.:1.000 3rd Qu.:1.0000
## Max. :8.000 Max. :4.0000
histList<- list()
n = c("FATALS","DRUNK_DR")
accidentDataAux= accidentData %>% select(all_of(n))
for(y in 1:ncol(accidentDataAux)){
col <- names(accidentDataAux)[y]
ggp <- ggplot(accidentDataAux, aes_string(x = col)) +
geom_histogram(bins = 30, fill = "cornflowerblue", color = "black",ggtittle = "Contador de ocurrencias por variable")
histList[[y]] <- ggp # añadimos cada plot a la lista vacía
}
multiplot(plotlist = histList, coles = 1)
## [1] 1
Observaciones:
Número de muertes: Todos los accidentes recogidos en estos datos reportan una muerte como mínimo. Siendo el accidente más grave con ocho víctimas y vemos que la distribución se acumula de forma muy evidente en una muerte por accidente.
Conductores bebidos involucrados en el accidente: Analizaremos con más detalle este dato más adelante para derivar un nuevo dato: Accidentes donde el alcohol está presente o no. De entrada, la media es de 0.26% de accidentes donde interviene un conductor bebido. La franja de conductores bebidos por accidente va de un conductor como mínimo a cuatro como máximo.
summary(accidentData[c("VE_TOTAL","VE_FORMS","PVH_INVL")])
## VE_TOTAL VE_FORMS PVH_INVL
## Min. : 1.00 Min. : 1.000 Min. : 0.00000
## 1st Qu.: 1.00 1st Qu.: 1.000 1st Qu.: 0.00000
## Median : 1.00 Median : 1.000 Median : 0.00000
## Mean : 1.56 Mean : 1.517 Mean : 0.04269
## 3rd Qu.: 2.00 3rd Qu.: 2.000 3rd Qu.: 0.00000
## Max. :15.00 Max. :15.000 Max. :10.00000
#Crearemos una lista para mostrar los atributos que interesan.
histList<- list()
n = c("VE_TOTAL","VE_FORMS","PVH_INVL")
accidentDataAux= accidentData %>% select(all_of(n))
for(y in 1:ncol(accidentDataAux)){
col <- names(accidentDataAux)[y]
ggp <- ggplot(accidentDataAux, aes_string(x = col)) +
geom_histogram(bins = 30, fill = "cornflowerblue", color = "black")
histList[[y]] <- ggp # añadimos cada plot a la lista vacía
}
multiplot(plotlist = histList, coles = 1)
## [1] 1
Observaciones en cuanto a los vehículos implicados.
Número de vehículos implicados (VE_TOTAL) en total está en la franja de 1 hasta 59 siendo este el valor máximo y una media de 1.5. Número de vehículos en movimiento implicados (VE_FORMS), el valor más habitual es 1 con un valor máximo también de 59. Prevemos que hay un valor extremo que habrá que tratar para poder sacar más información de esta variable. Número de vehículos estacionados implicados (PVH_INVL): Por lo que respecta a esta variable lo habitual es que no haya vehículos estacionados en los incidentes recogidos en estos datos. Con todo aparecen casos aislados donde incluso había 10 coches estacionados.
summary(accidentData[c("PEDS","PERSONS","PERMVIT","PERNOTMVIT")])
## PEDS PERSONS PERMVIT PERNOTMVIT
## Min. :0.0000 Min. : 0.000 Min. : 0.000 Min. :0.0000
## 1st Qu.:0.0000 1st Qu.: 1.000 1st Qu.: 1.000 1st Qu.:0.0000
## Median :0.0000 Median : 2.000 Median : 2.000 Median :0.0000
## Mean :0.2285 Mean : 2.173 Mean : 2.163 Mean :0.2387
## 3rd Qu.:0.0000 3rd Qu.: 3.000 3rd Qu.: 3.000 3rd Qu.:0.0000
## Max. :8.0000 Max. :61.000 Max. :61.000 Max. :9.0000
#Crearemos una lista para mostrar los atributos que interesan.
histList<- list()
n = c("PEDS","PERSONS","PERMVIT","PERNOTMVIT")
accidentDataAux= accidentData %>% select(all_of(n))
for(y in 1:ncol(accidentDataAux)){
col <- names(accidentDataAux)[y]
ggp <- ggplot(accidentDataAux, aes_string(x = col)) +
geom_histogram(bins = 30, fill = "cornflowerblue", color = "black")
histList[[y]] <- ggp # añadimos cada plot a la lista vacía
}
multiplot(plotlist = histList, coles = 1)
## [1] 1
Observaciones en cuanto a las personas implicadas en un accidente.
El número de peatones implicados (PEDS) es muy bajo siendo coherente con el tipo de vía que se estudia y dónde no es habitual que haya gente andando. Con todo el valor como media de 0.22 y máximo de 8 obliga a investigar más este dato. (PERSONS) El número de ocupantes de vehículo implicados se sitúa como media en 2.1 (PERMVIT) El número conductores y ocupantes de vehículos en circulación implicados tiene un valor de media de 2.1. Estas dos variables recogen la misma información, pero la cuantifican de diferente manera. El accidente con el mayor número de ocupantes es de 61 personas. Por lo que respecta al número peatones, ciclistas, personas en vehículos aparcados y otros (PERNOTMVIT) vemos que aumenta un poco la media respecto a peatón puesto que entendemos que se incluyen más casos.
Vamos a profundizar un poco en el tema de la relación del alcohol en los conductores y el número de accidentes.
accidentData$alcohol <- ifelse(accidentData$DRUNK_DR %in% c(0), 0, 1)
counts <- table(accidentData$alcohol)
barplot(prop.table(counts),
col=c("green","red"),
main="Accidentes con conductor bebido",
xlab ="Presencia Alcohol",
ylab = "Porcentaje",
ylim=c(0,0.8),
names.arg = c("No Alcohol", "Sí Alcohol"))
legend("topright", legend = c("No Alcohol", "Sí Alcohol"), fill = c("green", "red"))
Vemos que porcentualmente, en la gran mayoría de accidentes, alrededor del 75% no hay presencia de alcohol en el conductor. Los conductores que dan positivo están alrededor de un 22%. Hemos buscado contrastar el dato con otros países y estarían en un valor central donde los valores extremos máximo por país superan el 50% y los mínimos están sobre el 10%
Observamos ahora como se distribuyen las muertes por accidente.
df1 <- accidentData %>%
group_by(accidentData$FATALS) %>%
dplyr::summarise(counts = n())
df1
## # A tibble: 8 × 2
## `accidentData$FATALS` counts
## <int> <int>
## 1 1 33226
## 2 2 2154
## 3 3 289
## 4 4 71
## 5 5 20
## 6 6 4
## 7 7 1
## 8 8 1
counts <- table(accidentData$FATALS)
barplot(prop.table(counts),
col=("red"),ylim=c(0,0.99),
main="Distribución de la mortalidad a los accidentes",
xlab ="Número de muertos",
ylab = "Porcentaje")
Vemos que la mayoría de los accidentes tienen como mínimo un muerto. Vamos ahora a relacionar mortalidad y alcohol.
counts <- table(accidentData$alcohol, accidentData$FATALS)
colors <- c("green", "red")
barplot(prop.table(counts),
beside = TRUE,
col = colors,
ylim = c(0, 1),
axes = TRUE,
xlab = "Número de muertos",
ylab = "Porcentaje",
main = "Accidentes por muertes y conductores positivos en alcohol")
legend("topright", legend = c("No Alcohol", "Alcohol"), col = colors, pch = 15)
Probaremos ahora si hay relación entre el estado donde ha pasado el accidente y el número de conductores bebidos. Filtramos los cinco estados donde hay más accidentes.
accidentDataST5=subset(accidentData, accidentData$STATENAME == "California" | accidentData$STATENAME == "Texas" | accidentData$STATENAME == "Florida" | accidentData$STATENAME == "Georgia" | accidentData$STATENAME == "North Carolina")
files=dim(accidentDataST5)[1]
ggplot(data=accidentDataST5[1:files,],aes(x=DRUNK_DR,fill=STATENAME))+geom_bar()+ggtitle("Relación entre conductor bebido y Estado")+labs(x="Número de conductores bebidos implicados")
Como reflexión este gráfico tiene que pasar por el filtro de percentuar el número de accidentes por estado y la población del estado para no sacar conclusiones apresuradas.
Veamos ahora como en un mismo gráfico de frecuencias podemos trabajar con 3 variables: FATALS, STATENAME y WEATHERNAME.
ggplot(data = accidentDataST5[1:files,],aes(x=FATALS,fill=STATENAME))+geom_bar(position="fill")+facet_wrap(~WEATHERNAME)+ggtitle("Número de muertes en accidente por Estado y clima")+labs(x="Número de muertes")
Esta gráfica está bien como mecánica de construcción, pero los resultados los ponemos en entredicho. Está bien como paso inicial, pero hay que profundizar mucho más.
Vamos a buscar las correlaciones en función de las muertes y unas variables elegidas que creemos que pueden ayudar a explicar el aumento de muertes por accidente:
DRUNK_DR conductores bebidos VE_TOTAL número de vehículos implicados en total VE_FORMS número de vehículos en movimiento implicados PVH_INVL número de vehículos estacionados implicados PEDS número de peatón implicados PERSONS número de ocupante de vehículo implicados PERMVIT número conductores y ocupantes implicados PERNOTMVIT número peatones, ciclistas… Cualquier cosa menos vehículo motorizado
# Utilizamos esta librería para usar la funcio multiplot()
if(!require('Rmisc')) install.packages('Rmisc'); library('Rmisc')
n = c("DRUNK_DR","VE_TOTAL","VE_FORMS","PVH_INVL","PEDS","PERSONS","PERMVIT","PERNOTMVIT")
accidentDataAux= accidentData %>% select(all_of(n))
histList2<- vector('list', ncol(accidentDataAux))
for(i in seq_along(accidentDataAux)){
message(i)
histList2[[i]]<-local({
i<-i
col <-log(accidentDataAux[[i]])
ggp<- ggplot(data = accidentDataAux, aes(x = accidentData$FATALS, y=col)) +
geom_point(color = "gray30") + geom_smooth(method = lm,color = "firebrick") +
theme_bw() + xlab("Muertes") + ylab(names(accidentDataAux)[i])
})
}
multiplot(plotlist = histList2, cols = 3)
Podemos ver que:
De forma general cualquier aumento en las variables elegidas implica un aumento de las muertes en el accidente.
El factor que hace aumentar más el número de víctimas son las variables relacionadas con los peatones y pasajeros de los coches involucrados en el accidente.
Utilizamos las columnas que nos interesa para hacer la matriz y la visualizaremos utilizando la función corrplot.
# https://cran.r-project.org/web/packages/corrplot/vignettes/corrplot-intro.html
if(!require("corrplot")) install.packages("corrplot"); library("corrplot")
n = c("FATALS","DRUNK_DR","VE_TOTAL","VE_FORMS","PVH_INVL","PEDS","PERSONS","PERMVIT","PERNOTMVIT")
factores= accidentData %>% select(all_of(n))
res<-cor(factores)
corrplot(res,method="color",tl.col="black", tl.srt=30, order = "AOE",
number.cex=0.75,sig.level = 0.01, addCoef.col = "black")
No vemos que haya una correlación negativa significativa entre dos variables y sí una muy buena correlación ya previsible entre los peatones implicados y personas involucradas en el accidente que no van en coche (PEDS y PERNOTMVIT) Lo mismo podemos observar en cuanto al número de conductores y ocupantes implicados (PERMVIT) y el número de vehículos implicados en movimiento (VE_FORMS) o el total de vehículos (VE_TOTAL).
Vamos a probar si hay una correlación entre personas implicadas en el accidente y el número de muertes.
if (!require("tidyverse")) {
install.packages("tidyverse")
library(tidyverse)
} else {
library(tidyverse)
}
## Cargando paquete requerido: tidyverse
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ lubridate 1.9.4 ✔ tibble 3.2.1
## ✔ purrr 1.0.4 ✔ tidyr 1.3.1
## ✔ readr 2.1.5
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::arrange() masks plyr::arrange()
## ✖ purrr::compact() masks plyr::compact()
## ✖ dplyr::count() masks plyr::count()
## ✖ dplyr::desc() masks plyr::desc()
## ✖ dplyr::failwith() masks plyr::failwith()
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::id() masks plyr::id()
## ✖ dplyr::lag() masks stats::lag()
## ✖ dplyr::mutate() masks plyr::mutate()
## ✖ dplyr::rename() masks plyr::rename()
## ✖ stringr::str_wrap() masks xfun::str_wrap()
## ✖ dplyr::summarise() masks plyr::summarise()
## ✖ dplyr::summarize() masks plyr::summarize()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
cor.test(x = accidentData$PERSONS, y = accidentData$FATALS, method = "kendall")
##
## Kendall's rank correlation tau
##
## data: accidentData$PERSONS and accidentData$FATALS
## z = 53.008, p-value < 2.2e-16
## alternative hypothesis: true tau is not equal to 0
## sample estimates:
## tau
## 0.2558174
ggplot(data = accidentData, aes(x = PERSONS, y = log(FATALS))) +
geom_point(color = "gray30") +
geom_smooth(color = "firebrick") +
theme_bw() +
ggtitle("Correlación entre personas implicadas en el accidente y número de muertes")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'
De la observación de este gráfico podemos concluir que efectivamente el número de muertes aumenta en función de las personas implicadas en un accidente pero que la correlación no es tan elevada ni continúa como se podía prever.
Si dos variables están altamente correlacionadas obviamente darán casi exactamente la misma información en un modelo de regresión, por ejemplo. Pero, al incluir las dos variables, en realidad estamos debilitando el modelo. No estamos añadiendo información incremental. En lugar de esto, estamos haciendo un modelo ruidoso. No es una buena idea.
Cómo hemos visto antes tenemos una correlación muy grande entre PEDS y PERNOTMVIT, por lo tanto, podríamos eliminar la columna de peatones (PEDS) y dejar el total de peatones y otros reflejado a PERNOTMVIT.
# accidentData$PEDS<- NULL
str(accidentData)
## 'data.frame': 35766 obs. of 82 variables:
## $ STATE : int 1 1 1 1 1 1 1 1 1 1 ...
## $ STATENAME : chr "Alabama" "Alabama" "Alabama" "Alabama" ...
## $ ST_CASE : int 10001 10002 10003 10004 10005 10006 10007 10008 10009 10010 ...
## $ VE_TOTAL : int 1 4 2 1 1 2 1 2 2 2 ...
## $ VE_FORMS : int 1 4 2 1 1 2 1 2 2 2 ...
## $ PVH_INVL : int 0 0 0 0 0 0 0 0 0 0 ...
## $ PEDS : int 0 0 0 0 0 0 1 0 0 0 ...
## $ PERSONS : int 4 6 2 5 1 3 1 2 4 3 ...
## $ PERMVIT : int 4 6 2 5 1 3 1 2 4 3 ...
## $ PERNOTMVIT : int 0 0 0 0 0 0 1 0 0 0 ...
## $ COUNTY : int 51 73 117 15 37 103 73 25 45 95 ...
## $ COUNTYNAME : chr "ELMORE (51)" "JEFFERSON (73)" "SHELBY (117)" "CALHOUN (15)" ...
## $ CITY : int 0 350 0 0 0 0 330 0 0 1500 ...
## $ CITYNAME : chr "NOT APPLICABLE" "BIRMINGHAM" "NOT APPLICABLE" "NOT APPLICABLE" ...
## $ DAY : int 1 2 2 3 4 4 7 8 9 10 ...
## $ DAYNAME : int 1 2 2 3 4 4 7 8 9 10 ...
## $ MONTH : int 1 1 1 1 1 1 1 1 1 1 ...
## $ MONTHNAME : chr "January" "January" "January" "January" ...
## $ YEAR : int 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 ...
## $ DAY_WEEK : int 4 5 5 6 7 7 3 4 5 6 ...
## $ DAY_WEEKNAME: chr "Wednesday" "Thursday" "Thursday" "Friday" ...
## $ HOUR : int 2 17 14 15 0 16 19 7 20 10 ...
## $ HOURNAME : chr "2:00am-2:59am" "5:00pm-5:59pm" "2:00pm-2:59pm" "3:00pm-3:59pm" ...
## $ MINUTE : int 58 18 55 20 45 55 23 15 0 2 ...
## $ MINUTENAME : chr "58" "18" "55" "20" ...
## $ NHS : int 0 0 0 0 0 0 0 0 0 1 ...
## $ NHSNAME : chr "This section IS NOT on the NHS" "This section IS NOT on the NHS" "This section IS NOT on the NHS" "This section IS NOT on the NHS" ...
## $ ROUTE : int 4 6 3 4 4 3 4 4 4 2 ...
## $ ROUTENAME : chr "County Road" "Local Street - Municipality" "State Highway" "County Road" ...
## $ TWAY_ID : chr "cr-4" "martin luther king jr dr" "sr-76" "CR-ALEXANDRIA WELLINGTON RD" ...
## $ TWAY_ID2 : chr "" "" "us-280" "" ...
## $ RUR_URB : int 1 2 1 1 1 1 2 1 1 1 ...
## $ RUR_URBNAME : chr "Rural" "Urban" "Rural" "Rural" ...
## $ FUNC_SYS : int 5 4 4 7 5 4 4 5 5 3 ...
## $ FUNC_SYSNAME: chr "Major Collector" "Minor Arterial" "Minor Arterial" "Local" ...
## $ RD_OWNER : int 2 4 1 2 2 1 4 2 2 1 ...
## $ RD_OWNERNAME: chr "County Highway Agency" "City or Municipal Highway Agency" "State Highway Agency" "County Highway Agency" ...
## $ MILEPT : int 0 0 49 0 0 390 0 0 0 3019 ...
## $ MILEPTNAME : chr "None" "None" "49" "None" ...
## $ LATITUDE : num 32.4 33.5 33.3 33.8 32.8 ...
## $ LATITUDENAME: chr "32.43313333" "33.48465833" "33.29994167" "33.79507222" ...
## $ LONGITUD : num -86.1 -86.8 -86.4 -85.9 -86.1 ...
## $ LONGITUDNAME: chr "-86.09485" "-86.83954444" "-86.36964167" "-85.88348611" ...
## $ SP_JUR : int 0 0 0 0 0 0 0 0 0 0 ...
## $ SP_JURNAME : chr "No Special Jurisdiction" "No Special Jurisdiction" "No Special Jurisdiction" "No Special Jurisdiction" ...
## $ HARM_EV : int 42 12 34 42 42 12 8 12 12 12 ...
## $ HARM_EVNAME : chr "Tree (Standing Only)" "Motor Vehicle In-Transport" "Ditch" "Tree (Standing Only)" ...
## $ MAN_COLL : int 0 6 0 0 0 2 0 1 1 2 ...
## $ MAN_COLLNAME: chr "The First Harmful Event was Not a Collision with a Motor Vehicle in Transport" "Angle" "The First Harmful Event was Not a Collision with a Motor Vehicle in Transport" "The First Harmful Event was Not a Collision with a Motor Vehicle in Transport" ...
## $ RELJCT1 : int 0 0 0 0 0 0 0 0 0 0 ...
## $ RELJCT1NAME : chr "No" "No" "No" "No" ...
## $ RELJCT2 : int 1 1 3 1 1 1 3 1 8 1 ...
## $ RELJCT2NAME : chr "Non-Junction" "Non-Junction" "Intersection-Related" "Non-Junction" ...
## $ TYP_INT : int 1 1 3 1 1 1 2 1 1 1 ...
## $ TYP_INTNAME : chr "Not an Intersection" "Not an Intersection" "T-Intersection" "Not an Intersection" ...
## $ WRK_ZONE : int 0 0 0 0 0 0 0 0 0 0 ...
## $ WRK_ZONENAME: chr "None" "None" "None" "None" ...
## $ REL_ROAD : int 4 1 4 4 4 1 1 1 1 1 ...
## $ REL_ROADNAME: chr "On Roadside" "On Roadway" "On Roadside" "On Roadside" ...
## $ LGT_COND : int 2 3 1 1 2 2 3 1 2 1 ...
## $ LGT_CONDNAME: chr "Dark - Not Lighted" "Dark - Lighted" "Daylight" "Daylight" ...
## $ WEATHER : int 1 2 2 10 2 1 1 1 10 10 ...
## $ WEATHERNAME : chr "Clear" "Rain" "Rain" "Cloudy" ...
## $ SCH_BUS : int 0 0 0 0 0 0 0 0 0 0 ...
## $ SCH_BUSNAME : chr "No" "No" "No" "No" ...
## $ RAIL : chr "0000000" "0000000" "0000000" "0000000" ...
## $ RAILNAME : chr "Not Applicable" "Not Applicable" "Not Applicable" "Not Applicable" ...
## $ NOT_HOUR : int 99 17 14 99 0 17 19 7 20 10 ...
## $ NOT_HOURNAME: chr "Unknown" "5:00pm-5:59pm" "2:00pm-2:59pm" "Unknown" ...
## $ NOT_MIN : int 99 18 58 99 45 0 23 21 0 3 ...
## $ NOT_MINNAME : chr "Unknown" "18" "58" "Unknown" ...
## $ ARR_HOUR : int 3 17 15 99 0 17 19 7 20 10 ...
## $ ARR_HOURNAME: chr "3:00am-3:59am" "5:00pm-5:59pm" "3:00pm-3:59pm" "Unknown EMS Scene Arrival Hour" ...
## $ ARR_MIN : int 10 26 15 99 55 19 29 28 10 7 ...
## $ ARR_MINNAME : chr "10" "26" "15" "Unknown EMS Scene Arrival Minutes" ...
## $ HOSP_HR : int 99 99 99 99 88 18 88 88 99 10 ...
## $ HOSP_HRNAME : chr "Unknown" "Unknown" "Unknown" "Unknown" ...
## $ HOSP_MN : int 99 99 99 99 88 51 88 88 99 29 ...
## $ HOSP_MNNAME : chr "Unknown EMS Hospital Arrival Time" "Unknown EMS Hospital Arrival Time" "Unknown EMS Hospital Arrival Time" "Unknown EMS Hospital Arrival Time" ...
## $ FATALS : int 3 1 1 1 1 1 1 1 1 1 ...
## $ DRUNK_DR : int 1 0 0 0 0 0 0 0 0 0 ...
## $ alcohol : num 1 0 0 0 0 0 0 0 0 0 ...
Seguidamente vayamos a asignar un 1 por accidentes que se producen de madrugada (01h a 06h en invierno) y un 0 para el resto de franja horaria, es decir, vamos a categorizar la variable HOUR y así tendremos una variable numérica que nos permitirá trabajar mejor en el futuro. La denominaremos madrugada. Después la utilizaremos para ver cómo se distribuyen los accidentes en las dos franjas horarias. Debemos tener en cuenta que la hora incluye el código 99 qué quiere decir que la hora no está informada. Miraremos de filtrar los registros con este valor para excluirlos.
accidentDataAux=subset(accidentData, accidentData$HOUR <= 24)
accidentData$madrugada <- NA
accidentData$madrugada[accidentDataAux$HOUR >=1 & accidentDataAux$HOUR <= 6] <- 1
accidentData$madrugada[accidentDataAux$HOUR ==0 | accidentDataAux$HOUR >6 ] <- 0
counts <- table(accidentData$madrugada)
barplot(prop.table(counts),
col=c("green","red"),
ylim=c(0,1),
main="Distribución de accidentes la madrugada y resto del día",
xlab="0 Resto del día 1 Madrugada",
ylab="Porcentaje" )
legend("topright", legend = c("Resto del día", "Madrugada"), fill = c("green", "red"))
Ahora añadiremos un campo nuevo a los datos. Este campo contendrá el valor de la hora del accidente discretizada con un método simple de intervalos de igual amplitud.
summary(accidentDataAux[,"HOUR"])
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.00 7.00 15.00 13.19 19.00 23.00
Discretizamos con intervalos. Los criterios de corte están cogidos de la Web del Parlamento de Cataluña.
accidentDataAux["segmento_horario"] <- cut(accidentDataAux$HOUR, breaks = c(0,4,11,14,18,22), labels = c("Madrugada", "Mañana", "Mediodía", "Anochecer","Noche"))
Observamos los datos discretizados y construimos un gráfico para analizar cómo se agrupan los accidentes.
head(accidentDataAux$segmento_horario)
## [1] Madrugada Anochecer Mediodía Anochecer <NA> Anochecer
## Levels: Madrugada Mañana Mediodía Anochecer Noche
plot(accidentDataAux$segmento_horario,main="Número de accidentes por segmento horario",xlab="Segmento horario", ylab="Cantidad",col = "ivory")
Ahora vamos a discretizar la variable que contiene el número de vehículos implicados en un accidente (VE_TOTALS) puesto que era una de las variables en que las distancias entre sus valores eran muy grandes:
# Utilizaremos la función discretize de arules: This function implements several basic unsupervised methods to convert a continuous variable into a categorical variable (factor) using different binning strategies.
# https://cran.r-project.org/web/packages/arules/index.html
if (!require('arules')) install.packages('arules'); library('arules')
## Cargando paquete requerido: arules
## Cargando paquete requerido: Matrix
##
## Adjuntando el paquete: 'Matrix'
## The following objects are masked from 'package:tidyr':
##
## expand, pack, unpack
##
## Adjuntando el paquete: 'arules'
## The following object is masked from 'package:dplyr':
##
## recode
## The following objects are masked from 'package:base':
##
## abbreviate, write
set.seed(2)
table(discretize(accidentData$VE_TOTAL, "cluster" ))
##
## [1,1.57) [1.57,3.38) [3.38,15]
## 19972 14972 822
hist(accidentData$VE_TOTAL, main="Número de accidentes por vehículos implicados con kmeans",xlab="Vehículos implicados", ylab="Cantidad",col = "ivory")
abline(v=discretize(accidentData$VE_TOTAL, method="cluster", onlycuts=TRUE),col="red")
Podemos observar que sin pasar ningún argumento y permitiendo que el algoritmo elija el conjunto de particiones se muestran tres clústeres que agrupan los vehículos implicados en las franjas mencionadas. Podemos asignar el propio clúster como una variable más al dataset para trabajar después.
accidentData$VE_TOTAL_KM<- (discretize(accidentData$VE_TOTAL, "cluster" ))
head(accidentData$VE_TOTAL_KM)
## [1] [1,1.5) [2.73,15] [1.5,2.73) [1,1.5) [1,1.5) [1.5,2.73)
## Levels: [1,1.5) [1.5,2.73) [2.73,15]
Ahora normalizaremos el número de muertes por el máximo añadiendo un nuevo campo a los datos que contendrá el valor.
accidentData$FATALS_NM<- (accidentData$FATALS/max(accidentData[,"FATALS"]))
head(accidentData$FATALS_NM)
## [1] 0.375 0.125 0.125 0.125 0.125 0.125
Supongamos que queremos normalizar por la diferencia para ubicar entre 0 y 1 la variable del número de muertes del accidente dado que el algoritmo de minería que utilizaremos así lo requiere. Observamos la distribución de la variable original y las generadas.
accidentData$FATALS_ND = (accidentData$FATALS-min(accidentData$FATALS))/(max(accidentData$FATALS)-min(accidentData$FATALS))
max(accidentData$FATALS)
## [1] 8
min(accidentData$FATALS)
## [1] 1
hist(accidentData$FATALS,xlab="Muertos", col="ivory",ylab="Cantidad", main="Número de muertes en accidente")
hist(accidentData$FATALS_NM,xlab="Muertos",ylab="Cantidad",col="ivory", main="Muertos normalizado por el máximo")
hist(accidentData$FATALS_ND,xlab="Muertos",ylab="Cantidad", col="ivory", main="Muertos normalizado por la diferencia")
A continuación, vamos a normalizar las otras columnas para asegurarnos que cada variable contribuye por igual en nuestro análisis.
# Definimos la función de normalización
nor <-function(x) { (x -min(x))/(max(x)-min(x))}
# Guardamos un nuevo dataset normalizado
accidentData$type<- NULL
n = c("FATALS","DRUNK_DR","VE_TOTAL","VE_FORMS","PVH_INVL","PEDS","PERSONS","PERMVIT","PERNOTMVIT")
accidentData<- accidentData %>% select(all_of(n))
accidentData_nor <- as.data.frame(lapply(accidentData, nor))
head(accidentData_nor)
## FATALS DRUNK_DR VE_TOTAL VE_FORMS PVH_INVL PEDS PERSONS PERMVIT
## 1 0.2857143 0.25 0.00000000 0.00000000 0 0 0.06557377 0.06557377
## 2 0.0000000 0.00 0.21428571 0.21428571 0 0 0.09836066 0.09836066
## 3 0.0000000 0.00 0.07142857 0.07142857 0 0 0.03278689 0.03278689
## 4 0.0000000 0.00 0.00000000 0.00000000 0 0 0.08196721 0.08196721
## 5 0.0000000 0.00 0.00000000 0.00000000 0 0 0.01639344 0.01639344
## 6 0.0000000 0.00 0.07142857 0.07142857 0 0 0.04918033 0.04918033
## PERNOTMVIT
## 1 0
## 2 0
## 3 0
## 4 0
## 5 0
## 6 0
Tanto el análisis de componentes principales, principal componente analysis (PCA) en inglés, como la descomposición de valores singulares, singular value decomposition (SVD) en inglés, son técnicas que nos permitan trabajar con nuevas características llamadas componentes, que ciertamente son independientes entre sí. En realidad, estas dos técnicas nos permiten representar el juego de datos en un nuevo sistema de coordenadas que denominamos componentes principales. Este sistema está mejor adaptado a la distribución del juego de datos, de forma que recoge mejor su variabilidad.
Aplicamos el análisis de componentes principales al dataset. Empezamos ejecutando la función prcomp().
pca.acc <- prcomp(accidentData_nor)
summary(pca.acc)
## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6 PC7
## Standard deviation 0.1168 0.08755 0.0690 0.0484 0.03269 0.02437 0.01072
## Proportion of Variance 0.4520 0.25389 0.1577 0.0776 0.03539 0.01967 0.00381
## Cumulative Proportion 0.4520 0.70584 0.8635 0.9411 0.97652 0.99619 1.00000
## PC8 PC9
## Standard deviation 1.143e-14 2.491e-15
## Proportion of Variance 0.000e+00 0.000e+00
## Cumulative Proportion 1.000e+00 1.000e+00
Como se puede observar la función summary, nos devuelve la proporción de varianza aplicada al conjunto total de cada atributo. Gracias a esto, el atributo 1 explica el 0.452 de variabilidad del total de datos; en cambio, el atributo 7 explica solo el 0.000381.
A continuación, se muestra un histograma para ver el peso de cada atributo sobre el conjunto total de datos:
if (!require('factoextra')) install.packages('factoextra'); library('factoextra')
## Cargando paquete requerido: factoextra
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
#Los valores propios corresponden a la cantidad de variación explicada por cada componente principal (PC).
ev= get_eig(pca.acc)
ev
## eigenvalue variance.percent cumulative.variance.percent
## Dim.1 1.364366e-02 4.519469e+01 45.19469
## Dim.2 7.664656e-03 2.538921e+01 70.58391
## Dim.3 4.760727e-03 1.576993e+01 86.35384
## Dim.4 2.342530e-03 7.759642e+00 94.11348
## Dim.5 1.068327e-03 3.538839e+00 97.65232
## Dim.6 5.937915e-04 1.966938e+00 99.61926
## Dim.7 1.149407e-04 3.807416e-01 100.00000
## Dim.8 1.305543e-28 4.324617e-25 100.00000
## Dim.9 6.203717e-30 2.054984e-26 100.00000
fviz_eig(pca.acc)
En este ejercicio se decidió utilizar el método de Káiser para decidir cuales de las variables obtenidas serán escogidas. Este criterio mantendrá todas aquellas variables cuya varianza sea superior a 1.
# Calculamos la varianza de los componentes principales a partir de la desviación estándar
var_acc <- pca.acc$sdev^2
var_acc
## [1] 1.364366e-02 7.664656e-03 4.760727e-03 2.342530e-03 1.068327e-03
## [6] 5.937915e-04 1.149407e-04 1.305543e-28 6.203717e-30
Con los resultados obtenidos es muy complicado decidir cuáles son los componentes principales componentes a escoger. Este hecho podría estar causado por no haber escalado los datos previamente. Por lo tanto, el siguiente paso es escalar los datos y volver a calcular la varianza para ver qué datos selecciona.
# Escalamos los datos
acc_scale <- scale(accidentData_nor)
# Calculamos las componentes principales
pca.acc_scale <- prcomp(acc_scale)
# Mostramos la varianza de dichas variables:
var_acc_scale <- pca.acc_scale$sdev^2
head(var_acc_scale)
## [1] 3.5632826 1.8581532 1.1186798 1.0185157 0.8423082 0.5603141
Después de analizar la varianza y aplicando el criterio de Káiser nos quedaremos con los componentes principales 1,2,3 y 4 que son los superiores a 1. Este criterio tiene el problema de sobreestimar el número de factores, pero a pesar de ello es el que aplicaremos para analizar los resultados.
Mostramos el histograma de porcentaje de varianza explicado con los datos escalados:
fviz_eig(pca.acc_scale)
ev = get_eig(pca.acc_scale)
ev
## eigenvalue variance.percent cumulative.variance.percent
## Dim.1 3.563283e+00 3.959203e+01 39.59203
## Dim.2 1.858153e+00 2.064615e+01 60.23817
## Dim.3 1.118680e+00 1.242978e+01 72.66795
## Dim.4 1.018516e+00 1.131684e+01 83.98479
## Dim.5 8.423082e-01 9.358980e+00 93.34377
## Dim.6 5.603141e-01 6.225712e+00 99.56948
## Dim.7 3.874645e-02 4.305161e-01 100.00000
## Dim.8 3.781577e-26 4.201752e-25 100.00000
## Dim.9 2.016132e-26 2.240146e-25 100.00000
Los valores propios se pueden utilizar para determinar el número de componentes principales a retener después de la PCA (Kaiser 1961):
Un valor propio > 1 indica que los PCs representan más varianza de la que representa una de las variables originales de los datos estandarizados. Esto se utiliza habitualmente como punto de corte para el cual se conservan los PCs. Esto solo es cierto cuando los datos están estandarizados.
También podemos limitar el número de componentes a este número que representa una determinada fracción de la varianza total. Por ejemplo, si estamos satisfecho con el 80% de la varianza total explicada, usamos el número de componentes para conseguirlo que son los 4 componentes principales vistos antes.
Continuamos con el análisis de los componentes principales. Después de aplicar el método Káiser se han seleccionado los 4 componentes principales.
var <- get_pca_var(pca.acc_scale)
var
## Principal Component Analysis Results for variables
## ===================================================
## Name Description
## 1 "$coord" "Coordinates for the variables"
## 2 "$cor" "Correlations between variables and dimensions"
## 3 "$cos2" "Cos2 for the variables"
## 4 "$contrib" "contributions of the variables"
Los componentes de get_pca_var() se pueden utilizar en el diagrama de variables de la siguiente manera:
#Utilizamos los 4 componentes principales encontrados antes
head(var$coord[,1:4],11)
## Dim.1 Dim.2 Dim.3 Dim.4
## FATALS -0.30725642 0.07606945 0.28817514 -0.73967833
## DRUNK_DR -0.04921565 -0.38170799 -0.26454706 -0.58497489
## VE_TOTAL -0.83708697 0.28706095 -0.34390477 0.13727724
## VE_FORMS -0.86483356 0.18416941 -0.02398033 0.21866655
## PVH_INVL -0.06062570 0.30358100 -0.85844575 -0.18336810
## PEDS 0.48249027 0.82661079 0.13673775 -0.08353380
## PERSONS -0.88514448 0.21755791 0.19732665 -0.07582156
## PERMVIT -0.88736748 0.19749105 0.22352113 -0.06716534
## PERNOTMVIT 0.45872440 0.85355861 0.04773257 -0.10804664
La calidad de representación de las variables en el mapa de factores se denomina cos2 (coseno cuadrado, coordenadas cuadradas). Podemos acceder al cos2 de la siguiente manera:
head(var$cos2[,1:4],11)
## Dim.1 Dim.2 Dim.3 Dim.4
## FATALS 0.094406509 0.005786562 0.083044911 0.547124037
## DRUNK_DR 0.002422180 0.145700988 0.069985146 0.342195618
## VE_TOTAL 0.700714591 0.082403990 0.118270488 0.018845040
## VE_FORMS 0.747937080 0.033918370 0.000575056 0.047815060
## PVH_INVL 0.003675475 0.092161422 0.736929104 0.033623861
## PEDS 0.232796860 0.683285394 0.018697211 0.006977896
## PERSONS 0.783480750 0.047331446 0.038937806 0.005748910
## PERMVIT 0.787421038 0.039002717 0.049961697 0.004511183
## PERNOTMVIT 0.210428078 0.728562294 0.002278398 0.011674076
corrplot(var$cos2[,1:4], is.corr=FALSE)
También es posible crear un diagrama de barras de variables cos2 mediante la función fviz_cos2():
fviz_cos2(pca.acc_scale, choice = "var", axes = 1:2)
Un cos2 elevado indica una buena representación de la variable en el componente principal. En este caso, la variable se coloca cerca de la circunferencia del círculo de correlación.
Un cos2 bajo indica que la variable no está perfectamente representada por los PC. En este caso, la variable está cerca del centro del círculo.
Para una variable dada, la suma del cos2 de todos los componentes principales es igual a uno.
Si una variable está perfectamente representada por solo dos componentes principales (Dim.1 y Dim.2), la suma del cos2 en estos dos PCs es igual a uno. En este caso las variables se colocarán en el círculo de correlaciones.
Para algunas de las variables, pueden ser necesarios más de 2 componentes para representar perfectamente los datos. En este caso las variables se sitúan dentro del círculo de correlaciones.
En resumen:
fviz_pca_var(pca.acc_scale,
col.var = "cos2",
gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
repel = TRUE
)
Las contribuciones de las variables en la contabilización de la variabilidad de un determinado componente principal se expresan en porcentaje.
Las variables que están correlacionadas con PC1 (es decir, Dim.1) y PC2 (es decir, Dim.2) son las más importantes para explicar la variabilidad en el conjunto de datos.
Las variables que no están correlacionadas con ningún PC o con las últimas dimensiones son variables con una contribución baja y se pueden eliminar para simplificar el análisis global.
La contribución de las variables se puede extraer de la siguiente manera:
head(var$contrib[,1:4],11)
## Dim.1 Dim.2 Dim.3 Dim.4
## FATALS 2.64942527 0.3114147 7.42347448 53.7177824
## DRUNK_DR 0.06797608 7.8411720 6.25604798 33.5974816
## VE_TOTAL 19.66486180 4.4347254 10.57232696 1.8502454
## VE_FORMS 20.99011424 1.8253807 0.05140488 4.6945826
## PVH_INVL 0.10314857 4.9598398 65.87489045 3.3012610
## PEDS 6.53321358 36.7722855 1.67136397 0.6851044
## PERSONS 21.98761218 2.5472306 3.48069265 0.5644400
## PERMVIT 22.09819245 2.0990044 4.46613018 0.4429174
## PERNOTMVIT 5.90545583 39.2089469 0.20366845 1.1461852
Cuando más grande sea el valor de la contribución, más contribución habrá al componente.
corrplot(var$contrib[,1:4], is.cor=FALSE)
Las variables más importantes (que más contribuyen) se pueden resaltar a la gráfica de correlación de la siguiente manera:
fviz_pca_var(pca.acc_scale, col.var = "contrib",
gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07")
)
Las variables correlacionadas positivas apuntan al mismo lado de la trama. Las variables correlacionadas negativas apuntan a lados opuestos del gráfico. Por ejemplo, vemos que las personas involucradas en un accidente (PVH_INVL) y conductor bebido (DRUNK_DR) apuntan direcciones opuestas por tanto no están nada correlacionas, además lo hemos visto antes puesto que tienen un coeficiente de correlación de -0.01.
Se observa que las variables que más aportan a las componentes principales son PEDS y PERNOTMVIT por un lado y VE_TOTAL, VE_FORMS, PERSONS y PERMVIT por otro. Esto es debido al hecho que están correlacionadas. En concreto por el diagrama de correlación de antes de que PEDS está muy bien correlacionada con PERNOTMVIT. De otra banda VE_TOTAL, VE_FORMS, PERSONS y PERMVIT están también bastante correlacionadas. La correlación de FATALS con este grupo de variables no es elevada, pero apunta en la misma dirección.
Podrían ahora rehacer los componentes excluyendo las variables que no aportan información. Una vez rehechas estas nuevas variables sustituyen a las originales que las forman y se podrían utilizar por ejemplo como un indicador de gravedad de accidente puesto que incluye vehículo en movimiento, parado, peatones, conductores y otros implicados en una sola variable.
Los datos estudiados contemplan accidentes de tráfico con víctimas en las redes de autopistas en los EUUU a largo del 2020. Todos los registros tienen un identificador único de accidente y una serie de hechos principales como número de muertos, número de conductores bebidos, vehículos y personas implicadas. Tenemos que añadir otras variables que los caracterizan agrupadas por ubicación geográfica, temporal, condiciones específicas del accidente, meteorológicas, la intervención del servicio de emergencias y otros factores.
Revisados los datos parecen bien informados. Los datos están bastante limpios y bien documentados. No plantean graves problemas de campos con valores nulos o vacíos y tienen bastante potencial para generar nuevos indicadores a partir de los datos.
Podemos afirmar que a lo largo del 2020 en las autopistas de EE. UU. sucedieron 35766 accidentes en los que perdieron la vida 38824 personas. Pretendiamos extraer relaciones entre la presencia de alcohol en los conductores y el número de accidentes, pero las conclusiones no fueron claras. Las relaciones más obvias comprobadas son el incremento de muertes en función del incremento del número de vehículos, pasajeros y peatones implicados.
Habría que profundizar mucho más. Sí que podemos perfilar cómo son los accidentes típicos en cuanto al número de vehículos y personas, conductores o peatones implicados.
El más habitual es un muerto por accidente incrementándose este valor en función de las variables relacionadas. Los conductores bebidos aparecen en uno de cada cuatro accidentes mortales aproximadamente. Los vehículos implicados en los accidentes son típicamente uno pudiéndose incrementar a dos en los casos más típicos. El número de peatones implicados es relativamente bajo dado el tipo de vía que estamos estudiando.
En cuanto al consumo de alcohol, con el grado de profundidad estudiado, no se observa un estado donde las proporcionalidades del número de conductor con presencia de alcohol sean superiores a otros estados.
Estudiando el número de muertes en accidente en relación con el estado donde ha sucedido y la condición climática, vemos necesario profundizar con técnicas por ejemplo de agregación para ver cómo se agrupan y poder obtener un perfil.
Se ha estudiado la franja horaria de la madrugada para ver si acumula un mayor número de accidentes, no siendo así. Parece que el número de accidentes mantiene también proporcionalidad respecto las franjas horarias. Se ha estudiado el número de accidentes por segmento horario con una discretización fijada en intervalo arbitrarios. La mayor presencia de accidentes en horario por la mañana y anochecer (ir y volver al trabajo) hace pensar en que queda pendiente estudiar dado el tipo de vía la distribución horaria de los accidentes lunes a viernes respecto a los fines de semana y festivos para ver si hay horas donde se acumulan más accidentes mortales.
Finalmente, con la técnica de los componentes principales hemos generado una nueva variable que combina otras variables con una correlación inicial que se podría considerar como índice de gravedad del accidente.
A partir de un juego de datos que te parezca interesante, propón un proyecto completo de minería de datos. La organización de la respuesta tiene que coincidir en las fases típicas del ciclo de vida de un proyecto de minería de datos.
No hay que realizar las tareas de la fase, este es un ejercicio teórico.
Se espera por lo tanto que se responda de forma argumentada a las siguientes preguntas (Metodología CRISP-DM):
Para cada fase indica cuál es el objetivo de la fase y el producto que se obtendrá. Utiliza ejemplos de qué y cómo podrían ser las tareas. Si hay alguna característica que hace diferente el ciclo de vida de un proyecto de minería respecto a otros proyectos indícalo.
Extensión mínima: 400 palabras
El objetivo del negocio es reducir la siniestralidad vial mediante el entendimiento profundo de las principales causas que provocan los accidentes de tráfico mortales. Este conocimiento resulta crucial para que autoridades viales, organismos de seguridad pública y compañías aseguradoras puedan diseñar medidas preventivas más eficaces, optimizar campañas de concienciación y focalizar recursos en puntos críticos.
Para ello, se propone desarrollar un modelo de clasificación capaz de identificar la causa probable más probable de cada accidente a partir de datos históricos recogidos en el archivo accident.csv (año 2020). Las causas se agrupan en cuatro grandes categorías: error humano, condiciones climáticas y factores externos (infraestructura, obras, entorno, vehículo).
El éxito del proyecto se medirá por la precisión del modelo predictivo, su interpretabilidad y su utilidad para apoyar la toma de decisiones estratégicas en seguridad vial.
El resultado será un documento detallado que describirá los objetivos del proyecto desde una perspectiva de negocio.
El conjunto de datos contiene 35.766 registros de accidentes mortales en EEUU, con 81 variables categóricas y numéricas que describen aspectos del contexto geográfico, temporal, climático y estructural del siniestro.
Las variables de interés seleccionadas para el modelado de clasificación para identificar la causa del sinientro en Error humano o Factores externos, en un principio son:
Los datos están bien documentados y no contienen valores nulos o vacíos que sean críticos. Aunque la variables TWAY_ID2 tienen valores ausentes, éstas no afectan directamente al nuestro análisis, lo que asegura la calidad de los datos.
El producto final será un informe exploratorio de los datos donde se incluirá descripción de las variables, estadísticas descriptivas y visualizaciones, detección de valores inconsistentes y por último la identificación de posible variables significativas para nuestro objetivo.
Esta fase tiene como objetivo preparar un conjunto de datos para ser modelado. Esta fase es crítica en el ciclo de vida del proyecto, ya que implica convertir datos brutos de accidentes en una forma estructurada, limpia y adecuada para alimentar modelos de clasificación.
Tareas principales que se llevarán a cabo: - Selección de variables significativas para el modelo, directamente relacionadas co n la posibles causas de los accidentes mortales de acuerdo con la categorización mencionada. - Limpieza de registros con incosistencias relevantes. - Creación de variables auxiliares: Se construirá las variables ERR_HUMAN y EXT_FACTORS mediante lógica condicional (case_when() en R) a partir de las variables observadas. - Codificación de las variables categóricas como factores para modelos de aprendezaje supervisado. - Normalización de variables numéricas como PERSONS o VE_TOTAL, se evaluará la normalización si se aplican algoritmos sensibles a escala. - División del conjunto de datos de entrenamiento del 80% y de prueba del 20%, asegurando una distribución proporcional por categoría para evitar sesgo en clases minoritarias.
El producto final de esta fase será Un dataset estructurado y preparado con la variable objetivo bien definida, listo para alimentar distintos modelos de clasificación.
El objetrivo de la fase de modelado es construir uno o varios modelos de clasificación capaces de predecir la causa probable de un accidente mortal a partir de los datos preparados.
Las principales tareas son:
Selección de técnicas ded modelado. Se aplicarán distintos enfoques para su comparación: - Árboles de decisión (rpart): Fácilmente interpretable que permite generar reglas lógicas comprensibles por decisores. - Random Forest: Mejora la precisión y mitiga problemas de sobreajuste. - Regresión logística multinomial: Interpreta estadísticamente el peso de cada variable predictiva.
Diseño y pruebas de validación: Se aplicarñá la validación cruzada (5-fold) para la evaluar la consistencia del modelo y evitar sobreajuste. También se aplicará matices de confusión para el modelo.
Entrenamiento del modelo: Se ajustarán los modelos seleccionados con el conjunto de entrenamiento.
Se analizarán las variables más relevantes mediante medidas de importancia en Random Forest o coeficientes en regresión logística.
El producto final de esta fase serán los modelos de clasificación entrenados, validos y listos para su evaluación final.
En esta fase se ddeterminará si los modelos construidos cumplen con los objetivos de negocio y se escogerá la mejor solución.
El modelo seleccionado se evaluará en base a: 1.Evaluación del modelo según las métricas sigueintes: - Precisión global - Recall por clase - F1-score - Matriz de confusión Estas métricas permitirán identificar si el modelo clasifica correctamente las distintas causas de accidentes mortales. 2. Evaluación por contexto geográfico: El modelo se testeará también en distintos escenarios (urbano, rural, autopista) usando la variable FUNC_SYSNAME o ROUTENAME 3. Evaluación del proceso: Se revisarán las decisiones tomadas en cada fase para verificar si se cumplió con la lógica del problema, los criterios de calidad y los objetivos del cliente. 4. Selección del modelo que mejor explique la información que deseamos obtener.
El producto final de esta fase será la entrega a negocio del modelo seleccionado y justificado según las evaluaciones y evidencias técnicas.
Los resultados del proyecto se desplegará a través de los siguientes archivos que contendrán todo el flujo de trabajo, desde la carga, selección de los datos relevantes, preprocesammiento que incluye limpieza y tratammiento de los datos, transformación, mineria de datos y su interpretación: - Archivo .Rmd - Informe generado con RMarkdown en formato HTML del archivo Rmd.
Se planteará un sistema de mantenimiento que permita actualizar el modelo con nuevos datos. Esto permitirá la mejora continua, actualización de los datos y adaptación a posibles cambios en los patrones de accidentes.
A partir del juego de datos utilizado en el ejemplo de la PEC, realiza las tareas previas a la generación de un modelo de minería de datos explicadas en los módulos “El proceso de minería de datos” y “Preprocesado de los datos y gestión de características”.
Puedes utilizar de referencia el ejemplo de la PEC, pero procura cambiar el enfoque y analizar los datos en función de las diferentes dimensiones que presentan los datos. Así, no se puede utilizar la combinación de variables utilizada en el ejemplo: “FATALS”,“DRUNK_DR”,“VE_TOTAL”,“VE_FORMS”,“PVH_INVL”,“PEDS”,“PERSONS”,“PERMVIT”,“PERNOTMVIT”. Se debe analizar cualquier otra combinación que puede incluir (o no) algunas de estas variables con otras nuevas.
Opcionalmente y valorable se pueden añadir al estudio datos de otros años para realizar comparaciones temporales (https://www.nhtsa.gov/file-downloads?p=nhtsa/downloads/FARS/) o añadir otros hechos a estudiar relacionados, por ejemplo, el consumo de drogas en los accidentes (https://static.nhtsa.gov/nhtsa/downloads/FARS/2020/National/FARS2020NationalCSV.zip)
# Limpiar el entorno
rm(list = ls())
Datos públicos extraídos de un opendata National Highway Traffic Safety Administration donde se recopilan informes enfocados al análisis de mortalidad en las carreteras. Estos datos pertenecen a los años 2018, 2019 y 2020. Nos muesta información sobre la casuística de accidentes mortales ocurridos. El objetivo de nuestro estudio se fundamenta en clasificar el siniestro a dos posibles causas: + Error Humano + Factores Externos (infraestructuras, condiciones climáticas, mala señalización, fallo vehículo) Para más infornación sobre el conjunto de los datos, podéis visitar https://www.nhtsa.gov/crash-data-systems/fatality-analysis-reporting-system
Primera aproximación al conjunto de datos para identificar variables relevantes, dimensión del dataset, tipología de los datos, la distribución de las varibles, agregar datos de los diferentes archivos csv y extraer información básica del comportamiento de las variables.
Cargamos los datos y agregamos las variables de drugs.csv a cada uno de los archivos accident.csv correspondientes a cada año de estudio 2018, 2029 y 2020.
Verificamos que las observaciones y dimensiones de los diferentes datasets coinciden.
# Cargamos el juego de datos Drugs.csv del año 2018, 2019 y 2020
path2018 = 'Drugs2018.CSV'
path2019 = 'Drugs2019.CSV'
path2020 = 'Drugs2020.CSV'
drugs2018 <- read.csv(path2018, row.names = NULL)
drugs2019 <- read.csv(path2019, row.names = NULL)
drugs2020 <- read.csv(path2020, row.names = NULL)
# Tamaño del dataset drugs2018
dim(drugs2018)
## [1] 99097 9
# Tamaño del dataset drugs2019
dim(drugs2019)
## [1] 98899 9
# Tamaño del dataset drugs2020
dim(drugs2020)
## [1] 107141 9
file2018 = 'accident2018.CSV'
file2019 = 'accident2019.CSV'
file2020 = 'accident2020.CSV'
# Cargamos el juego de datos accident.csv del año 2018, 2019 y 2020
accident2018 <- read.csv(file2018, row.names = NULL)
accident2019 <- read.csv(file2019, row.names = NULL)
accident2020 <- read.csv(file2020, row.names = NULL)
# Tamaño del dataset accidents2018
dim(accident2018)
## [1] 33919 91
# Tamaño del dataset accidents2019
dim(accident2019)
## [1] 33487 91
# Tamaño del dataset accidents2020
dim(accident2020)
## [1] 35766 81
# Unimos ambos datasets drugs.csv y accident.csv por la columna ST_CASE
merged2018 <- merge(accident2018, drugs2018, by = "ST_CASE", all = FALSE)
merged2019 <- merge(accident2019, drugs2019, by = "ST_CASE", all = FALSE)
merged2020 <- merge(accident2020, drugs2020, by = "ST_CASE", all = FALSE)
# Dimensiones
dim(merged2018)
## [1] 99097 99
dim(merged2019)
## [1] 98899 99
dim(merged2020)
## [1] 106397 89
# Columnas comunes entre los tres datasets
common_cols <- Reduce(intersect, list(
colnames(merged2018),
colnames(merged2019),
colnames(merged2020)
))
# Filtramos los tres datasets para conservar solo las columnas comunes
merged2018 <- merged2018[, common_cols]
merged2019 <- merged2019[, common_cols]
merged2020 <- merged2020[, common_cols]
# Unir los datasets en uno solo
accident3Y <- rbind(merged2018, merged2019, merged2020)
# Eliminamos duplicados
accident3Y <- accident3Y %>%
select(-STATENAME.y)
accident3Y <- accident3Y %>%
select(-STATE.y)
# Renombramos la varible
accident3Y <- accident3Y %>%
rename(STATENAME = STATENAME.x)
accident3Y <- accident3Y %>%
rename(STATE = STATE.x)
dim(accident3Y)
## [1] 304393 87
# Primeros registros
head(accident3Y)
## ST_CASE STATE STATENAME VE_TOTAL VE_FORMS PVH_INVL PEDS PERSONS PERMVIT
## 1 10001 1 Alabama 2 1 1 0 1 1
## 2 10002 1 Alabama 1 1 0 0 2 2
## 3 10002 1 Alabama 1 1 0 0 2 2
## 4 10003 1 Alabama 2 2 0 0 2 2
## 5 10003 1 Alabama 2 2 0 0 2 2
## 6 10003 1 Alabama 2 2 0 0 2 2
## PERNOTMVIT COUNTY COUNTYNAME CITY CITYNAME DAY DAYNAME MONTH
## 1 0 121 TALLADEGA (121) 1870 LINCOLN 5 5 1
## 2 0 127 WALKER (127) 1780 JASPER 8 8 1
## 3 0 127 WALKER (127) 1780 JASPER 8 8 1
## 4 0 21 CHILTON (21) 0 NOT APPLICABLE 8 8 1
## 5 0 21 CHILTON (21) 0 NOT APPLICABLE 8 8 1
## 6 0 21 CHILTON (21) 0 NOT APPLICABLE 8 8 1
## MONTHNAME YEAR DAY_WEEK DAY_WEEKNAME HOUR HOURNAME MINUTE MINUTENAME
## 1 January 2018 6 Friday 6 6:00am-6:59am 0 0
## 2 January 2018 2 Monday 0 0:00am-0:59am 48 48
## 3 January 2018 2 Monday 0 0:00am-0:59am 48 48
## 4 January 2018 2 Monday 22 10:00pm-10:59pm 50 50
## 5 January 2018 2 Monday 22 10:00pm-10:59pm 50 50
## 6 January 2018 2 Monday 22 10:00pm-10:59pm 50 50
## NHS NHSNAME ROUTE ROUTENAME TWAY_ID TWAY_ID2 RUR_URB
## 1 1 This section IS ON the NHS 1 Interstate I-20 1
## 2 1 This section IS ON the NHS 1 Interstate I-22 CALUMET RD 2
## 3 1 This section IS ON the NHS 1 Interstate I-22 CALUMET RD 2
## 4 1 This section IS ON the NHS 1 Interstate I-65 1
## 5 1 This section IS ON the NHS 1 Interstate I-65 1
## 6 1 This section IS ON the NHS 1 Interstate I-65 1
## RUR_URBNAME FUNC_SYS FUNC_SYSNAME RD_OWNER RD_OWNERNAME MILEPT
## 1 Rural 1 Interstate 1 State Highway Agency 1676
## 2 Urban 1 Interstate 1 State Highway Agency 1621
## 3 Urban 1 Interstate 1 State Highway Agency 1621
## 4 Rural 1 Interstate 1 State Highway Agency 2028
## 5 Rural 1 Interstate 1 State Highway Agency 2028
## 6 Rural 1 Interstate 1 State Highway Agency 2028
## MILEPTNAME LATITUDE LATITUDENAME LONGITUD LONGITUDNAME SP_JUR
## 1 1676 33.59133 33.59133056 -86.13187 -86.13186944 0
## 2 1621 33.80919 33.80918611 -87.28985 -87.28984722 0
## 3 1621 33.80919 33.80918611 -87.28985 -87.28984722 0
## 4 2028 32.76774 32.76773611 -86.56404 -86.56403611 0
## 5 2028 32.76774 32.76773611 -86.56404 -86.56403611 0
## 6 2028 32.76774 32.76773611 -86.56404 -86.56403611 0
## SP_JURNAME HARM_EV HARM_EVNAME MAN_COLL
## 1 No Special Jurisdiction 14 Parked Motor Vehicle 0
## 2 No Special Jurisdiction 38 Fence 0
## 3 No Special Jurisdiction 38 Fence 0
## 4 No Special Jurisdiction 24 Guardrail Face 0
## 5 No Special Jurisdiction 24 Guardrail Face 0
## 6 No Special Jurisdiction 24 Guardrail Face 0
## MAN_COLLNAME RELJCT1 RELJCT1NAME RELJCT2
## 1 Not a Collision with Motor Vehicle In-Transport 0 No 1
## 2 Not a Collision with Motor Vehicle In-Transport 1 Yes 19
## 3 Not a Collision with Motor Vehicle In-Transport 1 Yes 19
## 4 Not a Collision with Motor Vehicle In-Transport 0 No 1
## 5 Not a Collision with Motor Vehicle In-Transport 0 No 1
## 6 Not a Collision with Motor Vehicle In-Transport 0 No 1
## RELJCT2NAME TYP_INT TYP_INTNAME WRK_ZONE
## 1 Non-Junction 1 Not an Intersection 0
## 2 Other location within Interchange Area 1 Not an Intersection 0
## 3 Other location within Interchange Area 1 Not an Intersection 0
## 4 Non-Junction 1 Not an Intersection 1
## 5 Non-Junction 1 Not an Intersection 1
## 6 Non-Junction 1 Not an Intersection 1
## WRK_ZONENAME REL_ROAD REL_ROADNAME LGT_COND LGT_CONDNAME WEATHER
## 1 None 2 On Shoulder 4 Dawn 1
## 2 None 3 On Median 2 Dark - Not Lighted 2
## 3 None 3 On Median 2 Dark - Not Lighted 2
## 4 Construction 4 On Roadside 2 Dark - Not Lighted 10
## 5 Construction 4 On Roadside 2 Dark - Not Lighted 10
## 6 Construction 4 On Roadside 2 Dark - Not Lighted 10
## WEATHERNAME SCH_BUS SCH_BUSNAME RAIL RAILNAME NOT_HOUR NOT_HOURNAME
## 1 Clear 0 No 0000000 Not Applicable 6 6:00am-6:59am
## 2 Rain 0 No 0000000 Not Applicable 0 0:00am-0:59am
## 3 Rain 0 No 0000000 Not Applicable 0 0:00am-0:59am
## 4 Cloudy 0 No 0000000 Not Applicable 99 Unknown
## 5 Cloudy 0 No 0000000 Not Applicable 99 Unknown
## 6 Cloudy 0 No 0000000 Not Applicable 99 Unknown
## NOT_MIN NOT_MINNAME ARR_HOUR ARR_HOURNAME ARR_MIN ARR_MINNAME HOSP_HR
## 1 99 Unknown 6 6:00am-6:59am 15 15 88
## 2 99 Unknown 0 0:00am-0:59am 59 59 88
## 3 99 Unknown 0 0:00am-0:59am 59 59 88
## 4 99 Unknown 23 11:00pm-11:59pm 10 10 99
## 5 99 Unknown 23 11:00pm-11:59pm 10 10 99
## 6 99 Unknown 23 11:00pm-11:59pm 10 10 99
## HOSP_HRNAME HOSP_MN HOSP_MNNAME
## 1 Not Applicable (Not Transported) 88 Not Applicable (Not Transported)
## 2 Not Applicable (Not Transported) 88 Not Applicable (Not Transported)
## 3 Not Applicable (Not Transported) 88 Not Applicable (Not Transported)
## 4 Unknown 99 Unknown EMS Hospital Arrival Time
## 5 Unknown 99 Unknown EMS Hospital Arrival Time
## 6 Unknown 99 Unknown EMS Hospital Arrival Time
## FATALS DRUNK_DR VEH_NO PER_NO DRUGSPEC DRUGSPECNAME DRUGRES
## 1 1 0 1 1 1 Whole Blood 1
## 2 2 0 1 1 0 Test Not Given 0
## 3 2 0 1 2 0 Test Not Given 0
## 4 1 0 1 1 1 Whole Blood 401
## 5 1 0 1 1 1 Whole Blood 417
## 6 1 0 1 1 1 Whole Blood 316
## DRUGRESNAME
## 1 Tested, No Drugs Found/Negative
## 2 Test Not Given
## 3 Test Not Given
## 4 AMPHETAMINE
## 5 METHAMPHETAMINE
## 6 Clonazepam
# Información de las variables y sus valores una vez agregados
structure3Y <- str(accident3Y)
## 'data.frame': 304393 obs. of 87 variables:
## $ ST_CASE : int 10001 10002 10002 10003 10003 10003 10003 10003 10004 10004 ...
## $ STATE : int 1 1 1 1 1 1 1 1 1 1 ...
## $ STATENAME : chr "Alabama" "Alabama" "Alabama" "Alabama" ...
## $ VE_TOTAL : int 2 1 1 2 2 2 2 2 1 1 ...
## $ VE_FORMS : int 1 1 1 2 2 2 2 2 1 1 ...
## $ PVH_INVL : int 1 0 0 0 0 0 0 0 0 0 ...
## $ PEDS : int 0 0 0 0 0 0 0 0 0 0 ...
## $ PERSONS : int 1 2 2 2 2 2 2 2 2 2 ...
## $ PERMVIT : int 1 2 2 2 2 2 2 2 2 2 ...
## $ PERNOTMVIT : int 0 0 0 0 0 0 0 0 0 0 ...
## $ COUNTY : int 121 127 127 21 21 21 21 21 3 3 ...
## $ COUNTYNAME : chr "TALLADEGA (121)" "WALKER (127)" "WALKER (127)" "CHILTON (21)" ...
## $ CITY : int 1870 1780 1780 0 0 0 0 0 0 0 ...
## $ CITYNAME : chr "LINCOLN" "JASPER" "JASPER" "NOT APPLICABLE" ...
## $ DAY : int 5 8 8 8 8 8 8 8 9 9 ...
## $ DAYNAME : int 5 8 8 8 8 8 8 8 9 9 ...
## $ MONTH : int 1 1 1 1 1 1 1 1 1 1 ...
## $ MONTHNAME : chr "January" "January" "January" "January" ...
## $ YEAR : int 2018 2018 2018 2018 2018 2018 2018 2018 2018 2018 ...
## $ DAY_WEEK : int 6 2 2 2 2 2 2 2 3 3 ...
## $ DAY_WEEKNAME: chr "Friday" "Monday" "Monday" "Monday" ...
## $ HOUR : int 6 0 0 22 22 22 22 22 13 13 ...
## $ HOURNAME : chr "6:00am-6:59am" "0:00am-0:59am" "0:00am-0:59am" "10:00pm-10:59pm" ...
## $ MINUTE : int 0 48 48 50 50 50 50 50 2 2 ...
## $ MINUTENAME : chr "0" "48" "48" "50" ...
## $ NHS : int 1 1 1 1 1 1 1 1 1 1 ...
## $ NHSNAME : chr "This section IS ON the NHS" "This section IS ON the NHS" "This section IS ON the NHS" "This section IS ON the NHS" ...
## $ ROUTE : int 1 1 1 1 1 1 1 1 1 1 ...
## $ ROUTENAME : chr "Interstate" "Interstate" "Interstate" "Interstate" ...
## $ TWAY_ID : chr "I-20" "I-22" "I-22" "I-65" ...
## $ TWAY_ID2 : chr "" "CALUMET RD" "CALUMET RD" "" ...
## $ RUR_URB : int 1 2 2 1 1 1 1 1 1 1 ...
## $ RUR_URBNAME : chr "Rural" "Urban" "Urban" "Rural" ...
## $ FUNC_SYS : int 1 1 1 1 1 1 1 1 1 1 ...
## $ FUNC_SYSNAME: chr "Interstate" "Interstate" "Interstate" "Interstate" ...
## $ RD_OWNER : int 1 1 1 1 1 1 1 1 1 1 ...
## $ RD_OWNERNAME: chr "State Highway Agency" "State Highway Agency" "State Highway Agency" "State Highway Agency" ...
## $ MILEPT : int 1676 1621 1621 2028 2028 2028 2028 2028 460 460 ...
## $ MILEPTNAME : chr "1676" "1621" "1621" "2028" ...
## $ LATITUDE : num 33.6 33.8 33.8 32.8 32.8 ...
## $ LATITUDENAME: chr "33.59133056" "33.80918611" "33.80918611" "32.76773611" ...
## $ LONGITUD : num -86.1 -87.3 -87.3 -86.6 -86.6 ...
## $ LONGITUDNAME: chr "-86.13186944" "-87.28984722" "-87.28984722" "-86.56403611" ...
## $ SP_JUR : int 0 0 0 0 0 0 0 0 0 0 ...
## $ SP_JURNAME : chr "No Special Jurisdiction" "No Special Jurisdiction" "No Special Jurisdiction" "No Special Jurisdiction" ...
## $ HARM_EV : int 14 38 38 24 24 24 24 24 24 24 ...
## $ HARM_EVNAME : chr "Parked Motor Vehicle" "Fence" "Fence" "Guardrail Face" ...
## $ MAN_COLL : int 0 0 0 0 0 0 0 0 0 0 ...
## $ MAN_COLLNAME: chr "Not a Collision with Motor Vehicle In-Transport" "Not a Collision with Motor Vehicle In-Transport" "Not a Collision with Motor Vehicle In-Transport" "Not a Collision with Motor Vehicle In-Transport" ...
## $ RELJCT1 : int 0 1 1 0 0 0 0 0 0 0 ...
## $ RELJCT1NAME : chr "No" "Yes" "Yes" "No" ...
## $ RELJCT2 : int 1 19 19 1 1 1 1 1 1 1 ...
## $ RELJCT2NAME : chr "Non-Junction" "Other location within Interchange Area" "Other location within Interchange Area" "Non-Junction" ...
## $ TYP_INT : int 1 1 1 1 1 1 1 1 1 1 ...
## $ TYP_INTNAME : chr "Not an Intersection" "Not an Intersection" "Not an Intersection" "Not an Intersection" ...
## $ WRK_ZONE : int 0 0 0 1 1 1 1 1 0 0 ...
## $ WRK_ZONENAME: chr "None" "None" "None" "Construction" ...
## $ REL_ROAD : int 2 3 3 4 4 4 4 4 4 4 ...
## $ REL_ROADNAME: chr "On Shoulder" "On Median" "On Median" "On Roadside" ...
## $ LGT_COND : int 4 2 2 2 2 2 2 2 1 1 ...
## $ LGT_CONDNAME: chr "Dawn" "Dark - Not Lighted" "Dark - Not Lighted" "Dark - Not Lighted" ...
## $ WEATHER : int 1 2 2 10 10 10 10 10 10 10 ...
## $ WEATHERNAME : chr "Clear" "Rain" "Rain" "Cloudy" ...
## $ SCH_BUS : int 0 0 0 0 0 0 0 0 0 0 ...
## $ SCH_BUSNAME : chr "No" "No" "No" "No" ...
## $ RAIL : chr "0000000" "0000000" "0000000" "0000000" ...
## $ RAILNAME : chr "Not Applicable" "Not Applicable" "Not Applicable" "Not Applicable" ...
## $ NOT_HOUR : int 6 0 0 99 99 99 99 99 13 13 ...
## $ NOT_HOURNAME: chr "6:00am-6:59am" "0:00am-0:59am" "0:00am-0:59am" "Unknown" ...
## $ NOT_MIN : int 99 99 99 99 99 99 99 99 99 99 ...
## $ NOT_MINNAME : chr "Unknown" "Unknown" "Unknown" "Unknown" ...
## $ ARR_HOUR : int 6 0 0 23 23 23 23 23 13 13 ...
## $ ARR_HOURNAME: chr "6:00am-6:59am" "0:00am-0:59am" "0:00am-0:59am" "11:00pm-11:59pm" ...
## $ ARR_MIN : int 15 59 59 10 10 10 10 10 14 14 ...
## $ ARR_MINNAME : chr "15" "59" "59" "10" ...
## $ HOSP_HR : int 88 88 88 99 99 99 99 99 88 88 ...
## $ HOSP_HRNAME : chr "Not Applicable (Not Transported)" "Not Applicable (Not Transported)" "Not Applicable (Not Transported)" "Unknown" ...
## $ HOSP_MN : int 88 88 88 99 99 99 99 99 88 88 ...
## $ HOSP_MNNAME : chr "Not Applicable (Not Transported)" "Not Applicable (Not Transported)" "Not Applicable (Not Transported)" "Unknown EMS Hospital Arrival Time" ...
## $ FATALS : int 1 2 2 1 1 1 1 1 1 1 ...
## $ DRUNK_DR : int 0 0 0 0 0 0 0 0 0 0 ...
## $ VEH_NO : int 1 1 1 1 1 1 1 2 1 1 ...
## $ PER_NO : int 1 1 2 1 1 1 1 1 1 2 ...
## $ DRUGSPEC : int 1 0 0 1 1 1 1 0 1 1 ...
## $ DRUGSPECNAME: chr "Whole Blood" "Test Not Given" "Test Not Given" "Whole Blood" ...
## $ DRUGRES : int 1 0 0 401 417 316 605 0 1 1 ...
## $ DRUGRESNAME : chr "Tested, No Drugs Found/Negative" "Test Not Given" "Test Not Given" "AMPHETAMINE" ...
El dataset en el que basaremos nuestro estudio contiene información de 304.393 observaciones correspondientes a accidentes de circulación mortales ocurridos en 2018, 2019 y 2020 en EEUU. Presenta 89 variables que proporcionan información relacionada con la casuística de los siniestros y se ha ampliado información auxiliar referente a la detección de drogas. Consultar en https://www.nhtsa.gov/research-data/fatality-analysis-reporting-system-fars
Observamos la descripción de las variables del fichero y apreciamos que la variable ST_CASE identificadora del siniestro.
Destacamos que existen variables duplicadas en forma numérica or ejemplo: NHS, ROUTE, FUNC_SYS, WEATHER, etc. y la versión descriptiva correspondiente, como NHSNAME, ROUTENAME, FUNC_SYSNAME, WEATHERNAME, etc. lo que nos permite usar tanto los valores descriptivos NAME para su interpretación o visualización, mientras que los codificados CODE pueden usarse para análisis automatizados.
Además, la mayoría de variables son categóricas, es decir describen tipos de condiciones por ejemplo: LGT_CONDNAME, segmentos: RUR_URBNAME, sistemas viales: FUNC_SYSNAME, etc. lo que implica que muchas técnicas de modelado requerirán transformación de variables categóricas a factores o variables dummy.
En esta etapa incluiremos la limpieza de los datos, transformación de variables, normalización y discretización si fueran necesario.
# Verificamos la existencia de valors nulos o vacíos por columnas
colSums(is.na(accident3Y))
## ST_CASE STATE STATENAME VE_TOTAL VE_FORMS PVH_INVL
## 0 0 0 0 0 0
## PEDS PERSONS PERMVIT PERNOTMVIT COUNTY COUNTYNAME
## 0 0 0 0 0 0
## CITY CITYNAME DAY DAYNAME MONTH MONTHNAME
## 0 0 0 0 0 0
## YEAR DAY_WEEK DAY_WEEKNAME HOUR HOURNAME MINUTE
## 0 0 0 0 0 0
## MINUTENAME NHS NHSNAME ROUTE ROUTENAME TWAY_ID
## 0 0 0 0 0 0
## TWAY_ID2 RUR_URB RUR_URBNAME FUNC_SYS FUNC_SYSNAME RD_OWNER
## 0 0 0 0 0 0
## RD_OWNERNAME MILEPT MILEPTNAME LATITUDE LATITUDENAME LONGITUD
## 0 0 0 0 0 0
## LONGITUDNAME SP_JUR SP_JURNAME HARM_EV HARM_EVNAME MAN_COLL
## 0 0 0 0 0 0
## MAN_COLLNAME RELJCT1 RELJCT1NAME RELJCT2 RELJCT2NAME TYP_INT
## 0 0 0 0 0 0
## TYP_INTNAME WRK_ZONE WRK_ZONENAME REL_ROAD REL_ROADNAME LGT_COND
## 0 0 0 0 0 0
## LGT_CONDNAME WEATHER WEATHERNAME SCH_BUS SCH_BUSNAME RAIL
## 0 0 0 0 0 0
## RAILNAME NOT_HOUR NOT_HOURNAME NOT_MIN NOT_MINNAME ARR_HOUR
## 0 0 0 0 0 0
## ARR_HOURNAME ARR_MIN ARR_MINNAME HOSP_HR HOSP_HRNAME HOSP_MN
## 0 0 0 0 0 0
## HOSP_MNNAME FATALS DRUNK_DR VEH_NO PER_NO DRUGSPEC
## 0 0 0 0 0 0
## DRUGSPECNAME DRUGRES DRUGRESNAME
## 0 0 0
colSums(accident3Y=="")
## ST_CASE STATE STATENAME VE_TOTAL VE_FORMS PVH_INVL
## 0 0 0 0 0 0
## PEDS PERSONS PERMVIT PERNOTMVIT COUNTY COUNTYNAME
## 0 0 0 0 0 0
## CITY CITYNAME DAY DAYNAME MONTH MONTHNAME
## 0 0 0 0 0 0
## YEAR DAY_WEEK DAY_WEEKNAME HOUR HOURNAME MINUTE
## 0 0 0 0 0 0
## MINUTENAME NHS NHSNAME ROUTE ROUTENAME TWAY_ID
## 0 0 0 0 0 0
## TWAY_ID2 RUR_URB RUR_URBNAME FUNC_SYS FUNC_SYSNAME RD_OWNER
## 218583 0 0 0 0 0
## RD_OWNERNAME MILEPT MILEPTNAME LATITUDE LATITUDENAME LONGITUD
## 0 0 0 0 0 0
## LONGITUDNAME SP_JUR SP_JURNAME HARM_EV HARM_EVNAME MAN_COLL
## 0 0 0 0 0 0
## MAN_COLLNAME RELJCT1 RELJCT1NAME RELJCT2 RELJCT2NAME TYP_INT
## 0 0 0 0 0 0
## TYP_INTNAME WRK_ZONE WRK_ZONENAME REL_ROAD REL_ROADNAME LGT_COND
## 0 0 0 0 0 0
## LGT_CONDNAME WEATHER WEATHERNAME SCH_BUS SCH_BUSNAME RAIL
## 0 0 0 0 0 0
## RAILNAME NOT_HOUR NOT_HOURNAME NOT_MIN NOT_MINNAME ARR_HOUR
## 0 0 0 0 0 0
## ARR_HOURNAME ARR_MIN ARR_MINNAME HOSP_HR HOSP_HRNAME HOSP_MN
## 0 0 0 0 0 0
## HOSP_MNNAME FATALS DRUNK_DR VEH_NO PER_NO DRUGSPEC
## 0 0 0 0 0 0
## DRUGSPECNAME DRUGRES DRUGRESNAME
## 0 0 0
# Distribución de la variable FATALS
library(dplyr)
df_fatal <- accident3Y %>%
group_by(FATALS) %>%
dplyr::summarise(counts = n())
df_fatal
## # A tibble: 9 × 2
## FATALS counts
## <int> <int>
## 1 1 269537
## 2 2 27520
## 3 3 5067
## 4 4 1596
## 5 5 390
## 6 6 93
## 7 7 88
## 8 8 79
## 9 20 23
#
ggplot(accident3Y, aes(x = as.factor(YEAR), fill = as.factor(YEAR))) +
geom_bar(stat = "count", show.legend = FALSE) +
scale_fill_manual(values = c("2018" = "skyblue", "2019" = "lightgreen", "2020" = "orange")) +
labs(title = "Número de Accidentes por Año", x = "Año", y = "Número de Accidentes") +
geom_text(stat = "count", aes(label = ..count..), position = position_dodge(width = 1.2), vjust = 1.5, color = "black") +
theme_minimal() +
theme(panel.grid = element_blank(),
axis.text.x = element_text(angle = 45, hjust = 1))
Obaservamos un aumento de los accidentes en 2020 respecto a los años anteriores, en comparación con 2018 es del 7.37% y un 7.58% con el año 2019. Podriamos decir que existe una tendencia a aumentar del número de accidentes mortales.
# Distribución de la variable WEATHER
df_weather <- accident3Y %>%
group_by(WEATHER) %>%
dplyr::summarise(counts = n()) %>%
left_join(accident3Y %>% select(WEATHER, WEATHERNAME) %>% distinct(), by = "WEATHER")
df_weather
## # A tibble: 13 × 3
## WEATHER counts WEATHERNAME
## <int> <int> <chr>
## 1 1 208045 Clear
## 2 2 23852 Rain
## 3 3 453 Sleet or Hail
## 4 4 3314 Snow
## 5 5 3230 Fog, Smog, Smoke
## 6 6 511 Severe Crosswinds
## 7 7 59 Blowing Sand, Soil, Dirt
## 8 8 212 Other
## 9 10 42569 Cloudy
## 10 11 325 Blowing Snow
## 11 12 284 Freezing Rain or Drizzle
## 12 98 20301 Not Reported
## 13 99 1238 Reported as Unknown
ggplot(accident3Y, aes(x = WEATHERNAME, fill = as.factor(YEAR))) +
geom_bar(position = "dodge", stat = "count", show.legend = TRUE) +
scale_fill_manual(values = c("2018" = "skyblue", "2019" = "lightgreen", "2020" = "orange")) +
labs(title = "Accidentes por Condición Meteorológica y Año",
x = "Condición Meteorológica",
y = "Número de Accidentes",
fill = "Año") +
theme_minimal() +
theme(panel.grid = element_blank(),
axis.text.x = element_text(angle = 45, hjust = 1),
plot.title.margin = margin(t = 20))
#### Justificación de los resultados Se muestra el número de accidentes
por condición meteorológica y año. Existe un aumento significativo de
accidentes en 2020 bajo condiciones despejadas podría estar relacionado
con un aumento del tráfico, mientras que existe una disminución en
condiciones meteorológicas adversas como lluvia y nieve que podría
reflejar una reducción en el tráfico debido a la pandemia. Este gráfico
sugiere que la condición meteorológica más común, el clima despejado, es
donde se concentra el mayor número de accidentes. También, vemos un
aumento durante la lluvia en 2020 en comparación con los años
anteriores. Aunque, estos cambios podrian estar sesgados debido a los
años de pandemia, ya que a mayor trafico mayor probabilidad de tener un
siniestro, existe una relación positiva.
La matriz de correlación mostrará las relaciones entre las variables. + Las correlaciones cercanas a 1 indican una relación fuerte y positiva entre las variables. + Las correlaciones cercanas a -1 indican una relación fuerte y negativa. + Las correlaciones cercanas a 0 indican que no hay una relación lineal significativa.
# Variables numéricas relevantes
numeric_vars <- accident3Y[, c("VE_TOTAL", "FATALS", "DRUNK_DR", "WEATHER", "FUNC_SYS", "RUR_URB", "LGT_COND", "SP_JUR")]
corr_matrix <- cor(numeric_vars, use = "complete.obs")
# Visualizar la matriz de correlación
library(corrplot)
corrplot(corr_matrix, method = "color", type = "upper", tl.col="black", tl.srt=30, order = "AOE", number.cex=0.75, sig.level = 0.01, addCoef.col = "black")
#### Justificación de los resultados La correlación de 0.12 entre
VE_TOTAL y FATALS sugiere una relación muy débil, pero positiva,
mientras que la correlación de -0.01 indica que no hay una relación
significativa entre el número de vehículos involucrados y la presencia
de alcohol. Asimismo, existe una correlación debil pero positiva de 0.07
entre DRUNK_DR y FATALS. Tenemos en su amyoría relaciones débiles a
moderadas en su mayoría, otro ejemplo, es la variable RUR_URB que tiene
una correlación moderada con VE_TOTAL, lo que indica que las zonas
urbanas tienen más vehículos involucrados en los accidentes. Las
condiciones de luz en el momento del accidente tienen una correlación
algo más fuerte sugiriendo que los accidentes en condiciones de baja
visibilidad tienden a ser más graves.
library(tidyr)
# Contamos los accidentes por estado y año
accident_State <- accident3Y %>%
group_by(STATENAME, YEAR) %>%
summarise(total_accidents = n(), .groups = "drop")
# Convertimos año por columna
accident_State2 <- accident_State %>%
pivot_wider(names_from = YEAR, values_from = total_accidents,
values_fill = list(total_accidents = 0))
accident_State2
## # A tibble: 51 × 4
## STATENAME `2018` `2019` `2020`
## <chr> <int> <int> <int>
## 1 Alabama 2404 2411 2490
## 2 Alaska 227 210 206
## 3 Arizona 3056 2717 2868
## 4 Arkansas 1336 1214 1556
## 5 California 10716 11012 12323
## 6 Colorado 1808 1735 1893
## 7 Connecticut 834 676 818
## 8 Delaware 332 424 325
## 9 District of Columbia 86 66 88
## 10 Florida 8111 8633 8588
## # ℹ 41 more rows
accident_State3 <- accident_State2 %>%
pivot_longer(cols = c(`2018`, `2019`, `2020`),
names_to = "YEAR",
values_to = "total_accidents")
# Gráficamos
library(ggplot2)
ggplot(accident_State3, aes(x = STATENAME, y = total_accidents, fill = YEAR)) +
geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.7) + # Ancho ajustado de las barras
labs(title = "Número de Accidentes por Estado y Año",
x = "Estado",
y = "Número de Accidentes") +
theme_minimal() + # Fondo limpio
theme(
axis.text.x = element_text(angle = 90, hjust = 1, size = 8),
axis.text.y = element_text(size = 10),
axis.title.x = element_text(size = 12),
axis.title.y = element_text(size = 12),
legend.position = "top",
legend.text = element_text(size = 10),
plot.title = element_text(hjust = 0.5, size = 14, face = "bold")
) +
scale_fill_manual(values = c("2018" = "skyblue", "2019" = "lightgreen", "2020" = "orange")) +
coord_cartesian(clip = 'off')
#### Justificación de los resultados Los estados con mayor número de
accidentes son California y Texas, especialmente en 2020, donde los
accidentes fueron significativamente más altos en comparación con los
otros años, auque es una tendencia generalizada en consecuencia de la
pandemia. Los 5 primeros estados con mayor número de accidentes durante
los 3 años fueron California con 35.400 accidentes, Texas 34.200,
Florida 32.400, Ohio 31.500 y Georgia 29.500.
# Filtramos los estados específicos
accident_ST5 <- subset(accident3Y,
STATENAME %in% c("California", "Texas", "Florida", "Ohio", "Georgia"))
# Gráfico de barras con FATALS por tipo de carretera y estado
ggplot(data = accident_ST5, aes(x = FUNC_SYSNAME, fill = STATENAME)) +
geom_bar() +
ggtitle("Número de Fatalidades por Tipo de Carretera y Estado") +
labs(x = "Tipo de Carretera", y = "Número de Fatalidades") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
#### Justificación de resultados California y Texas presentan más
fatalidades en carreteras de alta capacidad como interestatales y
principales arteriales, lo que puede deberse a una mayor cantidad de
afluencia y tráfico. Florida y Georgia tienen más diversidad según el
tipo de carretera, lo que sugiere que tienen una infraestructura más
variada y afecta a los accidentes de manera diferente. Ohio presenta
menos fatalidades en las carreteras de mayor capacidad, lo que podría
ser indicativo de una mejor gestión del tráfico o menores incidencias en
carreteras principales. Este análisis sugiere que la infraestructura
vial y la cantidad de tráfico son factores clave en la distribución de
las fatalidades, y sería útil realizar un análisis más profundo,
considerando otras variables como la densidad de tráfico.
# Gráfico de barras apiladas por FATALS, facetas por WEATHER
ggplot(data = accident_ST5, aes(x = FATALS, fill = STATENAME)) +
geom_bar(position = "fill") + # Usamos "fill" para ver la proporción
facet_wrap(~WEATHER) + # Facetamos por las condiciones meteorológicas
ggtitle("Número de Fatalidades por Estado, Tipo de Carretera y Condiciones Meteorológicas") +
labs(x = "Número de Fatalidades", y = "Proporción") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
#### Justificación de los resultados El gráfico nos muestra la relación
entre las fatalidades por estado, condiciones meteorológicas y segun el
tipo de carrtera. Al comparar los estados, se observa que estados como
California y Texas tienen barras más grandes y más segmentos, lo que
refleja una mayor cantidad de accidentes en diversas condiciones
meteorológicas. En cambio, estados como Ohio y Florida presentan menos
fatalidades en ciertas condiciones, lo que podría estar relacionado con
diferentes patrones de tráfico. El gráfico identificar patrones en las
condiciones meteorológicas, por ejemplo, las condiciones despejadas o
soleadas pueden estar relacionadas con más fatalidades en California
debido a su alto volumen de tráfico, mientras que las condiciones de
lluvia o tormentas podrían estar asociadas con más fatalidades en
estados con infraestructuras viales deficientes. En términos de tipo de
carretera, se observa que las carreteras de alta capacidad, como las
interestatales y autopistas principales en estados como California y
Texas, tienen una mayor incidencia de fatalidades. Esto se debe a la
alta densidad de tráfico en estas vías. En resumen, este análisis m¡nos
permite comparar cómo las fatalidades se distribuyen en los diferentes
estados según las condiciones meteorológicas, sugiriendo que factores
como la infraestructura vial, la densidad de tráfico y la gestión de
condiciones meteorológicas juegan un papel fundamental en los
siniestros. Los estados con más fatalidades en condiciones
meteorológicas adversas podrían necesitar mejorar la infraestructura o
implementar políticas de seguridad vial más estrictas.
Discretizamos la variable MONTH en intervalos mensuales. Se dividirá en intervalos trimestrales (enero-marzo), segundo trimestre (abril-junio), tercer trimestre (julio-septiembre) y cuarto trimestre (octubre-diciembre).
# Discretizamos la variable MONTH en 4 trimestres
accident3Y$MONTH_BIN <- cut(
accident3Y$MONTH,
breaks = c(0, 3, 6, 9, 12),
labels = c("Q1", "Q2", "Q3", "Q4"),
right = FALSE
)
# Verificamos las primeras filas con la nueva columna MONTH_BIN
head(accident3Y)
## ST_CASE STATE STATENAME VE_TOTAL VE_FORMS PVH_INVL PEDS PERSONS PERMVIT
## 1 10001 1 Alabama 2 1 1 0 1 1
## 2 10002 1 Alabama 1 1 0 0 2 2
## 3 10002 1 Alabama 1 1 0 0 2 2
## 4 10003 1 Alabama 2 2 0 0 2 2
## 5 10003 1 Alabama 2 2 0 0 2 2
## 6 10003 1 Alabama 2 2 0 0 2 2
## PERNOTMVIT COUNTY COUNTYNAME CITY CITYNAME DAY DAYNAME MONTH
## 1 0 121 TALLADEGA (121) 1870 LINCOLN 5 5 1
## 2 0 127 WALKER (127) 1780 JASPER 8 8 1
## 3 0 127 WALKER (127) 1780 JASPER 8 8 1
## 4 0 21 CHILTON (21) 0 NOT APPLICABLE 8 8 1
## 5 0 21 CHILTON (21) 0 NOT APPLICABLE 8 8 1
## 6 0 21 CHILTON (21) 0 NOT APPLICABLE 8 8 1
## MONTHNAME YEAR DAY_WEEK DAY_WEEKNAME HOUR HOURNAME MINUTE MINUTENAME
## 1 January 2018 6 Friday 6 6:00am-6:59am 0 0
## 2 January 2018 2 Monday 0 0:00am-0:59am 48 48
## 3 January 2018 2 Monday 0 0:00am-0:59am 48 48
## 4 January 2018 2 Monday 22 10:00pm-10:59pm 50 50
## 5 January 2018 2 Monday 22 10:00pm-10:59pm 50 50
## 6 January 2018 2 Monday 22 10:00pm-10:59pm 50 50
## NHS NHSNAME ROUTE ROUTENAME TWAY_ID TWAY_ID2 RUR_URB
## 1 1 This section IS ON the NHS 1 Interstate I-20 1
## 2 1 This section IS ON the NHS 1 Interstate I-22 CALUMET RD 2
## 3 1 This section IS ON the NHS 1 Interstate I-22 CALUMET RD 2
## 4 1 This section IS ON the NHS 1 Interstate I-65 1
## 5 1 This section IS ON the NHS 1 Interstate I-65 1
## 6 1 This section IS ON the NHS 1 Interstate I-65 1
## RUR_URBNAME FUNC_SYS FUNC_SYSNAME RD_OWNER RD_OWNERNAME MILEPT
## 1 Rural 1 Interstate 1 State Highway Agency 1676
## 2 Urban 1 Interstate 1 State Highway Agency 1621
## 3 Urban 1 Interstate 1 State Highway Agency 1621
## 4 Rural 1 Interstate 1 State Highway Agency 2028
## 5 Rural 1 Interstate 1 State Highway Agency 2028
## 6 Rural 1 Interstate 1 State Highway Agency 2028
## MILEPTNAME LATITUDE LATITUDENAME LONGITUD LONGITUDNAME SP_JUR
## 1 1676 33.59133 33.59133056 -86.13187 -86.13186944 0
## 2 1621 33.80919 33.80918611 -87.28985 -87.28984722 0
## 3 1621 33.80919 33.80918611 -87.28985 -87.28984722 0
## 4 2028 32.76774 32.76773611 -86.56404 -86.56403611 0
## 5 2028 32.76774 32.76773611 -86.56404 -86.56403611 0
## 6 2028 32.76774 32.76773611 -86.56404 -86.56403611 0
## SP_JURNAME HARM_EV HARM_EVNAME MAN_COLL
## 1 No Special Jurisdiction 14 Parked Motor Vehicle 0
## 2 No Special Jurisdiction 38 Fence 0
## 3 No Special Jurisdiction 38 Fence 0
## 4 No Special Jurisdiction 24 Guardrail Face 0
## 5 No Special Jurisdiction 24 Guardrail Face 0
## 6 No Special Jurisdiction 24 Guardrail Face 0
## MAN_COLLNAME RELJCT1 RELJCT1NAME RELJCT2
## 1 Not a Collision with Motor Vehicle In-Transport 0 No 1
## 2 Not a Collision with Motor Vehicle In-Transport 1 Yes 19
## 3 Not a Collision with Motor Vehicle In-Transport 1 Yes 19
## 4 Not a Collision with Motor Vehicle In-Transport 0 No 1
## 5 Not a Collision with Motor Vehicle In-Transport 0 No 1
## 6 Not a Collision with Motor Vehicle In-Transport 0 No 1
## RELJCT2NAME TYP_INT TYP_INTNAME WRK_ZONE
## 1 Non-Junction 1 Not an Intersection 0
## 2 Other location within Interchange Area 1 Not an Intersection 0
## 3 Other location within Interchange Area 1 Not an Intersection 0
## 4 Non-Junction 1 Not an Intersection 1
## 5 Non-Junction 1 Not an Intersection 1
## 6 Non-Junction 1 Not an Intersection 1
## WRK_ZONENAME REL_ROAD REL_ROADNAME LGT_COND LGT_CONDNAME WEATHER
## 1 None 2 On Shoulder 4 Dawn 1
## 2 None 3 On Median 2 Dark - Not Lighted 2
## 3 None 3 On Median 2 Dark - Not Lighted 2
## 4 Construction 4 On Roadside 2 Dark - Not Lighted 10
## 5 Construction 4 On Roadside 2 Dark - Not Lighted 10
## 6 Construction 4 On Roadside 2 Dark - Not Lighted 10
## WEATHERNAME SCH_BUS SCH_BUSNAME RAIL RAILNAME NOT_HOUR NOT_HOURNAME
## 1 Clear 0 No 0000000 Not Applicable 6 6:00am-6:59am
## 2 Rain 0 No 0000000 Not Applicable 0 0:00am-0:59am
## 3 Rain 0 No 0000000 Not Applicable 0 0:00am-0:59am
## 4 Cloudy 0 No 0000000 Not Applicable 99 Unknown
## 5 Cloudy 0 No 0000000 Not Applicable 99 Unknown
## 6 Cloudy 0 No 0000000 Not Applicable 99 Unknown
## NOT_MIN NOT_MINNAME ARR_HOUR ARR_HOURNAME ARR_MIN ARR_MINNAME HOSP_HR
## 1 99 Unknown 6 6:00am-6:59am 15 15 88
## 2 99 Unknown 0 0:00am-0:59am 59 59 88
## 3 99 Unknown 0 0:00am-0:59am 59 59 88
## 4 99 Unknown 23 11:00pm-11:59pm 10 10 99
## 5 99 Unknown 23 11:00pm-11:59pm 10 10 99
## 6 99 Unknown 23 11:00pm-11:59pm 10 10 99
## HOSP_HRNAME HOSP_MN HOSP_MNNAME
## 1 Not Applicable (Not Transported) 88 Not Applicable (Not Transported)
## 2 Not Applicable (Not Transported) 88 Not Applicable (Not Transported)
## 3 Not Applicable (Not Transported) 88 Not Applicable (Not Transported)
## 4 Unknown 99 Unknown EMS Hospital Arrival Time
## 5 Unknown 99 Unknown EMS Hospital Arrival Time
## 6 Unknown 99 Unknown EMS Hospital Arrival Time
## FATALS DRUNK_DR VEH_NO PER_NO DRUGSPEC DRUGSPECNAME DRUGRES
## 1 1 0 1 1 1 Whole Blood 1
## 2 2 0 1 1 0 Test Not Given 0
## 3 2 0 1 2 0 Test Not Given 0
## 4 1 0 1 1 1 Whole Blood 401
## 5 1 0 1 1 1 Whole Blood 417
## 6 1 0 1 1 1 Whole Blood 316
## DRUGRESNAME MONTH_BIN
## 1 Tested, No Drugs Found/Negative Q1
## 2 Test Not Given Q1
## 3 Test Not Given Q1
## 4 AMPHETAMINE Q1
## 5 METHAMPHETAMINE Q1
## 6 Clonazepam Q1
# Eliminar los registros con valores NA en la columna MONTH_BIN
accident3Y_clean <- accident3Y[!is.na(accident3Y$MONTH_BIN), ]
# Verificar nuevamente la distribución de los datos
table(accident3Y_clean$MONTH_BIN)
##
## Q1 Q2 Q3 Q4
## 42705 69595 84364 82452
# Verificamos la distribución de los intervalos
table(accident3Y_clean$MONTH_BIN)
##
## Q1 Q2 Q3 Q4
## 42705 69595 84364 82452
# Gráficamos la distribución de los intervalos de MONTH_BIN
ggplot(accident3Y_clean, aes(x = MONTH_BIN, fill = MONTH_BIN)) +
geom_bar() +
ggtitle("Distribución de Accidentes por Trimestre del Año") +
labs(x = "Trimestre", y = "Número de Accidentes") +
theme_minimal()
#### Jusrificación de resultados Discretización de la variable MONTH en
trimestres nos permite observar cómo varían las fatalidades a lo largo
del año. El gráfico muestra que los **accidentes son más frecuentes en
los trimestres Q3 y Q4, lo que puede estar relacionado con un aumento
del tráfico o condiciones meteorológicas específicas en estos períodos.
La menor frecuencia de accidentes en Q1 podría reflejar una disminución
de los viajes debido al clima invernal o a las menores actividades en
invierno, mientras que Q3 se dispara, lo que podría estar influenciado
por el turismo o el tráfico veraniego. Y, Q4 podría estar influenciado
por el clima de invierno, la proximidad de las festividades y el aumento
de desplazamientos, lo que incrementa el riesgo de accidentes. Útil para
diseñar estrategias de seguridad vial en épocas específicas del año,
como campañas de concienciación durante los meses con mayor número de
accidentes.
# Variables numéricas
numerics <- c("VE_TOTAL", "FATALS", "PEDS", "PERSONS", "DRUGSPEC")
accident_numerics <- accident3Y[, numerics]
# Eliminarmos los NA
accident_numerics <- na.omit(accident_numerics)
# Normalizarmos los datos
accident_numerics2 <- scale(accident_numerics)
# PCA
pca1 <- prcomp(accident_numerics2, center = TRUE, scale. = TRUE)
# Resumen del pca
summary(pca1)
## Importance of components:
## PC1 PC2 PC3 PC4 PC5
## Standard deviation 1.3395 1.0025 0.9687 0.9410 0.61380
## Proportion of Variance 0.3589 0.2010 0.1877 0.1771 0.07535
## Cumulative Proportion 0.3589 0.5599 0.7476 0.9246 1.00000
# Visualización de la varianza explicada por cada componente
if(!require("factoextra")) install.packages("factoextra")
library("factoextra")
# Graficamos la varianza explicada
# Usando fviz_eig con colores personalizados por componente
fviz_eig(pca1, addlabels = TRUE, ylim = c(0, 50)) +
scale_fill_manual(values = c("skyblue", "lightgreen", "orange", "pink", "purple"))
Este gráfico muestra la proporción de la varianza explicada por cada componente principal en el análisis de componentes principales (PCA). El PC1 explica el 35.9% de la varianza total, lo que significa que esta dimensión es la que contiene la mayor cantidad de información de los datos. PC2 explica el 20.1% de la varianza, lo que indica que agrega una cantidad significativa de variabilidad al modelo. PC3, PC4 y PC5 aunque importantes, explican una porción mucho más pequeña de la varianza. PC3 explica el 18.8%, PC4 explica el 17.7%, y PC5 explica el 7.5%. La desviación estándar de los componentes principales indica cuánta variabilidad tiene cada componente.El PC1 tiene una desviación estándar de 1.3395, lo que significa que captura una gran cantidad de variabilidad en los datos, mientras que PC2 captura 1.0025, lo que también es significativo. La Proporción acumulada de PC1 + PC2 explica 55.99% de la varianza total. Por tanto, para un buen ajuste es recomendable capturar el 92.46% de la varianza total que engloba PC1 + PC2 + PC3 + PC4.
# Seleccionamos los primeros 4 componentes principales
pca_data <- pca1$x[, 1:4]
# Aplicamos el algoritmo K-means
set.seed(123)
kmeans_result <- kmeans(pca_data, centers = 4)
# Añadimos la columna con los grupos/clusters al dataframe original
accident3Y$Cluster <- kmeans_result$cluster
# Visualización con ggplot
ggplot(accident3Y, aes(x = pca_data[, 1], y = pca_data[, 2], color = as.factor(Cluster))) +
geom_point(alpha = 0.7) +
labs(title = "Visualización de Clusters usando PCA (PC1 vs PC2)",
x = "PC1", y = "PC2", color = "Cluster") +
theme_minimal() +
scale_color_manual(values = c("red", "blue", "green", "purple"))
Al aplicar K-means, hemos podido identificado 4 grupos de accidentes con características similares. Cada color corresponde a un cluster, lo que nos permite visualizar cómo se segmentan los datos en función de las componentes principales. La dispersión de los puntos dentro de cada cluster puede ser útil para entender la variabilidad interna de los grupos. Cluster 1 (rojo): Se concentra en valores negativos de PC1 y PC2, sugiriendo características distintas con valores bajos en ambas dimensiones. Cluster 2 (azul): Centrado cerca de cero en PC1 con alta dispersión en PC2, indicando valores intermedios en PC1 y mayor variabilidad en PC2. Cluster 3 (verde): Con valores positivos en PC1 y negativos en PC2, indicando características correlacionadas con PC1 altos y PC2 bajos. Cluster 4 (púrpura): Se encuentra en el extremo derecho, con valores altos en ambas dimensiones, sugiriendo una correlación positiva entre PC1 y PC2.
Calculamos la media y la mode
# Función para calcular la mode
Mode <- function(x) {
ux <- unique(x)
ux[which.max(tabulate(match(x, ux)))]
}
# Añadimos el cluster resultante al dataset
accident3Y$Cluster <- kmeans_result$cluster
# Analizamos las características por cluster, seleccionando variables relevantes
cluster_summary <- accident3Y %>%
group_by(Cluster) %>%
summarise(
mean_fatalities = mean(FATALS, na.rm = TRUE),
mean_ve_total = mean(VE_TOTAL, na.rm = TRUE),
mean_persons = mean(PERSONS, na.rm = TRUE),
mean_peds = mean(PEDS, na.rm = TRUE),
mode_weather = Mode(WEATHERNAME),
mode_func_sys = Mode(FUNC_SYSNAME),
mode_state = Mode(STATENAME),
)
print(cluster_summary)
## # A tibble: 4 × 8
## Cluster mean_fatalities mean_ve_total mean_persons mean_peds mode_weather
## <int> <dbl> <dbl> <dbl> <dbl> <chr>
## 1 1 1.09 1.87 3.11 0.000179 Clear
## 2 2 2.49 3.95 10.1 0.0193 Clear
## 3 3 1.10 1.77 2.60 0.292 Clear
## 4 4 1.03 1.28 1.78 1.13 Clear
## # ℹ 2 more variables: mode_func_sys <chr>, mode_state <chr>
library(reshape2)
# Convertir los datos del resumen en formato largo
cluster_long <- cluster_summary %>%
select(Cluster, mean_fatalities, mean_ve_total, mean_persons, mean_peds) %>%
melt(id.vars = "Cluster", variable.name = "Variable", value.name = "Mean_Value")
# Gráfico de barras para comparar las medias por Cluster
ggplot(cluster_long, aes(x = factor(Cluster), y = Mean_Value, fill = Variable)) +
geom_bar(stat = "identity", position = "dodge") +
labs(title = "Comparación de Características por Cluster",
x = "Cluster", y = "Valor Promedio") +
scale_fill_brewer(palette = "Set3") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Explicación de las variables: + mean_fatalities (fatalidades): Promedio de las fatalidades por accidente. + mean_ve_total (número total de vehículos involucrados): Promedio de vehículos involucrados en los accidentes. + mean_persons (número de personas involucradas): Promedio de personas involucradas en los accidentes. + mean_peds (número de peatones involucrados): Promedio de peatones involucrados en los accidentes. Cluster 1 representa accidentes más pequeños o menos graves con menos vehículos, personas y peatones involucrados. Cluster 2 representa los accidentes más graves con mayor número de vehículos y personas involucradas. Cluster 3 y Cluster 4 son intermedios, con características que se asemejan más a los grupos más graves pero sin llegar a los niveles del Cluster 2. Este gráfico te permite comparar cómo las variables clave de los accidentes (fatalidades, vehículos, personas, peatones) varían a lo largo de diferentes grupos (clusters) generados en el análisis de PCA y clustering.
# Convertimos las modas
cluster_mode <- cluster_summary %>%
select(Cluster, mode_weather, mode_func_sys, mode_state) %>%
melt(id.vars = "Cluster", variable.name = "Variable", value.name = "Mode")
# Gráfico de barras apiladas para las modas de las variables categóricas
ggplot(cluster_mode, aes(x = factor(Cluster), fill = Mode)) +
geom_bar(stat = "count", position = "stack") +
facet_wrap(~Variable, scales = "free") +
labs(title = "Distribución de Modas por Cluster",
x = "Cluster", y = "Frecuencia") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
#### Justificación de los resultados Gráfico comparativo de las
frecuencias de las categorías más comunes de las variables categóricas
(como clima, tipo de carretera y estado) por cada cluster. Este gráfico
permite observar cómo se distribuyen las categorías más frecuentes
(modas) dentro de cada cluster para las variables categóricas como el
clima, el tipo de carretera y el estado. Ayuda a ver qué características
son predominantes dentro de cada cluster, como si ciertos estados o
tipos de carreteras están asociados a clusters con más fatalidades.
A partir del juego de datos utilizado en el ejemplo de la PEC, realiza un análisis exploratorio de datos con el paquete explore() de R y comenta las ventajas e inconvenientes que presenta respecto al análisis realizado en el ejercicio 2.
Puedes utilizar la documentación publicada del paquete explore() en https://github.com/rolkra/explore
if (!requireNamespace("explore", quietly = TRUE)) {
install.packages("explore")
}
# Cargar el paquete
library(explore)
Paso 2: Aplicación del Paquete explore() Aplicaremos el paquete explore() a nuestro conjunto de datos (accident3Y), o al conjunto de datos proporcionado, y realizaremos un análisis exploratorio de datos (EDA).
explore(accident3Y)
Paso 3: Analisis de los resultados con explore()
Rapidez y eficiencia: El principal beneficio de usar explore() es su rapidez. Con una sola línea de código, obtienes un análisis completo del dataset. En vez de escribir múltiples bloques de código para cada análisis (estadísticas descriptivas, gráficos, identificación de outliers), todo se hace automáticamente. Esto es ideal cuando el tiempo es limitado o cuando se necesita hacer un análisis exploratorio preliminar de manera rápida.
Automatización: El paquete se encarga de generar los gráficos y cálculos necesarios sin tener que realizar tareas repetitivas de manera manual. Esto es útil cuando se tiene un gran volumen de datos o cuando se quiere ahorrar tiempo en el análisis preliminar.
Resumen: explore() es útil cuando quieres obtener rápidamente una visión global del conjunto de datos. Muestra la distribución de las variables, las relaciones entre ellas y cualquier irregularidad en los datos.
Poca personalización: Aunque explore() genera resúmenes estadísticos y gráficos automáticamente, la personalización es limitada. Si necesitas ajustar el formato de los gráficos, cambiar los colores, o realizar análisis más específicos (como segmentar datos en función de una variable), entonces tendrás que recurrir a herramientas más flexibles, como ggplot2 o dplyr.
Análisis superficial: El paquete ofrece una descripción general, pero no profundiza en el contexto ni en las relaciones complejas entre las variables. En el ejercicio 2, el análisis fue realizado manualmente, lo que nos permitió tomar decisiones informadas sobre qué hacer con los datos (como seleccionar variables de interés, hacer transformaciones específicas o crear gráficos personalizados).
Poca flexibilidad para análisis complejos: Si se necesitan análisis más complejos, como el cálculo de métricas específicas o la creación de modelos, explore() no ofrece esta flexibilidad. Por ejemplo, si tuviéramos que aplicar técnicas de modelado o realizar un análisis de regresión, necesitaríamos hacerlo manualmente utilizando otros paquetes de R.
En el ejercicio 2, realizamos un análisis exploratorio de datos detallado utilizando ggplot2, dplyr y otras librerías para limpiar, transformar y visualizar los datos. Este enfoque nos permitió:
En cambio, con explore(), no tenemos tanto control sobre el análisis y la visualización. El paquete genera un resumen rápido, pero la capacidad de personalizar el análisis y los gráficos es limitada.
explore() es muy útil para realizar un análisis exploratorio rápido y obtener una visión global del conjunto de datos de forma automatizada. Sin embargo, es menos flexible que el enfoque manual realizado en el ejercicio 2, donde tenemos más control sobre el análisis y la personalización de los gráficos. Si buscamos rapidez y eficiencia para un análisis preliminar, explore() es una excelente opción. Sin embargo, si necesitamos un análisis más profundo, específico o personalizado, el enfoque manual será más adecuado.