Este análisis forma parte de la fase de limpieza, preprocesado y análisis de datos del Trabajo Final de Máster ‘Análisis y modelización predictiva de accidentes de tráfico con animales involucrados en vías interurbanas de España’, realizado por Alba Gómez Varela y dirigido por Sergio Trilles Oliver en el marco del Máster Universitario de Ciencia de Datos (Data Science) de la Universitat Oberta de Catalunya (UOC).
Los datos que se tratan y analizan en el presente documento proceden de un proceso de optimización de los registros de todos los accidentes de tráfico en España en los que ha habido animales involucrados entre 2016 y 2021, cuya fuente es la Dirección General de Tráfico (DGT). Para ello, se ha realizado un complejo proceso de búsqueda de nuevas fuentes de datos, conversión e integración que se puede consultar en este repositorio de GitHub.
En primer lugar, se procede a realizar la conexión
con la base de datos tfm, que es con la que se trabaja
durante todo el proyecto:
# Se lee el driver de PostgreSQL
drv <- dbDriver("PostgreSQL")
# Se crea la conexion con la base de datos
con <- dbConnect(drv, dbname = "tfm",
host = "localhost", port = 5432,
user = "postgres", password = pw)
# Se elimina la contraseña
rm(pw) Con la conexión ya realizada, se procede a cargar los
datos que están almacenados en la base de datos
tfm y se lee la tabla
accidentes_animales_final, que es la que contiene los
registros de accidentes de tráfico con animales ya optimizados tras la
decodificación e integración de nuevas fuentes de datos:
accidentes.raw <- DBI::dbReadTable(con, "accidentes_animales_final")
accidentes.raw.dim <- dim(accidentes.raw)Se han cargado 165.452 registros con 50 campos asociados a cada uno. Así, se muestran 5 registros aleatorios para comprobar la estructura del conjunto de datos, puesto que si se seleccionan los del principio (head) o final (tail) todos serán del mismo año:
accidentes.raw[sample(nrow(accidentes.raw), 5), ]Además, se examina el tipo de datos de cada variable:
Form.Basic = c("striped", "hover", "condensed", "responsive")
kbl(cbind(sapply(accidentes.raw, class)),
caption="Tipo de datos de cada variable") %>%
kable_styling(bootstrap_options = Form.Basic) %>%
scroll_box(width = "100%",
height = "400px")| id_num | numeric |
| ind_accda | integer |
| nombre_ind_accd | character |
| ind_acciv | integer |
| nombre_ind_acciv | character |
| total_mu30df | integer |
| total_hg30df | integer |
| total_hl30df | integer |
| fecha_accidente | Date |
| hora_accidente | character |
| mes_1f | integer |
| nombre_mes | character |
| anyo | integer |
| ccaa_1f | integer |
| nombre_ccaa | character |
| provincia_1f | integer |
| nombre_provincia | character |
| cod_municipio | integer |
| nombre_municipio | character |
| carretera | character |
| km | numeric |
| sentido_1f | integer |
| nombre_sentido | character |
| tipo_via_3f | integer |
| nombre_tipo_via | character |
| titularidad_via_2f | integer |
| nombre_titularidad_via | character |
| tipo_animal_1f | integer |
| nombre_tipo_animal_1f | character |
| tipo_animal_2f | integer |
| nombre_tipo_animal_2f | character |
| longitud | numeric |
| latitud | numeric |
| geom | character |
| dia_semana | integer |
| nombre_dia_semana | character |
| parte_dia | character |
| luna | integer |
| prec | numeric |
| tmin | numeric |
| tmax | numeric |
| sol | numeric |
| uso_suelo | character |
| altitud | numeric |
| pendiente | numeric |
| taxonkey | character |
| tipo_dia | character |
| tmed | numeric |
| imd_total | numeric |
| maxspeed | integer |
Para facilitar el análisis, se modifica el tipo de datos de las variables en función de su contenido, puesto que se conoce porque ya que se ha trabajado cada una de ellas en la fase de captura, obtención y gestión de los datos:
accidentes <- accidentes.raw %>%
dplyr::mutate(ind_accda = as.factor(ind_accda),
nombre_ind_accd = as.factor(nombre_ind_accd),
ind_acciv = as.factor(ind_acciv),
nombre_ind_acciv = as.factor(nombre_ind_acciv),
mes_1f = as.factor(mes_1f),
nombre_mes = as.factor(nombre_mes),
anyo = as.factor(anyo),
ccaa_1f = as.factor(ccaa_1f),
nombre_ccaa = as.factor(nombre_ccaa),
provincia_1f = as.factor(provincia_1f),
nombre_provincia = as.factor(nombre_provincia),
cod_municipio = as.factor(cod_municipio ),
nombre_municipio = as.factor(nombre_municipio),
sentido_1f = as.factor(sentido_1f),
nombre_sentido = as.factor(nombre_sentido),
tipo_via_3f = as.factor(tipo_via_3f),
nombre_tipo_via = as.factor(nombre_tipo_via),
titularidad_via_2f = as.factor(titularidad_via_2f),
nombre_titularidad_via = as.factor(nombre_titularidad_via),
tipo_animal_1f = as.factor(tipo_animal_1f),
nombre_tipo_animal_1f = as.factor(nombre_tipo_animal_1f),
tipo_animal_2f = as.factor(tipo_animal_2f),
nombre_tipo_animal_2f = as.factor(nombre_tipo_animal_2f),
dia_semana = as.factor(dia_semana),
nombre_dia_semana = as.factor(nombre_dia_semana),
parte_dia = as.factor(parte_dia),
uso_suelo = as.factor(uso_suelo),
taxonkey = as.factor(taxonkey),
tipo_dia = as.factor(tipo_dia),
maxspeed = as.factor(maxspeed))
accidentes[sample(nrow(accidentes), 5), ]Se examinan los datos resumen de cada variable del dataset:
options(knitr.kable.NA = '')
kable(summary(accidentes),
digits=2,
align='l',
caption="Datos resumen de cada tipo de variable") %>%
kable_styling(bootstrap_options = Form.Basic) %>%
scroll_box(width = "100%", height = "470px")| id_num | ind_accda | nombre_ind_accd | ind_acciv | nombre_ind_acciv | total_mu30df | total_hg30df | total_hl30df | fecha_accidente | hora_accidente | mes_1f | nombre_mes | anyo | ccaa_1f | nombre_ccaa | provincia_1f | nombre_provincia | cod_municipio | nombre_municipio | carretera | km | sentido_1f | nombre_sentido | tipo_via_3f | nombre_tipo_via | titularidad_via_2f | nombre_titularidad_via | tipo_animal_1f | nombre_tipo_animal_1f | tipo_animal_2f | nombre_tipo_animal_2f | longitud | latitud | geom | dia_semana | nombre_dia_semana | parte_dia | luna | prec | tmin | tmax | sol | uso_suelo | altitud | pendiente | taxonkey | tipo_dia | tmed | imd_total | maxspeed | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Min. :201602000001 | 0: 3173 | Accidente de daños materiales exclusivamente:162279 | 0:162279 | Accidente con víctimas exclusivamente : 3173 | Min. :0 | Min. :0 | Min. : 0 | Min. :2016-01-01 | Length:165452 | 11 :19517 | Noviembre :19517 | 2016:22630 | 8 :58854 | Castilla y León :58854 | 9 : 14080 | Burgos : 14080 | 0 :114159 | Lugo : 967 | Length:165452 | Min. : 0 | 1:84710 | Ambos : 3112 | 1: 22296 | Autopista y autovía : 22296 | 1 :55681 | Autonómica :81882 | 8 :65713 | Jabalí :65713 | 0: 4013 | Animal no identificado: 4013 | Min. :-18 | Min. :28 | Length:165452 | 1:23996 | Domingo :26183 | Amanecer :12249 | Min. : 0 | Min. : 0 | Min. :-18 | Min. : 0 | Min. : 0 | Cultivos :111166 | Min. :-999 | Min. :-9999 | 7705930:65856 | Diario:115522 | Min. :-7 | Min. : 0 | 80 :58909 | |
| 1st Qu.:201734040999 | 1:162279 | No es un accidente de daños exclusivamente : 3173 | 1: 3173 | No es un accidente con víctimas exclusivamente:162279 | 1st Qu.:0 | 1st Qu.:0 | 1st Qu.: 0 | 1st Qu.:2017-10-18 | Class :character | 12 :18257 | Diciembre :18257 | 2017:26358 | 12 :28303 | Galicia :28303 | 24 : 11478 | León : 11478 | 27028 : 967 | Siero : 709 | Class :character | 1st Qu.: 6 | 2:77573 | Ascendente :84710 | 2:143156 | Resto vías interurbanas:143156 | 2 :81882 | Estatal :55681 | 5 :49684 | Corzo :49684 | 1:134555 | Doméstico : 26884 | 1st Qu.: -6 | 1st Qu.:40 | Class :character | 2:22207 | Jueves :22534 | Anochecer:16731 | 1st Qu.: 17 | 1st Qu.: 0 | 1st Qu.: 3 | 1st Qu.:14 | 1st Qu.: 0 | Monte desarbolado : 15165 | 1st Qu.: 418 | 1st Qu.: 1 | 5220126:49684 | Finde : 49930 | 1st Qu.: 9 | 1st Qu.: 2316 | 120 :47267 | |
| Median :201913082360 | Median :0 | Median :0 | Median : 0 | Median :2019-03-28 | Mode :character | 10 :17448 | Octubre :17448 | 2018:27520 | 7 :16808 | Castilla-La Mancha:16808 | 27 : 9898 | Lugo : 9898 | 33066 : 709 | Vilalba : 708 | Mode :character | Median : 22 | 3: 3112 | Descendente :77573 | 3 :24092 | Municipal : 3063 | 20 :21023 | Canino :21023 | 2: 26884 | Silvestre :134555 | Median : -4 | Median :42 | Mode :character | 3:22085 | Lunes :23996 | Día :32651 | Median : 55 | Median : 0 | Median : 8 | Median :19 | Median : 4 | Monte arbolado : 13946 | Median : 736 | Median : 3 | :27175 | Median :13 | Median : 6678 | 90 :37278 | ||||||||
| Mean :201892557704 | Mean :0 | Mean :0 | Mean : 0 | Mean :2019-03-16 | 8 :13908 | Agosto :13908 | 2019:29271 | 2 :13168 | Aragón :13168 | 42 : 7928 | Soria : 7928 | 27065 : 708 | Soria : 514 | Mean : 95 | 4: 57 | Se desconoce: 57 | 4 : 3063 | Otra : 733 | 3 : 7870 | Ciervo : 7870 | Mean : -4 | Mean :41 | 4:22534 | Martes :22207 | Noche :95463 | Mean : 52 | Mean : 2 | Mean : 8 | Mean :20 | Mean : 5 | Artificial : 6477 | Mean : 669 | Mean :-2004 | 2440958: 7870 | Mean :14 | Mean : 11201 | 100 : 9760 | |||||||||||||
| 3rd Qu.:202033123921 | 3rd Qu.:0 | 3rd Qu.:0 | 3rd Qu.: 0 | 3rd Qu.:2020-09-25 | 1 :13708 | Enero :13708 | 2020:27683 | 1 :12155 | Andalucía :12155 | 32 : 7789 | Ourense: 7789 | 42173 : 514 | Monforte de Lemos: 426 | 3rd Qu.: 101 | 5 : 733 | Provincial, Cabildo/Consell:24092 | 17 : 5102 | Zorro : 5102 | 3rd Qu.: -3 | 3rd Qu.:43 | 5:24700 | Miércoles:22085 | NA’s : 8358 | 3rd Qu.: 88 | 3rd Qu.: 0 | 3rd Qu.: 12 | 3rd Qu.:26 | 3rd Qu.: 9 | Monte arbolado de plantación: 3294 | 3rd Qu.: 937 | 3rd Qu.: 10 | 5219243: 5102 | 3rd Qu.:19 | 3rd Qu.: 15000 | 50 : 1294 | |||||||||||||||
| Max. :202151165311 | Max. :2 | Max. :4 | Max. :21 | Max. :2021-12-31 | 9 :13673 | Septiembre:13673 | 2021:31990 | 10 : 7309 | Extremadura : 7309 | 49 : 6738 | Zamora : 6738 | (Other): 48394 | (Other) : 47870 | Max. :9999 | 99: 1 | NA’s : 1 | 0 : 4013 | Animal no identificado: 4013 | Max. : 4 | Max. :44 | 6:23747 | Sábado :23747 | Max. :100 | Max. :136 | Max. : 30 | Max. :45 | Max. :15 | (Other) : 7046 | Max. :3270 | Max. : 60 | 2433875: 1902 | Max. :36 | Max. :286799 | (Other): 2586 | ||||||||||||||||
| (Other):68941 | (Other) :68941 | (Other):28855 | (Other) :28855 | (Other):107541 | (Other):107541 | NA’s : 1 | NA’s :114258 | (Other):12047 | (Other) :12047 | NA’s :8358 | NA’s :8358 | 7:26183 | Viernes :24700 | NA’s :69989 | NA’s :13998 | NA’s :13998 | NA’s :13998 | NA’s :13998 | NA’s : 8358 | NA’s :10125 | NA’s :8358 | (Other): 7863 | NA’s :13998 | NA’s :8358 | NA’s : 8358 |
En primer lugar, se verifica que no existen registros duplicados:
accidentes[duplicated(accidentes$id_num),]Se comprueba que, efectivamente, todos los id_num son
diferentes:
length(unique(accidentes$id_num)) == dim(accidentes)[1]## [1] TRUE
Durante la fase de integración de datos se importaron nulos
señalizados como en las fuentes originales de otro modo. Es el caso de
la altitud y de la pendiente, como se observa
a continuación:
min(accidentes$altitud, na.rm = TRUE)## [1] -999
min(accidentes$pendiente, na.rm = TRUE)## [1] -9999
Por tanto, se imputan esos valores como NA y se verifica que han desaparecido esos valores extremos:
# Se imputan los nulos
accidentes["altitud"][accidentes["altitud"] == -999] <- NA
accidentes["pendiente"][accidentes["pendiente"] == -9999] <- NA
# Se verifica la imputación
min(accidentes$altitud, na.rm = TRUE)## [1] -1.8
min(accidentes$pendiente, na.rm = TRUE)## [1] 0
Se comprueba cuántos valores ausentes hay en cada variable:
kable(colSums(is.na(accidentes)),
digits=2,
align='l',
caption="Valores nulos en cada variable") %>%
kable_styling(bootstrap_options = Form.Basic) %>%
scroll_box(width = "100%", height = "470px")| x | |
|---|---|
| id_num | 0 |
| ind_accda | 0 |
| nombre_ind_accd | 0 |
| ind_acciv | 0 |
| nombre_ind_acciv | 0 |
| total_mu30df | 0 |
| total_hg30df | 0 |
| total_hl30df | 0 |
| fecha_accidente | 0 |
| hora_accidente | 0 |
| mes_1f | 0 |
| nombre_mes | 0 |
| anyo | 0 |
| ccaa_1f | 0 |
| nombre_ccaa | 0 |
| provincia_1f | 0 |
| nombre_provincia | 0 |
| cod_municipio | 1 |
| nombre_municipio | 114258 |
| carretera | 0 |
| km | 0 |
| sentido_1f | 0 |
| nombre_sentido | 0 |
| tipo_via_3f | 0 |
| nombre_tipo_via | 0 |
| titularidad_via_2f | 0 |
| nombre_titularidad_via | 1 |
| tipo_animal_1f | 0 |
| nombre_tipo_animal_1f | 0 |
| tipo_animal_2f | 0 |
| nombre_tipo_animal_2f | 0 |
| longitud | 8358 |
| latitud | 8358 |
| geom | 8358 |
| dia_semana | 0 |
| nombre_dia_semana | 0 |
| parte_dia | 8358 |
| luna | 69989 |
| prec | 13998 |
| tmin | 13998 |
| tmax | 13998 |
| sol | 13998 |
| uso_suelo | 8358 |
| altitud | 13748 |
| pendiente | 39947 |
| taxonkey | 0 |
| tipo_dia | 0 |
| tmed | 13998 |
| imd_total | 8358 |
| maxspeed | 8358 |
Como sí que hay más columnas con valores ausentes, se estudia la proporción con el objetivo de tomar decisiones en cada caso:
colMeans(is.na(accidentes))## id_num ind_accda nombre_ind_accd
## 0.000000 0.000000 0.000000
## ind_acciv nombre_ind_acciv total_mu30df
## 0.000000 0.000000 0.000000
## total_hg30df total_hl30df fecha_accidente
## 0.000000 0.000000 0.000000
## hora_accidente mes_1f nombre_mes
## 0.000000 0.000000 0.000000
## anyo ccaa_1f nombre_ccaa
## 0.000000 0.000000 0.000000
## provincia_1f nombre_provincia cod_municipio
## 0.000000 0.000000 0.000006
## nombre_municipio carretera km
## 0.690581 0.000000 0.000000
## sentido_1f nombre_sentido tipo_via_3f
## 0.000000 0.000000 0.000000
## nombre_tipo_via titularidad_via_2f nombre_titularidad_via
## 0.000000 0.000000 0.000006
## tipo_animal_1f nombre_tipo_animal_1f tipo_animal_2f
## 0.000000 0.000000 0.000000
## nombre_tipo_animal_2f longitud latitud
## 0.000000 0.050516 0.050516
## geom dia_semana nombre_dia_semana
## 0.050516 0.000000 0.000000
## parte_dia luna prec
## 0.050516 0.423017 0.084605
## tmin tmax sol
## 0.084605 0.084605 0.084605
## uso_suelo altitud pendiente
## 0.050516 0.083094 0.241442
## taxonkey tipo_dia tmed
## 0.000000 0.000000 0.084605
## imd_total maxspeed
## 0.050516 0.050516
Los únicos registros que no se pueden emplear para el desarrollo del
modelo de predicción son aquellos que no contienen la información de
longitud, latitud y geom, puesto
que se trata de la información espacial esencial. Como
se trata solo del 5% del conjunto de datos, se decide
eliminarlos porque esta acción no distorsiona el
análisis y permite optimizar los procesos en futuras fases:
accidentes <- accidentes %>% drop_na(geom)Como muchos campos dependían para su cálculo de la ubicación del accidente, es probable que la proporción de nulos haya bajado en el conjunto de datos completo, por lo que se vuelve a comprobar:
colMeans(is.na(accidentes))## id_num ind_accda nombre_ind_accd
## 0.0000000 0.0000000 0.0000000
## ind_acciv nombre_ind_acciv total_mu30df
## 0.0000000 0.0000000 0.0000000
## total_hg30df total_hl30df fecha_accidente
## 0.0000000 0.0000000 0.0000000
## hora_accidente mes_1f nombre_mes
## 0.0000000 0.0000000 0.0000000
## anyo ccaa_1f nombre_ccaa
## 0.0000000 0.0000000 0.0000000
## provincia_1f nombre_provincia cod_municipio
## 0.0000000 0.0000000 0.0000064
## nombre_municipio carretera km
## 0.6942913 0.0000000 0.0000000
## sentido_1f nombre_sentido tipo_via_3f
## 0.0000000 0.0000000 0.0000000
## nombre_tipo_via titularidad_via_2f nombre_titularidad_via
## 0.0000000 0.0000000 0.0000064
## tipo_animal_1f nombre_tipo_animal_1f tipo_animal_2f
## 0.0000000 0.0000000 0.0000000
## nombre_tipo_animal_2f longitud latitud
## 0.0000000 0.0000000 0.0000000
## geom dia_semana nombre_dia_semana
## 0.0000000 0.0000000 0.0000000
## parte_dia luna prec
## 0.0000000 0.3923192 0.0359021
## tmin tmax sol
## 0.0359021 0.0359021 0.0359021
## uso_suelo altitud pendiente
## 0.0000000 0.0343107 0.2010834
## taxonkey tipo_dia tmed
## 0.0000000 0.0000000 0.0359021
## imd_total maxspeed
## 0.0000000 0.0000000
Efecitvamente, la cantidad de nulos ha bajado, y se toma la decisión de mantener el resto de registros por:
nombre_municipio: a pesar del 69% de
nulos se trata de una información espacial genérica si se compara con la
longitudy latitud o el geom, por
lo que no afecta porque realmente no se empleará.nombre_titularidad_via y
cod_municipio: 0.00064% es una proporción
despreciable.prec,
tmin, tmed,
tmax y sol:
son datos meteorológicos que podrían llegar a ayudar en el análisis y
predicción, pero su ausencia no compromete el proyecto además de
tratarse solo de un 3.59% de los registros.luna: el campo es nulo cuando no se
calcula su valor porque el accidente no ha ocurrido por la noche, por lo
que incluso ser nulo aporta información relevante.pendiente y
altitud: es información proporcionada por
el Centro Nacional de Información Geográfica (CNIG) y el valor es nulo
simplemente porque no se ha documentado dicha información para esa
localización. Su ausencia tampoco compromete la viabilidad del
proyecto.A continuación, se analizan los posibles valores extremos o outliers que pueden tomar las variables cuantitativas, adoptando la estrategia que mejor se adapta a cada una de ellas. En este sentido, cabe destacar que todo apunta a que no habrá valores extremos según los datos que ha arrojado el análisis de los datos resumen de cada tipo de variable realizado en la introducción.
Los atributos total_mu30df,
total_hg30df y
total_hl30df son totalizadores que indican
el número de fallecidos, heridos hospitalizados y no hospitalizados,
respectivamente, en un cómputo de 30 días para cada uno de los
accidentes. Por ello, se evalúa que el valor no sea menor que 0 porque
no sería posible y se estudia el máximo para valorar si se trata de un
error o no. El mismo proceso de comprobación se hace con las variables
altitud,
pendiente y
imd_total debido a que se desconoce su
dominio exacto, pero por el conocimiento del campo sí que se puede
evaluar si el rango es plausible:
var_cuant <- c('total_mu30df',
'total_hg30df',
'total_hl30df',
'altitud',
'pendiente',
'imd_total')
min.cuant <- as.vector(sapply(accidentes[, var_cuant], min,na.rm = TRUE))
max.cuant <- as.vector(sapply(accidentes[, var_cuant], max,na.rm = TRUE))
kable(data.frame(Variables= names(accidentes[, var_cuant]),
min = min.cuant,
max = max.cuant),
digits=2, caption="Mínimo y máximo") %>%
kable_styling(bootstrap_options = Form.Basic)| Variables | min | max |
|---|---|---|
| total_mu30df | 0.0 | 2 |
| total_hg30df | 0.0 | 4 |
| total_hl30df | 0.0 | 21 |
| altitud | -1.8 | 3270 |
| pendiente | 0.0 | 60 |
| imd_total | 0.0 | 286799 |
A la vista de los resultados en los totalizadores, no se puede
considerar que haya ningún outlier que deba
ser tratado puesto que el valor más alto es el de heridos no
hospitalizados, que en, al menos, un accidente asciende a 21. Debido a
que la altitud máxima de España es de 3.715 metros y que también hay
zonas ligeramente por debajo del nivel del mar, la latitud también se
puede considerar dentro de valores normales. Las variables
pendiente e imd_total, asimismo, se encuentran
dentro de rangos esperables.
En cuanto a las temperaturas registradas el día del
accidente, se decide comparar los boxplots interactivos de
tmin, tmed y
tmax, de manera que se puede consultar
directamente el valor de los valores extremos:
fig <- plot_ly(y = accidentes$tmin, type = "box", name="Temperatura mínima")
fig <- fig %>% add_trace(y = accidentes$tmed, name="Temperatura media")
fig <- fig %>% add_trace(y = accidentes$tmax, name="Temperatura máxima")
fig <- fig %>% layout(title = "Datos de temperaturas", yaxis = list(title = 'Grados celsius'))
figComo el alcance del proyecto es el territorio español, estos datos coinciden con las temperaturas registradas en España en los últimos años, a pesar de que las cálidas parezcan muy altas, puesto que han sido los años más extremos de la serie histórica. Del mismo modo, las temperaturas mínimas se acercan a los récords registrados desde 2016, por lo que no hay motivos para sospechar que se trate de datos erróneos.
Por su parte, los valores de prec y
sol se analizan en dos diagramas de caja
diferentes puesto que no comparten medida, aunque también son
interactivos para consultar el valor de los outliers:
fig1 <- plot_ly(y = accidentes$prec, type = "box", name="Lluvia diaria (mm)")
fig2 <- plot_ly(y = accidentes$sol, type = "box", name="Horas de sol al día")
fig <- subplot(fig1, fig2) %>%
layout(title = 'Meteorología diaria')
figAl igual que ocurre con la temperatura, los valores mínimos de sol y lluvia son 0, por lo que no hay errores en ese sentido, y los máximos de lluvia pueden encontrar explicación en las precipitaciones torrenciales que se han dado en varios momentos en los últimos años.
La carretera N-340 es la más larga de España y tiene una extensión de
1248 kilómetros, por lo que se comprueba si el atributo
km cumple la condición de que no haya
ningún kilómetro con un valor mayor que este ni menor que 0, puesto que
la normativa marca que deben ser positivos.
if (all(between(accidentes$km, 0, 1248), na.rm = TRUE) == TRUE){
print("Todos los valores no nulos de km están dentro del dominio [0, 1248]")}## [1] "Todos los valores no nulos de km están dentro del dominio [0, 1248]"
En cuanto a la variable luna, ese campo
recoge la superficie de la luna iluminada, siendo 0 luna nueva y 100
luna llena, por lo que se verifica que no haya ningún valor fuera de
este rango:
if (all(between(accidentes$luna, 0, 100), na.rm = TRUE) == TRUE){
print("Todos los valores no nulos de luna tienen el dominio [0, 100]")}## [1] "Todos los valores no nulos de luna tienen el dominio [0, 100]"
Del mismo modo, se comprueba que todos los registros estén dentro de
la longitud y
latitud de España:
latitud_range <- all(between(accidentes$latitud,27.5,43.78333333333333), na.rm = TRUE)
longitud_range <- all(between(accidentes$longitud,-18.15, 4.316666666666666), na.rm = TRUE)
if (latitud_range == TRUE & longitud_range == TRUE){
print("Todos los valores de longitud y latitud están dentro de España")}## [1] "Todos los valores de longitud y latitud están dentro de España"
Por tanto, se puede considerar que no existen valores extremos que deban ser tratados.
Para verificar los datos, se adoptan dos estrategias diferentes. Por un lado, en aquellas variables que puedan tomar muchos valores y se conozca cuántos, se opta por comprobar el total, puesto que mirar todos los nombres puede llevar a confusión y a pasar errores por alto. Por el otro, aquellas variables con menos opciones de clasificación, se muestran y comprueban que los niveles son correctos. En cualquier caso, no se prevén fallos puesto que en cada fase de obtención e integración de los datos se ha realizado un control exhaustivo de los mismos.
En primer lugar, se trabaja con las variables con más niveles:
var_cual <- c('mes_1f',
'nombre_mes',
'ccaa_1f',
'nombre_ccaa',
'provincia_1f',
'nombre_provincia',
'cod_municipio',
'nombre_municipio',
'dia_semana',
'nombre_dia_semana')
num.levels <- as.vector(sapply(accidentes[, var_cual], levels))
kable(data.frame(Variables= names(accidentes[, var_cual]),
total_levels = lengths(num.levels)),
digits=1, caption="Total de niveles de cada variable") %>%
kable_styling(bootstrap_options = Form.Basic)| Variables | total_levels | |
|---|---|---|
| mes_1f | mes_1f | 12 |
| nombre_mes | nombre_mes | 12 |
| ccaa_1f | ccaa_1f | 16 |
| nombre_ccaa | nombre_ccaa | 16 |
| provincia_1f | provincia_1f | 44 |
| nombre_provincia | nombre_provincia | 44 |
| cod_municipio | cod_municipio | 1007 |
| nombre_municipio | nombre_municipio | 1002 |
| dia_semana | dia_semana | 7 |
| nombre_dia_semana | nombre_dia_semana | 7 |
Todos los datos están correctos, porque hay menos comunidades autónomas, provincias y municipios en total ya que, o bien no se han registrado accidentes con animales en ellos (en alguna localidad) o no hay datos para esa región (como Cataluña).
En cuanto a las variables con menos niveles o que no se conoce de antemano el total que debe dar como correcto pero sí que se conoce la clasificación que debe dar como resultado, se muestran tanto las codificadas como las decodificadas y se verifica que todo sea correcto:
levels(accidentes$ind_accda)## [1] "0" "1"
levels(accidentes$nombre_ind_accd)## [1] "Accidente de daños materiales exclusivamente"
## [2] "No es un accidente de daños exclusivamente"
levels(accidentes$ind_acciv)## [1] "0" "1"
levels(accidentes$nombre_ind_acciv)## [1] "Accidente con víctimas exclusivamente"
## [2] "No es un accidente con víctimas exclusivamente"
levels(accidentes$anyo)## [1] "2016" "2017" "2018" "2019" "2020" "2021"
levels(accidentes$sentido_1f)## [1] "1" "2" "3" "4"
levels(accidentes$nombre_sentido)## [1] "Ambos" "Ascendente" "Descendente" "Se desconoce"
levels(accidentes$tipo_via_3f)## [1] "1" "2"
levels(accidentes$nombre_tipo_via)## [1] "Autopista y autovía" "Resto vías interurbanas"
levels(accidentes$titularidad_via_2f)## [1] "1" "2" "3" "4" "5" "99"
levels(accidentes$nombre_titularidad_via)## [1] "Autonómica" "Estatal"
## [3] "Municipal" "Otra"
## [5] "Provincial, Cabildo/Consell"
levels(accidentes$tipo_animal_1f)## [1] "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12" "13" "14"
## [16] "15" "16" "17" "18" "19" "20" "21" "22" "23" "24" "25" "26" "27"
levels(accidentes$nombre_tipo_animal_1f)## [1] "Animal no identificado" "Ave" "Cabra montés"
## [4] "Canino" "Caprino" "Ciervo"
## [7] "Conejo" "Corzo" "Equino"
## [10] "Felino" "Gamo" "Gato montés"
## [13] "Jabalí" "Liebre" "Lince ibérico"
## [16] "Lobo" "Muflón" "Nutria"
## [19] "Oso pardo" "Otro animal" "Ovino"
## [22] "Porcino" "Rebeco" "Tejón"
## [25] "Vacuno" "Zorro"
levels(accidentes$taxonkey)## [1] "" "2433433" "2433875" "2435035" "2435261"
## [6] "2436691" "2436940" "2440886\r\n" "2440958" "2441022"
## [11] "2441054" "2441056" "2441110" "2441116" "5219173"
## [16] "5219243" "5220126" "5220136" "5220170" "7705930"
## [21] "7964291"
levels(accidentes$tipo_animal_2f)## [1] "0" "1" "2"
levels(accidentes$nombre_tipo_animal_2f)## [1] "Animal no identificado" "Doméstico" "Silvestre"
levels(accidentes$parte_dia)## [1] "Amanecer" "Anochecer" "Día" "Noche"
levels(accidentes$tipo_dia)## [1] "Diario" "Finde"
levels(accidentes$uso_suelo)## [1] "Agua"
## [2] "Artificial"
## [3] "Cultivos"
## [4] "Humedal"
## [5] "Monte arbolado"
## [6] "Monte arbolado adehesado"
## [7] "Monte arbolado de plantación"
## [8] "Monte con arbolado disperso"
## [9] "Monte con arbolado disperso de dehesa"
## [10] "Monte con arbolado disperso de plantación"
## [11] "Monte con arbolado ralo"
## [12] "Monte con arbolado ralo de dehesa"
## [13] "Monte con arbolado ralo de plantación"
## [14] "Monte desarbolado"
levels(accidentes$maxspeed)## [1] "20" "30" "40" "48" "50" "60" "70" "80" "90" "100" "120"
Se detecta un fallo en la variable taxonkey producto
posiblemente de la inclusión de un retorno al crear la tabla auxiliar
aux_tipo_animal_1fque se encuentra en la base de datos
tfmy permitió decodificar esta variable. Por ello, se
sustituye por el valor adecuado y se verifica que se haya producido el
cambio:
levels(accidentes$taxonkey) <- sub("^2440886\r\n$", "2440886", levels(accidentes$taxonkey))
levels(accidentes$taxonkey)## [1] "" "2433433" "2433875" "2435035" "2435261" "2436691" "2436940"
## [8] "2440886" "2440958" "2441022" "2441054" "2441056" "2441110" "2441116"
## [15] "5219173" "5219243" "5220126" "5220136" "5220170" "7705930" "7964291"
Por último, en España no existe posibilidad de que la velocidad
máxima en ninguna vía sea de 48 kilómetros por hora, por lo que se
ajusta ese nivel y se homogeniza en 50 en la variable
maxspeed:
levels(accidentes$maxspeed) <- sub("^48$", "50", levels(accidentes$maxspeed))
levels(accidentes$maxspeed)## [1] "20" "30" "40" "50" "60" "70" "80" "90" "100" "120"
Tras acabar la fase de procesado de los datos y con todos ellos en los formatos correctos, en este apartado se realiza un análisis del conjunto de datos final, con el que se trabajarán los modelos.
Debido a que todas las variables contienen muchas más de 30 observaciones, se considera que su tamaño es lo suficientemente grande como para asumir normalidad aplicando el teorema del límite central (TLC).
Sin embargo, con el objetivo de afinar todos los cálculos al máximo,
se decide evaluar cada una de las variables numéricas, descartando la
longitudy latitud:
var_cuant <- list(accidentes$total_mu30df,
accidentes$total_hg30df,
accidentes$total_hl30df,
accidentes$altitud,
accidentes$pendiente,
accidentes$tmin,
accidentes$tmed,
accidentes$tmax,
accidentes$prec,
accidentes$sol,
accidentes$luna,
accidentes$imd_total)var_cuant_names <- c( substitute(total_mu30df),
substitute(total_hg30df),
substitute(total_hl30df),
substitute(altitud),
substitute(pendiente),
substitute(tmin),
substitute(tmed),
substitute(tmax),
substitute(prec),
substitute(sol),
substitute(luna),
substitute(maxspeed),
substitute(imd_total))line2user <- function(line, side) {
lh <- par('cin')[2] * par('cex') * par('lheight')
x_off <- diff(grconvertX(0:1, 'inches', 'user'))
y_off <- diff(grconvertY(0:1, 'inches', 'user'))
switch(side,
`1` = par('usr')[3] - line * y_off * lh,
`2` = par('usr')[1] - line * x_off * lh,
`3` = par('usr')[4] + line * y_off * lh,
`4` = par('usr')[2] + line * x_off * lh,
stop("side must be 1, 2, 3, or 4", call.=FALSE))
}par(mfrow=c(1,2))
i <- 1
for (var in var_cuant){
plot(density(na.omit(var)),
main= "Densidad",
col = "#69b3a2",
lwd = 2)
qqnorm(var,
main = "Normal Q-Q plot",
col = "azure4",
xlab="Cuantiles teóricos",
ylab="Cuantiles de la muestra")
qqline(var,
col = "red",
lwd = 1)
#mtext(var_cuant_names[[i]], side = 3, line = 21, outer = TRUE)
#text(0.1, 0.1, var_cuant_names[[i]],cex=2,font=2)
text(line2user(line=mean(par('mar')[c(2, 4)]), side=2),
line2user(line=2, side=3), var_cuant_names[[i]], xpd=NA, cex=1.7, font=2)
i <- i + 1}A la luz de estos gráficos, parece que ninguna variable tiene una distribución normal, aunque existen dudas sobre algunas de ellas. Por ello, se realiza el contraste de normalidad de Lilliefors, para lo que se plantean primero la hipótesis nula y la hipótesis alternativa:
\(H_0\): Variable \(=\) distribución normal
\(H_1\): Variable \(\neq\) distribución normal
i <- 1
vec_names = c()
vec_values = c()
for (var in var_cuant){
vec_names <- append(vec_names, var_cuant_names[i])
vec_values <- append(vec_values, format(lillie.test(var)$p.value, scientific=TRUE))
#cat(paste0(var_cuant_names[[i]]),":",(format(lillie.test(var)$p.value, scientific=TRUE)),"\n")
i <- i+1
}
vec_names <- unlist(vec_names)
vec_names <- as.vector(vec_names,'character')
kable(data.frame(vec_names, vec_values),
align='l',
caption="P-value de cada variable en el test de Lilliefors") %>%
kable_styling(bootstrap_options = Form.Basic) %>%
scroll_box(width = "100%", height = "470px")| vec_names | vec_values |
|---|---|
| total_mu30df | 0e+00 |
| total_hg30df | 0e+00 |
| total_hl30df | 0e+00 |
| altitud | 0e+00 |
| pendiente | 0e+00 |
| tmin | 9.3e-272 |
| tmed | 0e+00 |
| tmax | 0e+00 |
| prec | 0e+00 |
| sol | 0e+00 |
| luna | 0e+00 |
| maxspeed | 0e+00 |
Debido a que el p-value es muy inferior \(\alpha = 0.05\) en todos los casos, se rechaza la hipótesis nula y se concluye que ninguna variable procede de una distribución normal. El resultado de este test coincide con la conclusión de la inspección visual.
Como, de momento, no se están comparando muestras, no se realiza ningún test de homocedasticidad, por lo que se pasa directamente al análisis de la correlación entre las diferentes variables numéricas.
Se utiliza el coeficiente de correlación de Spearman, dado que se trata de un test no paramétrico y es más adecuado para los datos a analizar debido a que no siguen una distribución normal. Sin embargo, también se van a realizar las pruebas con el coeficiente de correlación de Pearson, ya que se puede aplicar el teorema del límite central (TLC) sobre la muestra al tener un tamaño suficientemente grande.
Se crea un dataframe únicamente con las variables cuantitativas a analizar y se muestra el correlograma de los cálculos, siempre teniendo en cuenta que correlación no tiene por qué implicar causalidad:
corr_cuant <- accidentes %>% dplyr::select(total_mu30df,
total_hg30df,
total_hl30df,
altitud,
pendiente,
imd_total,
tmin,
tmed,
tmax,
prec,
sol,
luna) %>%
dplyr::rename(mu30df=total_mu30df,
hg30df=total_hg30df,
hl30df=total_hl30df,
imd = imd_total)#fig.height = 3, fig.width = 3
# low = "steelblue", mid = "white", high = "darkred"
spearman <- ggcorr(corr_cuant,
method=c('complete.obs', 'spearman'),
name='Corr. coef.',
label=TRUE,
label_alpha=TRUE,
legend.position='left',
layout.exp = 1,
hjust = 0.8,
size = 4,
limits = c(-1, 1)) +
title.centered + ggtitle('Matriz de correlaciones (Spearman)') +
theme(legend.title=element_text(face='bold', size=10))
spearmanspearman <- ggcorr(corr_cuant,
method=c('complete.obs', 'pearson'),
name='Corr. coef.',
label=TRUE,
label_alpha=TRUE,
legend.position='left',
layout.exp = 1,
hjust = 0.8,
size = 4,
limits = c(-1, 1)) +
title.centered + ggtitle('Matriz de correlaciones (Pearson)') +
theme(legend.title=element_text(face='bold', size=10))
spearmanLas diferencias que se aprecian entre ambos correlogramas son
insignificantes, por lo que se puede llegar a las mismas conclusiones.
Las variables de temperatura tmin,
tmed y tmax altamente correlacionadas
de forma positiva, por lo que no podrán ser introducidas las tres en los
modelos de forma simultánea. Este resultado era esperable, sobre todo el
de tmed puesto que es resultado de una combinación lineal
de las otras dos. Para verificar esta premisa, se comprueba mediante un
test que dicha correlación sea significativa con un nivel de
significancia de \(\alpha = 0.05\):
# Test
tmin.tmed.spearman <- cor.test(corr_cuant$tmin, corr_cuant$tmed, method='spearman')
tmin.tmed.pearson <- cor.test(corr_cuant$tmin, corr_cuant$tmed, method='pearson')
tmin.tmax.spearman <-cor.test(corr_cuant$tmin, corr_cuant$tmax, method='spearman')
tmin.tmax.pearson <- cor.test(corr_cuant$tmin, corr_cuant$tmax, method='pearson')
tmed.tmax.spearman <-cor.test(corr_cuant$tmed, corr_cuant$tmax, method='spearman')
tmed.tmax.pearson <- cor.test(corr_cuant$tmed, corr_cuant$tmax, method='pearson')
# Tabla de resultados
results.table <- data.frame(Variables = c("tmin y tmed",
"tmin y tmax",
"tmed y tmax"),
Correlación.Pearson = c(tmin.tmed.pearson$estimate,
tmin.tmax.pearson$estimate,
tmed.tmax.pearson$estimate),
Pvalue.Pearson = c(format(tmin.tmed.pearson$p.value, scientific = TRUE),
format(tmin.tmax.pearson$p.value,scientific = TRUE),
format(tmed.tmax.pearson$p.value,scientific = TRUE)),
Correlación.Spearman = c(tmin.tmed.spearman$estimate,
tmin.tmax.spearman$estimate,
tmed.tmax.spearman$estimate),
Pvalue.Spearman = c(format(tmin.tmed.spearman$p.value,scientific = TRUE),
format(tmin.tmax.spearman$p.value, scientific = TRUE),
format(tmed.tmax.spearman$p.value,scientific = TRUE)))
results.table %>%
kable() %>%
kable_styling(bootstrap_options = Form.Basic) %>%
kableExtra::scroll_box(width = "100%")| Variables | Correlación.Pearson | Pvalue.Pearson | Correlación.Spearman | Pvalue.Spearman |
|---|---|---|---|---|
| tmin y tmed | 0.93 | 0e+00 | 0.93 | 0e+00 |
| tmin y tmax | 0.78 | 0e+00 | 0.77 | 0e+00 |
| tmed y tmax | 0.96 | 0e+00 | 0.95 | 0e+00 |
De este modo, se verifica que la correlación entre las tres variables analizadas en profundidad es estadísticamente significativa, positiva y alta.
Otra conclusión sorprendente es que no se encuentran
correlaciones fuertes entre variables que la intuición podría
haber señalado erróneamente. Por ejemplo, entre la velocidad máxima
(maxspeed) y el número de fallecidos o heridos.
Como una primera aproximación a las características de los accidentes, se estudia su frecuencia, para lo que la inspección visual sirve de apoyo. En primer lugar se realiza un histograma por cada una de las variables continuas:
par(mfrow=c(3,2))
tmin_freq <- ggplot(accidentes, aes(y = tmin)) +
ggtitle("tmin") +
theme(plot.title = element_text(hjust = 0.5)) +
geom_bar(fill = "darkorchid4", col="darkorchid1") +
xlab(" ") +
ylab("Grados celsius") +
coord_flip()
tmed_freq <- ggplot(accidentes, aes(y = tmed)) +
ggtitle("tmed") +
theme(plot.title = element_text(hjust = 0.5)) +
geom_bar(fill = "seagreen3", col="seagreen4") +
ylab("Grados celsius") +
xlab(" ") +
coord_flip()
tmax_freq <- ggplot(accidentes, aes(y = tmax)) +
theme(plot.title = element_text(hjust = 0.5)) +
ggtitle("tmax") +
geom_bar(fill = "tomato2", col="tomato4") +
ylab("Grados celsius") +
xlab(" ") +
coord_flip()
grid.arrange(tmin_freq,
tmed_freq,
tmax_freq,
nrow = 1,
top = "Frecuencia de las temperaturas",
left="Frecuencia")prec_freq <- ggplot(accidentes, aes(y = prec)) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_bar(fill = "darkorange", col="moccasin") +
ggtitle("Precipitaciones") +
ylab("mm") +
xlab(" ") +
coord_flip()
sol_freq <- ggplot(accidentes, aes(y = sol)) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_bar(fill = "deeppink", col="lightpink") +
ggtitle("Sol") +
ylab("Horas") +
xlab(" ") +
coord_flip()
lun_freq <- ggplot(accidentes, aes(y = luna)) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_bar(fill = "darkcyan", col="powderblue") +
ggtitle("Luna") +
ylab("Superficie iluminada") +
xlab(" ") +
coord_flip()
grid.arrange(prec_freq,
sol_freq,
lun_freq,
nrow = 1,
top = "Otras condiciones meteorológicas y periódicas",
left="Frecuencia")altitud_freq <- ggplot(accidentes, aes(y = altitud)) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_bar(fill = "darkorchid4", col="darkorchid1") +
ggtitle("Altitud") +
ylab("metros") +
xlab(" ") +
coord_flip()
pendiente_freq <- ggplot(accidentes, aes(y = pendiente)) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_bar(fill = "seagreen3", col="seagreen4") +
ggtitle("Pendiente") +
ylab("Metros") +
xlab(" ") +
coord_flip()
imd_freq <- ggplot(accidentes, aes(y = imd_total)) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_bar(fill = "tomato2", col="tomato4") +
ggtitle("IMD") +
ylab("Vehículos") +
xlab(" ") +
coord_flip()
grid.arrange(altitud_freq,
pendiente_freq,
imd_freq,
nrow = 1,
top = "Otras condiciones de la zona del accidente",
left="Frecuencia")mu30_freq <- ggplot(accidentes, aes(y = total_mu30df)) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_bar(fill = "darkorange", col="moccasin") +
ggtitle("Personas muertas") +
ylab("Personas") +
xlab(" ") +
coord_flip()
hg30_freq <- ggplot(accidentes, aes(y = total_hg30df)) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_bar(fill = "deeppink", col="lightpink") +
ggtitle("Personas hospitalizadas") +
ylab("Personas") +
xlab(" ") +
coord_flip()
hl30_freq <- ggplot(accidentes, aes(y = total_hl30df)) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_bar(fill = "darkcyan", col="powderblue") +
ggtitle("Personas no hospitalizadas") +
ylab("Personas") +
xlab(" ") +
coord_flip()
grid.arrange(mu30_freq,
hg30_freq,
hl30_freq,
nrow = 1,
top = "Frecuencia de fallecidos y heridos en 30 días",
left="Frecuencia")
Se pasa al estudio de las variables categóricas, aunque
en la temporalidad y espacialidad se profundizará en
apartados específicos. En el caso de aquellas tengan el valor
decodificado, se opta por analizar la que contiene esa
información para facilitar la interpretabilidad. Además, no se incluye
el análisis de
taxonkey puesto que también es una
decodificación del tipo de animal involucrado en el accidente. Aquellas
variables con más niveles se estudian mediante gráficos de
barras interactivos, que facilitan su interpretación y
selección:
# Tipo animal
freq_animal1 <- ggplot(data.frame(accidentes), aes(x=reorder(nombre_tipo_animal_1f, nombre_tipo_animal_1f,
function(x)-length(x)),
fill = nombre_tipo_animal_1f)) +
ggtitle("Distribución de los accidentes según el tipo de animal") +
xlab("Animal") +
ylab("Número de accidentes") +
theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
scale_color_gradientn(colours = terrain.colors(10)) +
labs(fill='Animal') +
geom_bar()
ggplotly(freq_animal1)# Velocidad máxima
freq_maxspeed <- ggplot(data.frame(accidentes), aes(x = maxspeed,
fill = maxspeed)) +
ggtitle("Distribución de los accidentes según la velocidad máxima") +
xlab("Kilómetros por hora") +
ylab("Número de accidentes") +
theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
scale_fill_brewer(palette = "Set3") +
labs(fill='Velocidad máxima') +
geom_bar()
ggplotly(freq_maxspeed)# Uso suelo
freq_suelo <- ggplot(data.frame(accidentes), aes(x=reorder(uso_suelo, uso_suelo,
function(x)-length(x)),
fill = uso_suelo)) +
ggtitle("Distribución de los accidentes según el uso del suelo") +
xlab("Uso del suelo") +
ylab("Número de accidentes") +
theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
scale_color_gradientn(colours = terrain.colors(10)) +
labs(fill='Uso del suelo') +
geom_bar()
ggplotly(freq_suelo)# Titularidad de la vía
freq_suelo <- ggplot(data.frame(accidentes), aes(x=reorder(nombre_titularidad_via, nombre_titularidad_via,
function(x)-length(x)),
fill = nombre_titularidad_via)) +
ggtitle("Distribución de los accidentes según la titularidad de la vía") +
xlab("Titularidad de la vía") +
ylab("Número de accidentes") +
theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
scale_fill_brewer(palette = "Pastel1") +
labs(fill='Titularidad de la vía') +
geom_bar()
ggplotly(freq_suelo)Como los animales son parte de los protagonistas de este proyecto, se estudia también su frecuencia relativa:
kable(prop.table(table(accidentes$nombre_tipo_animal_1f)),
digits=2,
align='l',
caption="Frecuencia relativa de la parte del día") %>%
kable_styling(bootstrap_options = Form.Basic)| Var1 | Freq |
|---|---|
| Animal no identificado | 0.02 |
| Ave | 0.01 |
| Cabra montés | 0.00 |
| Canino | 0.13 |
| Caprino | 0.00 |
| Ciervo | 0.05 |
| Conejo | 0.00 |
| Corzo | 0.30 |
| Equino | 0.01 |
| Felino | 0.01 |
| Gamo | 0.00 |
| Gato montés | 0.00 |
| Jabalí | 0.40 |
| Liebre | 0.00 |
| Lince ibérico | 0.00 |
| Lobo | 0.00 |
| Muflón | 0.00 |
| Nutria | 0.00 |
| Oso pardo | 0.00 |
| Otro animal | 0.01 |
| Ovino | 0.01 |
| Porcino | 0.00 |
| Rebeco | 0.00 |
| Tejón | 0.01 |
| Vacuno | 0.01 |
| Zorro | 0.03 |
Para aquellas variables categóricas con menos categorías posibles, se opta por comparar su distribución mediante pie charts
freq_accd <- accidentes %>%
group_by(nombre_ind_accd) %>%
dplyr::summarise(n = n()) %>%
ggplot(aes(x = "", y = n, fill = nombre_ind_accd)) +
geom_bar(stat = "identity", width = 2) +
coord_polar("y") +
geom_text(aes(label = n), position = position_stack(vjust = 0.5), check_overlap = T, size = 5) +
labs(x = NULL, y = NULL, fill = NULL, title = "Accd") +
theme(axis.line = element_blank(), axis.text = element_blank(), axis.ticks = element_blank(), plot.title = element_text(size = 14, hjust = 0.5), legend.position="bottom") +
guides(fill=guide_legend(nrow=2,byrow=TRUE))
freq_acciv <- accidentes %>%
group_by(nombre_ind_acciv) %>%
dplyr::summarise(n = n()) %>%
ggplot(aes(x = "", y = n, fill = nombre_ind_acciv)) +
geom_bar(stat = "identity", width = 2) +
coord_polar("y") +
geom_text(aes(label = n), position = position_stack(vjust = 0.5), check_overlap = T, size = 5) +
labs(x = NULL, y = NULL, fill = NULL, title = "Acciv") +
theme(axis.line = element_blank(), axis.text = element_blank(), axis.ticks = element_blank(), plot.title = element_text(size = 14, hjust = 0.5), legend.position="bottom") +
guides(fill=guide_legend(nrow=2,byrow=TRUE))
grid.arrange(freq_accd,
freq_acciv,
nrow = 1)# Sentido
freq_sentido <- accidentes %>%
group_by(nombre_sentido) %>%
dplyr::summarise(n = n()) %>%
ggplot(aes(x = "", y = n, fill = nombre_sentido)) +
geom_bar(stat = "identity", width = 2) +
coord_polar("y") +
geom_text(aes(label = n), position = position_stack(vjust = 0.5), check_overlap = T, size = 5) +
labs(x = NULL, y = NULL, fill = NULL, title = "Sentido") +
theme(axis.line = element_blank(), axis.text = element_blank(), axis.ticks = element_blank(), plot.title = element_text(size = 14, hjust = 0.5), legend.position="bottom") +
guides(fill=guide_legend(nrow=2,byrow=TRUE))
# Tipo vía
freq_via <- accidentes %>%
group_by(nombre_tipo_via) %>%
dplyr::summarise(n = n()) %>%
ggplot(aes(x = "", y = n, fill = nombre_tipo_via)) +
geom_bar(stat = "identity", width = 2) +
coord_polar("y") +
geom_text(aes(label = n), position = position_stack(vjust = 0.5), check_overlap = T, size = 5) +
labs(x = NULL, y = NULL, fill = NULL, title = "Tipo de vía") +
theme(axis.line = element_blank(), axis.text = element_blank(), axis.ticks = element_blank(), plot.title = element_text(size = 14, hjust = 0.5), legend.position="bottom") +
guides(fill=guide_legend(nrow=2,byrow=TRUE))
# Tipo animal 2
freq_animal <- accidentes %>%
group_by(nombre_tipo_animal_2f) %>%
dplyr::summarise(n = n()) %>%
ggplot(aes(x = "", y = n, fill = nombre_tipo_animal_2f)) +
geom_bar(stat = "identity", width = 2) +
coord_polar("y") +
geom_text(aes(label = n), position = position_stack(vjust = 0.5), check_overlap = T, size = 5) +
labs(x = NULL, y = NULL, fill = NULL, title = "Tipo de animal") +
theme(axis.line = element_blank(), axis.text = element_blank(), axis.ticks = element_blank(), plot.title = element_text(size = 14, hjust = 0.5), legend.position="bottom", legend.box="vertical") +
guides(fill=guide_legend(nrow=2,byrow=TRUE))
grid.arrange(freq_sentido,
freq_via,
freq_animal,
nrow = 1)En la mayoría de accidentes con animales, las consecuencias
no conllevan víctimas mortales
(total_mu30df), ni víctimas de ningún tipo
(total_hg30df y total_hl30df), conclusión que
se confirma con el análisis de las variables
nombre_ind_accd y nombre_ind_acciv.
Del análisis de las variables continuas también se comprueba, como se sospechaba, que la proporción de superficie de Luna iluminada en el momento del accidente puede llegar a ser un factor a tener en cuenta. Además, al contrario de lo que ocurre con otro tipos de accidentes de tráfico, se descubre que la mayor frecuencia de accidentes se da cuando el IMD es más bajo, es decir, en la vías cuya media de intensidad circulatoria es menor.
Por otro lado, los jabalíes, corzos y ciervos son los animales presentes en la mayoría de los accidentes, como ya adelantaban los estudios analizados en el estado del arte. Sin embargo, aquellos clasificados como ‘caninos’ se sitúan en el número tres, por lo que hay que tenerlo en cuenta ya que, al ser también clasificados como domésticos por la DGT, no se tienen sus datos de distribución del GBIF.
Además, se descubre que la mayoría de los accidentes se producen en vías cuya velocidad máxima permitida es de 80 kilómetros por hora o más.
Asimismo, la gran mayoría de los accidentes se producen en áreas rodeadas de cultivos.
Por último, la titularidad de la vía, el tipo y el sentido no aportan información que parezca que llegue a ser relevante en este proyecto.
El análisis temporal se aborda analizando las variables temporales según las categorías establecidas a lo largo del proceso de integración de los datos y generación de nuevas variables, de manera que se estudia de lo general a lo concreto:
# Mes
freq_mes <- ggplot(data.frame(accidentes), aes(x = mes_1f,
fill = nombre_mes)) +
ggtitle("Distribución de los accidentes por meses") +
xlab("Mes") +
ylab("Número de accidentes") +
theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
scale_fill_brewer(palette = "Paired") +
labs(fill='Mes') +
geom_bar()
ggplotly(freq_mes)# Día de la semana
freq_dia <- ggplot(data.frame(accidentes), aes(x = dia_semana,
fill = nombre_dia_semana)) +
ggtitle("Distribución de los accidentes durante la semana") +
xlab("Día") +
ylab("Número de accidentes") +
theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
scale_fill_brewer(palette = "Accent") +
labs(fill='Día') +
geom_bar()
ggplotly(freq_dia)# Parte del día
freq_parte_dia <- ggplot(data.frame(accidentes), aes(x=reorder(parte_dia, parte_dia,
function(x)-length(x)),
fill = parte_dia)) +
ggtitle("Distribución de los accidentes durante el día") +
xlab("Parte del día") +
ylab("Número de accidentes") +
theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
scale_fill_brewer(palette = "Set2") +
labs(fill='Parte del día') +
geom_bar()
ggplotly(freq_parte_dia)Se observa claramente que de octubre a enero son los meses en los que más accidentes con animales involucrados se registran, aunque esta diferencia no es tan relevante si se comparan los días de la semana entre ellos. Por último, que la gran mayoría de los accidentes se producen de noche y casi los mismos de día que en la suma del anochecer y el atardecer aunque los días son mucho más largos.
Debido a la importancia de la componente temporal en este Trabajo Final de Máster, se decide mostrar también la proporciones dentro de la variable que contiene el momento del día en el que se produce el accidente:
kable(prop.table(table(accidentes$parte_dia)),
digits=2,
align='l',
caption="Frecuencia relativa de la parte del día") %>%
kable_styling(bootstrap_options = Form.Basic)| Var1 | Freq |
|---|---|
| Amanecer | 0.08 |
| Anochecer | 0.11 |
| Día | 0.21 |
| Noche | 0.61 |
Debido a que se tienen datos diarios de los accidentes, se opta por empezar visualizando la serie histórica completa para, después, evaluar cada uno de los años. Para ello, se emplea infografía interactiva que aporta un valor más preciso de cada fecha si se pasa por encima gracias al tooltip y, como valor añadido, permite ampliar periodos específicos, lo que facilita, por ejemplo, comparar el mismo mes de todos los años de forma cómoda e intuitiva sin tener que hacer más gráficos:
# Todo
serie_total <- data.frame(table(accidentes$fecha_accidente))
tserie_total <- read.zoo(serie_total)
# 2016
accidentes_2016 <- subset(accidentes, subset = anyo == 2016)
serie_2016 <- data.frame(table(accidentes_2016$fecha_accidente))
tserie_2016 <- read.zoo(serie_2016)
# 2017
accidentes_2017 <- subset(accidentes, subset = anyo == 2017)
serie_2017 <- data.frame(table(accidentes_2017$fecha_accidente))
tserie_2017 <- read.zoo(serie_2017)
# 2018
accidentes_2018 <- subset(accidentes, subset = anyo == 2018)
serie_2018 <- data.frame(table(accidentes_2018$fecha_accidente))
tserie_2018 <- read.zoo(serie_2018)
# 2019
accidentes_2019 <- subset(accidentes, subset = anyo == 2019)
serie_2019 <- data.frame(table(accidentes_2019$fecha_accidente))
tserie_2019 <- read.zoo(serie_2019)
# 2020
accidentes_2020 <- subset(accidentes, subset = anyo == 2020)
serie_2020 <- data.frame(table(accidentes_2020$fecha_accidente))
tserie_2020 <- read.zoo(serie_2020)
# 2021
accidentes_2021 <- subset(accidentes, subset = anyo == 2021)
serie_2021 <- data.frame(table(accidentes_2021$fecha_accidente))
tserie_2021 <- read.zoo(serie_2021)color<-rainbow(6)
ts_plot(tserie_total,
title = "Todos los accidentes de tráfico con animales entre 2016 y 2021",
Xtitle = "Fecha",
Ytitle = "Accidentes",
slider = TRUE)ts_plot(tserie_2016,
title = "Accidentes de tráfico con animales en 2016",
Xtitle = "Fecha",
Ytitle = "Accidentes",
color = "darkmagenta",
slider = TRUE)ts_plot(tserie_2017,
title = "Accidentes de tráfico con animales en 2017",
Xtitle = "Fecha",
Ytitle = "Accidentes",
color = "maroon",
slider = TRUE)ts_plot(tserie_2018,
title = "Accidentes de tráfico con animales en 2018",
Xtitle = "Fecha",
Ytitle = "Accidentes",
color = "darkorange",
slider = TRUE)ts_plot(tserie_2019,
title = "Accidentes de tráfico con animales en 2019",
Xtitle = "Fecha",
Ytitle = "Accidentes",
color = "deepskyblue",
slider = TRUE)ts_plot(tserie_2020,
title = "Accidentes de tráfico con animales en 2020",
Xtitle = "Fecha",
Ytitle = "Accidentes",
color = "olivedrab",
slider = TRUE)ts_plot(tserie_2021,
title = "Accidentes de tráfico con animales en 2021",
Xtitle = "Fecha",
Ytitle = "Accidentes",
color = "red",
slider = TRUE)A primera vista, parece que se pueden observar tendencias similares comparando todos los años entre sí, aunque no ocurre lo mismo de una manera tan clara comparando unos meses con otros. Además, se detecta la anomalía que comienza en marzo de 2020, previsible debido a que fue cuando comenzó en España el confinamiento para hacer frente a la pandemia de coronavirus.
A continuación se estudian los resultados de la función de autocorrelación (ACF) con un intervalo de confianza del 95%, que están representadas por las dos líneas horizontales discontinuas:
acf_year <- ggAcf(tserie_total[,"Freq"]) +
ggtitle("Gráfico ACF de accidentes de tráfico con animales en España 2016-2021") +
theme(plot.title = element_text(hjust = 0.5))
ggplotly(acf_year)acf_2016 <- ggAcf(tserie_2016[,"Freq"]) +
ggtitle("Gráfico ACF de accidentes de tráfico con animales en España 2016") +
theme(plot.title = element_text(hjust = 0.5))
ggplotly(acf_2016)acf_2017 <- ggAcf(tserie_2017[,"Freq"]) +
ggtitle("Gráfico ACF de accidentes de tráfico con animales en España 2017") +
theme(plot.title = element_text(hjust = 0.5))
ggplotly(acf_2017)acf_2018 <- ggAcf(tserie_2018[,"Freq"]) +
ggtitle("Gráfico ACF de accidentes de tráfico con animales en España 2018") +
theme(plot.title = element_text(hjust = 0.5))
ggplotly(acf_2018)acf_2019 <- ggAcf(tserie_2019[,"Freq"]) +
ggtitle("Gráfico ACF de accidentes de tráfico con animales en España 2020") +
theme(plot.title = element_text(hjust = 0.5))
ggplotly(acf_2019)acf_2020 <- ggAcf(tserie_2020[,"Freq"]) +
ggtitle("Gráfico ACF de accidentes de tráfico con animales en España 2020") +
theme(plot.title = element_text(hjust = 0.5))
ggplotly(acf_2020)acf_2021 <- ggAcf(tserie_2021[,"Freq"]) +
ggtitle("Gráfico ACF de accidentes de tráfico con animales en España 2021")+
theme(plot.title = element_text(hjust = 0.5))
ggplotly(acf_2021)Todas las autocorrelaciones son significativamente distintas de cero. Por lo tanto, la serie temporal no es aleatoria ni en el estudio de su conjunto ni para cada uno de los años, incluido el 2020. Además, existe un alto grado de autocorrelación entre todas las observaciones adyacentes (lag = 1), casi adyacentes (lag = 2) y no adyacentes en el gráfico ACF, aunque se detecta que en 2018 esta correlación es ligeramente menor.
Por último, con el test de Raíz Unitaria de Kwiatkowski (KPSS), se estudia si los datos son estacionarios tanto en su conjunto como para cada uno de los años. Para ello, se plantean las siguientes hipótesis nula y alternativa:
\(H_0\): La serie es estacionaria
\(H_1\): La serie no es estacionaria
tserie_total[,"Freq"] %>% ur.kpss() %>% summary()##
## #######################
## # KPSS Unit Root Test #
## #######################
##
## Test is of type: mu with 8 lags.
##
## Value of test-statistic is: 4.5
##
## Critical value for a significance level of:
## 10pct 5pct 2.5pct 1pct
## critical values 0.35 0.46 0.57 0.74
tserie_2016[,"Freq"] %>% ur.kpss() %>% summary()##
## #######################
## # KPSS Unit Root Test #
## #######################
##
## Test is of type: mu with 5 lags.
##
## Value of test-statistic is: 3.8
##
## Critical value for a significance level of:
## 10pct 5pct 2.5pct 1pct
## critical values 0.35 0.46 0.57 0.74
tserie_2017[,"Freq"] %>% ur.kpss() %>% summary()##
## #######################
## # KPSS Unit Root Test #
## #######################
##
## Test is of type: mu with 5 lags.
##
## Value of test-statistic is: 3.2
##
## Critical value for a significance level of:
## 10pct 5pct 2.5pct 1pct
## critical values 0.35 0.46 0.57 0.74
tserie_2018[,"Freq"] %>% ur.kpss() %>% summary()##
## #######################
## # KPSS Unit Root Test #
## #######################
##
## Test is of type: mu with 5 lags.
##
## Value of test-statistic is: 2.6
##
## Critical value for a significance level of:
## 10pct 5pct 2.5pct 1pct
## critical values 0.35 0.46 0.57 0.74
tserie_2019[,"Freq"] %>% ur.kpss() %>% summary()##
## #######################
## # KPSS Unit Root Test #
## #######################
##
## Test is of type: mu with 5 lags.
##
## Value of test-statistic is: 3.3
##
## Critical value for a significance level of:
## 10pct 5pct 2.5pct 1pct
## critical values 0.35 0.46 0.57 0.74
tserie_2020[,"Freq"] %>% ur.kpss() %>% summary()##
## #######################
## # KPSS Unit Root Test #
## #######################
##
## Test is of type: mu with 5 lags.
##
## Value of test-statistic is: 2.7
##
## Critical value for a significance level of:
## 10pct 5pct 2.5pct 1pct
## critical values 0.35 0.46 0.57 0.74
tserie_2021[,"Freq"] %>% ur.kpss() %>% summary()##
## #######################
## # KPSS Unit Root Test #
## #######################
##
## Test is of type: mu with 5 lags.
##
## Value of test-statistic is: 4.1
##
## Critical value for a significance level of:
## 10pct 5pct 2.5pct 1pct
## critical values 0.35 0.46 0.57 0.74
En todos los casos se debe rechazar la hipótesis nula de estacionariedad, ya que el valor del estadístico de prueba es más extremo que los valores críticos del 10%, 5% y 1% (Value of test-statistic > 0,119, Value of test-statistic > 0,146, Value of test-statistic > Value of test-statistic).
De octubre a enero son los meses en los que más accidentes con animales involucrados se registran. No existe tal diferencia si se comparan días de la semana entre ellos. Lo más destacado, sin embargo, es que la gran mayoría de los accidentes se producen de noche y casi los mismos de día (10 horas) que en la suma del anochecer (1 hora) y el atardecer (1 hora).
En cuanto a la evolución de los accidentes en el tiempo, se pueden observar tendencias similares comparando todos los años entre sí, pero no en la comparación de los meses. Como era previsible por los efectos de la pandemia de coronavirus, 2020 es un año anómalo. Del mismo modo, se trabajó en el primer apartado del análisis la clara importancia de la superficie de la Luna iluminada, que también se puede entender como una componente temporal puesto que su ciclo es de 28 días.
El análisis de las autocorrelaciones arroja que la serie temporal no es aleatoria ni en el estudio de su conjunto ni para cada uno de los años, incluido el 2020. Además, existe un alto grado de autocorrelación entre todas las observaciones adyacentes, casi adyacentes y no adyacenteses.
A pesar de esta no aleatoriedad y fuerte autocorrelación, se verifica estadísticamente que los datos no son estacionales.
Para ir de lo general a lo concreto, se aborda el análisis de la espacialidad de más a menos área de estudio:
# Comunidad autónoma
freq_CCAA <- ggplot(data.frame(accidentes), aes(x=reorder(nombre_ccaa,nombre_ccaa,
function(x)-length(x)),
fill = nombre_ccaa)) +
ggtitle("Distribución de los accidentes por comunidades autónomas") +
xlab("Comunidad autónoma") +
ylab("Número de accidentes") +
theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
scale_color_gradientn(colours = rainbow(10)) +
labs(fill='Comunidad autónoma') +
geom_bar()
ggplotly(freq_CCAA)# Provincia
freq_PROV <- ggplot(data.frame(accidentes), aes(x=reorder(nombre_provincia, nombre_provincia,
function(x)-length(x)),
fill = nombre_provincia)) +
ggtitle("Distribución de los accidentes por provincias") +
xlab("Provincia") +
ylab("Número de accidentes") +
theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
scale_color_gradientn(colours = rainbow(10)) +
labs(fill='Provincia') +
geom_bar()
ggplotly(freq_PROV)Se observa que en País Vasco y Cataluña no hay registros y esto es debido a que los datos no han sido proporcionados por la DGT.
Por último, como hay muchos municipios diferentes, se opta por mostrar las frecuencias en forma de tabla por si hay se necesita recurrir a ella en otras fases del proyecto:
kable(data.frame(table(accidentes$nombre_municipio)),
align='l',
caption= "Frecuencia de accidentes con animales en cada municipio") %>%
kable_styling(bootstrap_options = Form.Basic) %>%
scroll_box(width = "100%", height = "470px")| Var1 | Freq |
|---|---|
| Abanilla | 14 |
| Abarán | 33 |
| Abegondo | 72 |
| Aceuchal | 6 |
| Adeje | 12 |
| Adra | 27 |
| Aguilar de Campoo | 319 |
| Aguilar de la Frontera | 26 |
| Águilas | 47 |
| Agüimes | 3 |
| Alagón | 26 |
| Alaior | 4 |
| Alameda | 6 |
| Álamo, El | 5 |
| Alaquàs | 1 |
| Alba de Tormes | 41 |
| Albacete | 376 |
| Albaida | 14 |
| Albal | 3 |
| Albatera | 9 |
| Alberic | 27 |
| Albolote | 51 |
| Alboraia/Alboraya | 1 |
| Albox | 12 |
| Albuñol | 22 |
| Alburquerque | 125 |
| Alcalá de Guadaíra | 135 |
| Alcalá de Henares | 21 |
| Alcalá de los Gazules | 21 |
| Alcalà de Xivert | 90 |
| Alcalá del Río | 7 |
| Alcalá del Valle | 3 |
| Alcalá la Real | 60 |
| Alcantarilla | 18 |
| Alcañiz | 167 |
| Alcaudete | 20 |
| Alcázar de San Juan | 101 |
| Alcázares, Los | 2 |
| Alcobendas | 7 |
| Alcora, l’ | 37 |
| Alcorcón | 8 |
| Alcoy/Alcoi | 70 |
| Alcúdia | 10 |
| Alcúdia de Crespins, l’ | 10 |
| Alcúdia, l’ | 6 |
| Aldaia | 1 |
| Aldea de San Nicolás, La | 0 |
| Aldeamayor de San Martín | 69 |
| Alfacar | 11 |
| Alfaro | 76 |
| Alfàs del Pi, l’ | 17 |
| Algaba, La | 9 |
| Algaida | 13 |
| Algarrobo | 1 |
| Algeciras | 19 |
| Algemesí | 13 |
| Algete | 11 |
| Alginet | 3 |
| Algodonales | 15 |
| Alguazas | 1 |
| Alhama de Granada | 10 |
| Alhama de Murcia | 52 |
| Alhaurín de la Torre | 2 |
| Alhaurín el Grande | 5 |
| Alhendín | 11 |
| Alicante/Alacant | 65 |
| Aljaraque | 14 |
| Allariz | 178 |
| Aller | 62 |
| Almadén | 38 |
| Almagro | 39 |
| Almansa | 125 |
| Almassora | 12 |
| Almazán | 222 |
| Almenara | 10 |
| Almendralejo | 43 |
| Almensilla | 1 |
| Almería | 111 |
| Almodóvar del Campo | 70 |
| Almodóvar del Río | 63 |
| Almonte | 57 |
| Almoradí | 9 |
| Almunia de Doña Godina, La | 42 |
| Almuñécar | 11 |
| Almussafes | 4 |
| Álora | 5 |
| Alovera | 8 |
| Alpedrete | 5 |
| Altea | 48 |
| Altsasu/Alsasua | 32 |
| Alzira | 81 |
| Ames | 90 |
| Andorra | 50 |
| Andújar | 65 |
| Ansoáin/Antsoain | 1 |
| Antequera | 164 |
| Antigua | 38 |
| Añover de Tajo | 5 |
| Aracena | 62 |
| Arafo | 1 |
| Arahal | 43 |
| Aranda de Duero | 295 |
| Aranguren | 41 |
| Aranjuez | 16 |
| Archena | 10 |
| Archidona | 74 |
| Arcos de la Frontera | 25 |
| Arenas de San Pedro | 109 |
| Ares | 11 |
| Arévalo | 63 |
| Argamasilla de Alba | 69 |
| Argamasilla de Calatrava | 30 |
| Arganda del Rey | 41 |
| Argés | 4 |
| Arico | 28 |
| Arjona | 9 |
| Armilla | 6 |
| Arnedo | 69 |
| Arona | 17 |
| Arrecife | 6 |
| Arroyo de la Encomienda | 9 |
| Arroyo de la Luz | 37 |
| Arroyomolinos | 5 |
| Artà | 9 |
| Arteixo | 87 |
| Arucas | 10 |
| Arzúa | 57 |
| Aspe | 21 |
| Astillero, El | 4 |
| Astorga | 139 |
| Atarfe | 14 |
| Ávila | 275 |
| Avilés | 63 |
| Ayamonte | 18 |
| Ayora | 119 |
| Aznalcóllar | 3 |
| Azuaga | 27 |
| Azuqueca de Henares | 6 |
| Badajoz | 228 |
| Baena | 14 |
| Baeza | 44 |
| Bailén | 29 |
| Baiona | 19 |
| Banyeres de Mariola | 49 |
| Bañeza, La | 78 |
| Barbadás | 174 |
| Barbastro | 243 |
| Barbate | 13 |
| Barco de Valdeorras, O | 120 |
| Bargas | 9 |
| Barrios, Los | 41 |
| Baza | 95 |
| Baztan | 55 |
| Beas de Segura | 23 |
| Becerril de la Sierra | 6 |
| Béjar | 20 |
| Bembibre | 200 |
| Benacazón | 5 |
| Benaguasil | 4 |
| Benahavís | 23 |
| Benalmádena | 0 |
| Benalup-Casas Viejas | 11 |
| Benamejí | 8 |
| Benavente | 160 |
| Benejúzar | 1 |
| Benicarló | 27 |
| Benicasim/Benicàssim | 28 |
| Benidorm | 14 |
| Beniel | 1 |
| Benifaió | 3 |
| Benigànim | 24 |
| Benissa | 41 |
| Bergondo | 98 |
| Berja | 22 |
| Berrioplano/Berriobeiti | 72 |
| Berriozar | 3 |
| Betanzos | 123 |
| Bétera | 13 |
| Betxí | 9 |
| Bigastro | 3 |
| Binéfar | 32 |
| Binissalem | 4 |
| Blanca | 21 |
| Boadilla del Monte | 16 |
| Boalo, El | 15 |
| Boiro | 47 |
| Bolaños de Calatrava | 28 |
| Bollullos de la Mitación | 15 |
| Bollullos Par del Condado | 12 |
| Bonares | 7 |
| Borja | 7 |
| Bormujos | 4 |
| Bornos | 6 |
| Borriana/Burriana | 17 |
| Borriol | 32 |
| Brenes | 5 |
| Breña Alta | 4 |
| Breña Baja | 1 |
| Brión | 31 |
| Briviesca | 150 |
| Brunete | 25 |
| Bueu | 12 |
| Bujalance | 10 |
| Bullas | 20 |
| Bunyola | 6 |
| Buñol | 14 |
| Burela | 27 |
| Burgo de Osma-Ciudad de Osma | 239 |
| Burgos | 153 |
| Burguillos | 2 |
| Burjassot | 2 |
| Burlada/Burlata | 1 |
| Cabanillas del Campo | 23 |
| Cabeza del Buey | 20 |
| Cabezas de San Juan, Las | 22 |
| Cabezón de la Sal | 38 |
| Cabra | 56 |
| Cacabelos | 22 |
| Cáceres | 260 |
| Cádiz | 3 |
| Calahorra | 46 |
| Calamonte | 3 |
| Calasparra | 48 |
| Calatayud | 109 |
| Caldas de Reis | 110 |
| Callosa d’en Sarrià | 3 |
| Callosa de Segura | 7 |
| Calp | 15 |
| Calvià | 5 |
| Camargo | 34 |
| Camariñas | 43 |
| Camarma de Esteruelas | 13 |
| Camas | 9 |
| Cambados | 21 |
| Cambre | 83 |
| Campana, La | 25 |
| Campanario | 12 |
| Campello, el | 26 |
| Campillos | 20 |
| Campo de Criptana | 49 |
| Campo Real | 13 |
| Campos | 12 |
| Canals | 25 |
| Candelaria | 10 |
| Candeleda | 35 |
| Canet d’En Berenguer | 0 |
| Cangas | 43 |
| Cangas de Onís | 77 |
| Cangas del Narcea | 80 |
| Cantillana | 20 |
| Cañiza, A | 127 |
| Capdepera | 7 |
| Caravaca de la Cruz | 102 |
| Carbajosa de la Sagrada | 3 |
| Carballiño, O | 196 |
| Carballo | 142 |
| Carboneras | 17 |
| Carcaixent | 11 |
| Carlet | 15 |
| Carlota, La | 54 |
| Carmona | 154 |
| Carolina, La | 12 |
| Carral | 48 |
| Carreño | 116 |
| Cartagena | 120 |
| Cártama | 27 |
| Cartaya | 65 |
| Cartes | 34 |
| Casar, El | 21 |
| Casares | 5 |
| Casariche | 10 |
| Casarrubios del Monte | 18 |
| Caspe | 79 |
| Castalla | 56 |
| Castell, Es | 0 |
| Castelló de la Plana | 120 |
| Castrillón | 185 |
| Castro-Urdiales | 41 |
| Castro de Rei | 362 |
| Castro del Río | 7 |
| Castuera | 49 |
| Catral | 11 |
| Caudete | 16 |
| Cazorla | 58 |
| Cedeira | 60 |
| Cee | 48 |
| Cehegín | 44 |
| Celanova | 166 |
| Cenes de la Vega | 9 |
| Cerceda | 40 |
| Cercedilla | 7 |
| Cerdedo-Cotobade | 58 |
| Ceuta | 0 |
| Ceutí | 1 |
| Chantada | 187 |
| Chauchina | 10 |
| Cheste | 24 |
| Chiclana de la Frontera | 44 |
| Chinchón | 11 |
| Chipiona | 13 |
| Chiva | 32 |
| Churriana de la Vega | 4 |
| Ciempozuelos | 7 |
| Cieza | 72 |
| Cigales | 29 |
| Cintruénigo | 30 |
| Cistérniga | 5 |
| Ciudad Real | 79 |
| Ciudad Rodrigo | 103 |
| Ciutadella de Menorca | 5 |
| Cobeña | 3 |
| Cocentaina | 26 |
| Coín | 9 |
| Colindres | 13 |
| Collado Mediano | 8 |
| Collado Villalba | 17 |
| Colmenar de Oreja | 10 |
| Colmenar Viejo | 54 |
| Colmenarejo | 7 |
| Conil de la Frontera | 11 |
| Constantina | 12 |
| Consuegra | 19 |
| Córdoba | 297 |
| Corella | 122 |
| Coria | 26 |
| Coria del Río | 5 |
| Coristanco | 52 |
| Corral de Almaguer | 16 |
| Corrales de Buelna, Los | 40 |
| Coruña, A | 7 |
| Corvera de Asturias | 94 |
| Coslada | 3 |
| Cox | 6 |
| Crevillent | 26 |
| Cuarte de Huerva | 3 |
| Cubas de la Sagra | 1 |
| Cudillero | 46 |
| Cuéllar | 248 |
| Cuenca | 217 |
| Cuervo de Sevilla, El | 3 |
| Cuevas del Almanzora | 25 |
| Cullera | 8 |
| Culleredo | 72 |
| Daganzo de Arriba | 4 |
| Daimiel | 54 |
| Dénia | 69 |
| Dolores | 3 |
| Don Benito | 102 |
| Dos Hermanas | 29 |
| Dúrcal | 23 |
| Écija | 141 |
| Eivissa | 3 |
| Ejea de los Caballeros | 181 |
| Ejido, El | 57 |
| Elche/Elx | 124 |
| Elda | 11 |
| Enguera | 3 |
| Entrambasaguas | 69 |
| Escorial, El | 23 |
| Espartinas | 9 |
| Espinar, El | 86 |
| Esporles | 1 |
| Esquivias | 2 |
| Estella-Lizarra | 28 |
| Estepa | 44 |
| Estepona | 27 |
| Estrada, A | 304 |
| Felanitx | 10 |
| Fene | 56 |
| Fernán-Núñez | 21 |
| Ferrol | 62 |
| Finestrat | 10 |
| Formentera | 1 |
| Fortuna | 12 |
| Foz | 206 |
| Fraga | 125 |
| Fuengirola | 3 |
| Fuenlabrada | 11 |
| Fuensalida | 7 |
| Fuente Álamo de Murcia | 51 |
| Fuente del Maestre | 33 |
| Fuente el Saz de Jarama | 18 |
| Fuente Palmera | 50 |
| Fuentes de Andalucía | 9 |
| Gabias, Las | 3 |
| Galapagar | 32 |
| Gáldar | 2 |
| Gandia | 61 |
| Garrucha | 6 |
| Gata de Gorgos | 5 |
| Gelves | 2 |
| Gerena | 7 |
| Getafe | 9 |
| Gibraleón | 83 |
| Gijón | 344 |
| Godella | 1 |
| Gondomar | 55 |
| Gozón | 10 |
| Grado | 104 |
| Granada | 29 |
| Granadilla de Abona | 42 |
| Griñón | 7 |
| Grove, O | 18 |
| Guadalajara | 273 |
| Guadalix de la Sierra | 49 |
| Guadarrama | 25 |
| Guadassuar | 6 |
| Guadix | 112 |
| Gualchos | 32 |
| Guancha, La | 1 |
| Guarda, A | 30 |
| Guardamar del Segura | 8 |
| Guardia de Jaén, La | 5 |
| Guardo | 121 |
| Guareña | 39 |
| Guía de Isora | 23 |
| Guijuelo | 27 |
| Guillena | 33 |
| Güímar | 15 |
| Guitiriz | 220 |
| Haría | 1 |
| Haro | 63 |
| Hellín | 174 |
| Herencia | 42 |
| Herrera | 6 |
| Hinojosa del Duque | 104 |
| Hoyo de Manzanares | 21 |
| Huarte/Uharte | 7 |
| Huelma | 36 |
| Huelva | 53 |
| Huércal-Overa | 69 |
| Huércal de Almería | 12 |
| Huesca | 112 |
| Huéscar | 35 |
| Huétor Tájar | 17 |
| Humanes de Madrid | 3 |
| Ibi | 31 |
| Icod de los Vinos | 2 |
| Illescas | 6 |
| Íllora | 20 |
| Inca | 21 |
| Ingenio | 3 |
| Íscar | 29 |
| Isla Cristina | 10 |
| Isla Mayor | 2 |
| Iznalloz | 56 |
| Jaca | 88 |
| Jaén | 123 |
| Jaraíz de la Vera | 67 |
| Jávea/Xàbia | 36 |
| Jerez de la Frontera | 134 |
| Jerez de los Caballeros | 67 |
| Jijona/Xixona | 41 |
| Jimena de la Frontera | 14 |
| Jódar | 29 |
| Jumilla | 76 |
| Laguna de Duero | 8 |
| Lalín | 340 |
| Langreo | 130 |
| Laracha, A | 54 |
| Lardero | 53 |
| Laredo | 23 |
| Laviana | 34 |
| Lebrija | 16 |
| Leganés | 7 |
| Lena | 109 |
| León | 14 |
| Lepe | 35 |
| Librilla | 19 |
| Linares | 62 |
| Línea de la Concepción, La | 13 |
| Llanera | 187 |
| Llanes | 275 |
| Llanos de Aridane, Los | 5 |
| Llerena | 42 |
| Llíria | 41 |
| Lloseta | 1 |
| Llucmajor | 16 |
| Loeches | 25 |
| Logroño | 86 |
| Loja | 47 |
| Lora del Río | 44 |
| Lorca | 238 |
| Lorquí | 8 |
| Lucena | 83 |
| Lugo | 926 |
| Macael | 8 |
| Madrid | 134 |
| Madridejos | 19 |
| Mairena del Alcor | 13 |
| Mairena del Aljarafe | 6 |
| Majadahonda | 17 |
| Málaga | 37 |
| Malagón | 49 |
| Malpica de Bergantiños | 63 |
| Manacor | 25 |
| Mancha Real | 42 |
| Manilva | 8 |
| Manises | 7 |
| Manzanares | 74 |
| Manzanares el Real | 49 |
| Maó-Mahón | 8 |
| Maracena | 4 |
| Marbella | 64 |
| Marchamalo | 32 |
| Marchena | 52 |
| María de Huerva | 8 |
| Marín | 45 |
| Marina de Cudeyo | 18 |
| Marmolejo | 19 |
| Marratxí | 4 |
| Martos | 49 |
| Massamagrell | 1 |
| Matanza de Acentejo, La | 7 |
| Mazarrón | 29 |
| Meaño | 21 |
| Meco | 12 |
| Medina de Pomar | 236 |
| Medina del Campo | 87 |
| Medina Sidonia | 43 |
| Medio Cudeyo | 54 |
| Mejorada del Campo | 7 |
| Melide | 91 |
| Membrilla | 38 |
| Mengíbar | 44 |
| Méntrida | 1 |
| Mercadal, Es | 1 |
| Mérida | 141 |
| Miajadas | 18 |
| Miengo | 6 |
| Mieres | 147 |
| Miguel Esteban | 2 |
| Miguelturra | 28 |
| Mijas | 27 |
| Miño | 87 |
| Miraflores de la Sierra | 20 |
| Miranda de Ebro | 138 |
| Mislata | 4 |
| Moaña | 35 |
| Mocejón | 1 |
| Moguer | 19 |
| Mojácar | 13 |
| Mojonera, La | 13 |
| Molar, El | 38 |
| Molina de Segura | 14 |
| Mollina | 12 |
| Monachil | 14 |
| Moncada | 1 |
| Moncofa | 3 |
| Monforte de Lemos | 402 |
| Monforte del Cid | 22 |
| Monóvar/Monòver | 34 |
| Montefrío | 3 |
| Montehermoso | 23 |
| Montellano | 7 |
| Montijo | 38 |
| Montilla | 54 |
| Montoro | 70 |
| Montserrat | 22 |
| Monzón | 220 |
| Mora | 9 |
| Moral de Calatrava | 37 |
| Moraleja | 51 |
| Moraleja de Enmedio | 3 |
| Moralzarzal | 7 |
| Morata de Tajuña | 5 |
| Moratalla | 42 |
| Morón de la Frontera | 45 |
| Mos | 78 |
| Móstoles | 14 |
| Mota del Cuervo | 36 |
| Motilla del Palancar | 44 |
| Motril | 88 |
| Moya | 1 |
| Muela, La | 31 |
| Mugardos | 28 |
| Mula | 69 |
| Murcia | 111 |
| Muro | 5 |
| Muro de Alcoy | 21 |
| Muros | 46 |
| Museros | 6 |
| Mutxamel | 32 |
| Nájera | 19 |
| Nàquera/Náquera | 11 |
| Narón | 222 |
| Nava | 92 |
| Navalcarnero | 47 |
| Navalmoral de la Mata | 25 |
| Navas del Marqués, Las | 28 |
| Navia | 115 |
| Neda | 37 |
| Negreira | 18 |
| Nerja | 11 |
| Nerva | 1 |
| Nigrán | 21 |
| Níjar | 88 |
| Noáin (Valle de Elorz)/Noain (Elortzibar) | 28 |
| Noia | 22 |
| Noreña | 13 |
| Novelda | 25 |
| Nucia, la | 11 |
| Nueva Carteya | 10 |
| Nuevo Baztán | 1 |
| Nules | 27 |
| Ocaña | 12 |
| Ogíjares | 4 |
| Oleiros | 87 |
| Olías del Rey | 6 |
| Oliva | 133 |
| Oliva de la Frontera | 11 |
| Oliva, La | 12 |
| Olivares | 4 |
| Olivenza | 45 |
| Olleria, l’ | 12 |
| Olula del Río | 4 |
| Olvera | 13 |
| Onda | 30 |
| Ondara | 48 |
| Onil | 9 |
| Ontinyent | 31 |
| Ordes | 100 |
| Órgiva | 10 |
| Orihuela | 44 |
| Oropesa del Mar/Orpesa | 40 |
| Oroso | 40 |
| Orotava, La | 10 |
| Ortigueira | 258 |
| Osuna | 119 |
| Ourense | 338 |
| Outeiro de Rei | 198 |
| Outes | 45 |
| Oviedo | 341 |
| Oza-Cesuras | 82 |
| Padrón | 36 |
| Padul | 29 |
| Paiporta | 1 |
| Pájara | 11 |
| Palacios y Villafranca, Los | 31 |
| Palazuelos de Eresma | 20 |
| Palencia | 105 |
| Palma | 37 |
| Palma del Condado, La | 16 |
| Palma del Río | 27 |
| Palmas de Gran Canaria, Las | 13 |
| Palomares del Río | 3 |
| Palos de la Frontera | 27 |
| Pamplona/Iruña | 8 |
| Paracuellos de Jarama | 5 |
| Paradas | 27 |
| Parla | 12 |
| Parres | 44 |
| Paso, El | 5 |
| Paterna | 20 |
| Paterna de Rivera | 4 |
| Peal de Becerro | 24 |
| Pedreguer | 55 |
| Pedrera | 4 |
| Pedrezuela | 20 |
| Pedro Muñoz | 11 |
| Pedroñeras, Las | 65 |
| Pego | 70 |
| Peligros | 7 |
| Peníscola/Peñíscola | 54 |
| Peñafiel | 157 |
| Peñaranda de Bracamonte | 7 |
| Peñarroya-Pueblonuevo | 28 |
| Peralta/Azkoien | 81 |
| Pereiro de Aguiar, O | 174 |
| Petrer | 14 |
| Picanya | 1 |
| Picassent | 16 |
| Piélagos | 108 |
| Pilar de la Horadada | 2 |
| Pilas | 6 |
| Piloña | 157 |
| Pinos Puente | 35 |
| Pinós, el/Pinoso | 52 |
| Pinto | 7 |
| Pizarra | 6 |
| Plasencia | 87 |
| Pobla de Vallbona, la | 7 |
| Pobla, Sa | 7 |
| Pobra do Caramiñal, A | 25 |
| Poio | 11 |
| Polanco | 33 |
| Pollença | 8 |
| Polop | 3 |
| Ponferrada | 256 |
| Ponte Caldelas | 55 |
| Ponteareas | 201 |
| Ponteceso | 57 |
| Pontedeume | 60 |
| Pontes de García Rodríguez, As | 242 |
| Pontevedra | 177 |
| Porcuna | 17 |
| Porreres | 6 |
| Porriño, O | 112 |
| Porto do Son | 51 |
| Posadas | 31 |
| Pozoblanco | 12 |
| Pozuelo de Alarcón | 12 |
| Prado del Rey | 9 |
| Pravia | 150 |
| Priego de Córdoba | 26 |
| Puçol | 4 |
| Puebla de Alfindén, La | 4 |
| Puebla de Almoradiel, La | 8 |
| Puebla de Cazalla, La | 22 |
| Puebla de la Calzada | 4 |
| Puebla de Montalbán, La | 9 |
| Puebla del Río, La | 7 |
| Puente Genil | 30 |
| Puerto de la Cruz | 0 |
| Puerto de Santa María, El | 21 |
| Puerto del Rosario | 21 |
| Puerto Lumbreras | 22 |
| Puerto Real | 33 |
| Puerto Serrano | 2 |
| Puertollano | 71 |
| Puig de Santa Maria, el | 4 |
| Pulianas | 9 |
| Pulpí | 23 |
| Punta Umbría | 7 |
| Quart de Poblet | 6 |
| Quesada | 12 |
| Quintanar de la Orden | 22 |
| Quintanar del Rey | 36 |
| Rafelbunyol | 1 |
| Rambla, La | 33 |
| Real Sitio de San Ildefonso | 26 |
| Realejos, Los | 4 |
| Redondela | 38 |
| Redován | 4 |
| Reinosa | 6 |
| Reocín | 64 |
| Requena | 105 |
| Rianxo | 59 |
| Riba-roja de Túria | 22 |
| Ribadavia | 114 |
| Ribadeo | 181 |
| Ribadesella | 51 |
| Ribadumia | 12 |
| Ribeira | 81 |
| Rincón de la Victoria | 5 |
| Rinconada, La | 25 |
| Rivas-Vaciamadrid | 9 |
| Rociana del Condado | 14 |
| Roda, La | 81 |
| Rojales | 6 |
| Ronda | 46 |
| Roquetas de Mar | 9 |
| Rosal, O | 19 |
| Rosario, El | 4 |
| Rota | 13 |
| Rozas de Madrid, Las | 17 |
| Rute | 12 |
| Sabiñánigo | 326 |
| Sada | 32 |
| Sagunto/Sagunt | 26 |
| Salamanca | 24 |
| Salas | 101 |
| Salceda de Caselas | 24 |
| Salobreña | 17 |
| Salteras | 8 |
| Salvaterra de Miño | 107 |
| San Adrián | 15 |
| San Agustín del Guadalix | 14 |
| San Andrés del Rabanedo | 20 |
| San Antonio de Benagéber | 1 |
| San Bartolomé | 7 |
| San Bartolomé de Tirajana | 8 |
| San Cibrao das Viñas | 224 |
| San Clemente | 124 |
| San Cristóbal de La Laguna | 16 |
| San Fernando | 3 |
| San Fernando de Henares | 19 |
| San Fulgencio | 4 |
| San Javier | 20 |
| San Juan de Aznalfarache | 3 |
| San Juan del Puerto | 22 |
| San Lorenzo de El Escorial | 38 |
| San Martín de la Vega | 13 |
| San Martín de Valdeiglesias | 54 |
| San Martín del Rey Aurelio | 30 |
| San Miguel de Abona | 11 |
| San Miguel de Salinas | 2 |
| San Pedro del Pinatar | 4 |
| San Roque | 39 |
| San Sebastián de la Gomera | 1 |
| San Sebastián de los Reyes | 14 |
| San Vicente de Alcántara | 31 |
| San Vicente del Raspeig/Sant Vicent del Raspeig | 25 |
| Sangüesa/Zangoza | 7 |
| Sanlúcar de Barrameda | 22 |
| Sanlúcar la Mayor | 30 |
| Sant Antoni de Portmany | 7 |
| Sant Joan d’Alacant | 2 |
| Sant Joan de Labritja | 7 |
| Sant Josep de sa Talaia | 10 |
| Sant Llorenç des Cardassar | 8 |
| Sant Lluís | 1 |
| Santa Brígida | 1 |
| Santa Comba | 60 |
| Santa Cruz de Bezana | 11 |
| Santa Cruz de la Palma | 1 |
| Santa Cruz de Tenerife | 5 |
| Santa Eulària des Riu | 14 |
| Santa Fe | 30 |
| Santa Lucía de Tirajana | 3 |
| Santa Margalida | 6 |
| Santa María de Cayón | 31 |
| Santa María de Guía de Gran Canaria | 1 |
| Santa María del Camí | 1 |
| Santa Marta de Tormes | 11 |
| Santa Pola | 14 |
| Santa Úrsula | 1 |
| Santaella | 11 |
| Santander | 14 |
| Santanyí | 2 |
| Santiago de Compostela | 226 |
| Santiponce | 5 |
| Santo Domingo de la Calzada | 48 |
| Santomera | 4 |
| Santoña | 27 |
| Santos de Maimona, Los | 34 |
| Sanxenxo | 49 |
| Sariegos | 67 |
| Sarria | 265 |
| Sauzal, El | 7 |
| Sax | 45 |
| Sedaví | 2 |
| Segorbe | 23 |
| Segovia | 150 |
| Seseña | 12 |
| Sevilla | 50 |
| Sevilla la Nueva | 7 |
| Siero | 640 |
| Silla | 5 |
| Silleda | 229 |
| Simancas | 54 |
| Socuéllamos | 34 |
| Solana, La | 39 |
| Son Servera | 2 |
| Sonseca | 6 |
| Soria | 483 |
| Soto del Real | 24 |
| Soutomaior | 9 |
| Suances | 14 |
| Sueca | 13 |
| Tacoronte | 5 |
| Tafalla | 72 |
| Talavera de la Reina | 87 |
| Talavera la Real | 42 |
| Talayuela | 17 |
| Tarancón | 50 |
| Tarazona | 129 |
| Tarazona de la Mancha | 67 |
| Tarifa | 27 |
| Tauste | 50 |
| Tavernes de la Valldigna | 39 |
| Tegueste | 2 |
| Teguise | 9 |
| Telde | 9 |
| Teo | 56 |
| Teror | 2 |
| Teruel | 338 |
| Teulada | 12 |
| Tías | 12 |
| Tinajo | 1 |
| Tineo | 171 |
| Tobarra | 84 |
| Tocina | 4 |
| Toledo | 40 |
| Tomelloso | 62 |
| Tomiño | 60 |
| Tordesillas | 105 |
| Toro | 212 |
| Torre-Pacheco | 25 |
| Torreblanca | 38 |
| Torredelcampo | 34 |
| Torredonjimeno | 36 |
| Torrejón de Ardoz | 9 |
| Torrejón de la Calzada | 4 |
| Torrejón del Rey | 12 |
| Torrelavega | 82 |
| Torrelodones | 5 |
| Torremolinos | 0 |
| Torrent | 34 |
| Torreperogil | 37 |
| Torres de Cotillas, Las | 7 |
| Torres de la Alameda | 10 |
| Torrevieja | 16 |
| Torrijos | 8 |
| Torrox | 3 |
| Totana | 47 |
| Trebujena | 13 |
| Tres Cantos | 7 |
| Trigueros | 10 |
| Trujillo | 71 |
| Tudela | 335 |
| Tudela de Duero | 97 |
| Tui | 64 |
| Tuineje | 30 |
| Turís | 10 |
| Úbeda | 65 |
| Ubrique | 5 |
| Umbrete | 11 |
| Unión, La | 3 |
| Utebo | 4 |
| Utiel | 49 |
| Utrera | 81 |
| Valdemorillo | 53 |
| Valdemoro | 7 |
| Valdepeñas | 109 |
| Valdés | 223 |
| Valdoviño | 202 |
| València | 15 |
| Valencia de Alcántara | 82 |
| Valencia de Don Juan | 50 |
| Valencina de la Concepción | 1 |
| Valga | 31 |
| Vall d’Uixó, la | 21 |
| Valladolid | 143 |
| Valle de Egüés/Eguesibar | 51 |
| Valverde de la Virgen | 196 |
| Valverde del Camino | 79 |
| Vedra | 43 |
| Vegas del Genil | 2 |
| Vejer de la Frontera | 18 |
| Vélez-Málaga | 23 |
| Vélez-Rubio | 14 |
| Velilla de San Antonio | 7 |
| Venta de Baños | 14 |
| Vera | 14 |
| Verín | 193 |
| Viator | 15 |
| Vícar | 15 |
| Victoria de Acentejo, La | 2 |
| Vigo | 83 |
| Vila-real | 17 |
| Vila de Cruces | 51 |
| Vilaboa | 61 |
| Vilagarcía de Arousa | 77 |
| Vilalba | 647 |
| Vilamarxant | 25 |
| Vilanova de Arousa | 17 |
| Villa de Otura | 12 |
| Villa del Prado | 8 |
| Villa del Río | 14 |
| Villablino | 26 |
| Villacañas | 13 |
| Villacarrillo | 32 |
| Villafranca de los Barros | 44 |
| Villafranca de los Caballeros | 2 |
| Villajoyosa/Vila Joiosa, la | 38 |
| Villalbilla | 4 |
| Villamartín | 20 |
| Villamayor | 14 |
| Villamediana de Iregua | 24 |
| Villamuriel de Cerrato | 93 |
| Villanueva de Castellón | 9 |
| Villanueva de Córdoba | 21 |
| Villanueva de la Cañada | 6 |
| Villanueva de la Serena | 46 |
| Villanueva de la Torre | 3 |
| Villanueva de los Infantes | 10 |
| Villanueva del Arzobispo | 18 |
| Villanueva del Pardillo | 6 |
| Villanueva del Trabuco | 17 |
| Villaquilambre | 41 |
| Villarejo de Salvanés | 33 |
| Villares de la Reina | 20 |
| Villares, Los | 0 |
| Villarrobledo | 138 |
| Villarrubia de los Ojos | 45 |
| Villava/Atarrabia | 1 |
| Villaverde del Río | 9 |
| Villaviciosa | 293 |
| Villaviciosa de Odón | 21 |
| Villena | 96 |
| Vimianzo | 95 |
| Vinaròs | 113 |
| Viso de San Juan, El | 2 |
| Viso del Alcor, El | 5 |
| Viveiro | 102 |
| Xàtiva | 65 |
| Xeraco | 4 |
| Xinzo de Limia | 223 |
| Xirivella | 4 |
| Yaiza | 3 |
| Yébenes, Los | 26 |
| Yecla | 35 |
| Yeles | 3 |
| Yepes | 3 |
| Yuncos | 4 |
| Zafra | 23 |
| Zamora | 188 |
| Zaragoza | 170 |
| Zaratán | 5 |
| Zizur Mayor/Zizur Nagusia | 18 |
| Zuera | 89 |
A partir de este análisis surge la duda de si los accidentes con los tipos de animales se distribuyen igual en todas las partes de España para poder tomar decisiones de cara al modelado:
# Provincia y tipo animal
freq_PROV <- ggplot(data.frame(accidentes), aes(x=reorder(nombre_provincia, nombre_provincia,
function(x)-length(x)),
fill = nombre_tipo_animal_1f)) +
ggtitle("Distribución de los accidentes por provincias según el animal") +
xlab("Provincia") +
ylab("Número de accidentes") +
theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
scale_color_gradientn(colours = terrain.colors(10)) + labs(fill='Mes') +
geom_bar()
ggplotly(freq_PROV)Aunque el jabalí es el animal más involucrado en accidentes de tráfico, la probabilidad de accidente con un tipo de animal u otro varía en función de la provincia. Por ejemplo, en Soria en mucho más probable chocarse con un corzo.
A la luz de toda la información obtenida, surgen dos necesidades: concretar mejor las zonas con alta probabilidad de este tipo de colisiones y hacerlo teniendo en cuenta el tipo de animal en cada caso. Este es el motivo por el que se decide desarrollar diferentes capas de estimación de densidad de Kernel (KDE), que permite estimar la función de densidad de probabilidad de los accidentes con animales involucrados con el objetivo de aumentar las probabilidades de precisión de los modelos.
Esta información es muy relevante y se va a productivizar para poder
emplearse en los modelos, por lo que para seguir con la línea del
proyecto, se deciden hacer los cálculos en Python, que
se pueden consultar en kde_analysis del
repositorio en GitHub. De este modo, además de la visualización que se
muestra a continuación para cada tipo de animal, se ha guardado un
array que contiene la información de
probabilidad en cada uno de los píxeles, lo que puede mejorar
la precisión del modelo predictivo. Por tanto, a continuación solo se
ven las imágenes resultantes del proceso, aunque no es la información
más relevante del mismo:
Los datos tienen una componente espacial que puede ser crítica para el proyecto. Por tanto, no es tan importante conocer en qué comunidades autónomas, provincias o municipios se produce cada accidente con animales, sino el análisis de cada registro en una ubicación concreta.
Del mismo modo, la distribución de los accidentes depende de cada tipo de animal, lo cual era previsible porque la fauna no se distribuye de forma homogénea por España, tal y como se pudo comprobar al analizar los datos procedentes de GBIF. Por tanto, el conocimiento más relevante que se extrae de este punto son lo arrays resultantes que contienen la estimación de densidad de kernel de los accidentes para cada uno de los animales, cuya visualización se ha mostrado.
accidentes.dim <- dim(accidentes)El conjunto de datos resultante de este proceso de análisis está compuesto de 157.094 registros con 50 campos por cada registro, que siguen la siguiente estructura:
str(accidentes)## 'data.frame': 157094 obs. of 50 variables:
## $ id_num : num 201714028065 202042129058 202118143196 202127149586 202106135682 ...
## $ ind_accda : Factor w/ 2 levels "0","1": 2 2 2 2 2 2 2 2 2 2 ...
## $ nombre_ind_accd : Factor w/ 2 levels "Accidente de daños materiales exclusivamente",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ ind_acciv : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
## $ nombre_ind_acciv : Factor w/ 2 levels "Accidente con víctimas exclusivamente",..: 2 2 2 2 2 2 2 2 2 2 ...
## $ total_mu30df : int 0 0 0 0 0 0 0 0 0 0 ...
## $ total_hg30df : int 0 0 0 0 0 0 0 0 0 0 ...
## $ total_hl30df : int 0 0 0 0 0 0 0 0 0 0 ...
## $ fecha_accidente : Date, format: "2017-09-11" "2020-06-01" ...
## $ hora_accidente : chr "7:30" "23:00" "18:50" "6:35" ...
## $ mes_1f : Factor w/ 12 levels "1","2","3","4",..: 9 6 12 6 12 12 2 12 12 12 ...
## $ nombre_mes : Factor w/ 12 levels "Abril","Agosto",..: 12 7 3 7 3 3 5 3 3 3 ...
## $ anyo : Factor w/ 6 levels "2016","2017",..: 2 5 6 6 6 6 6 6 6 6 ...
## $ ccaa_1f : Factor w/ 16 levels "1","2","3","4",..: 1 8 1 10 9 7 13 3 2 10 ...
## $ nombre_ccaa : Factor w/ 16 levels "Andalucía","Aragón",..: 1 8 1 12 11 7 15 3 2 12 ...
## $ provincia_1f : Factor w/ 44 levels "2","3","4","5",..: 12 37 15 22 5 16 26 28 38 27 ...
## $ nombre_provincia : Factor w/ 44 levels "Albacete","Alicante/Alacant",..: 15 38 18 24 6 19 28 4 39 29 ...
## $ cod_municipio : Factor w/ 1007 levels "0","2003","2009",..: 1 1 1 461 1 1 1 1 1 1 ...
## $ nombre_municipio : Factor w/ 1002 levels "Abanilla","Abarán",..: NA NA NA 486 NA NA NA NA NA NA ...
## $ carretera : chr "N-432" "CL-101" "A-44" "A-54" ...
## $ km : num 196.2 62.4 177.4 11.5 86.2 ...
## $ sentido_1f : Factor w/ 4 levels "1","2","3","4": 1 2 1 1 3 2 1 2 1 2 ...
## $ nombre_sentido : Factor w/ 4 levels "Ambos","Ascendente",..: 2 3 2 2 1 3 2 3 2 3 ...
## $ tipo_via_3f : Factor w/ 2 levels "1","2": 2 2 1 1 2 2 2 2 2 2 ...
## $ nombre_tipo_via : Factor w/ 2 levels "Autopista y autovía",..: 2 2 1 1 2 2 2 2 2 2 ...
## $ titularidad_via_2f : Factor w/ 6 levels "1","2","3","4",..: 1 2 1 1 2 2 2 1 2 2 ...
## $ nombre_titularidad_via: Factor w/ 5 levels "Autonómica","Estatal",..: 2 1 2 2 1 1 1 2 1 1 ...
## $ tipo_animal_1f : Factor w/ 28 levels "0","1","2","3",..: 21 9 21 6 21 6 9 9 6 21 ...
## $ nombre_tipo_animal_1f : Factor w/ 26 levels "Animal no identificado",..: 4 13 4 8 4 8 13 13 8 4 ...
## $ tipo_animal_2f : Factor w/ 3 levels "0","1","2": 3 2 3 2 3 2 2 2 2 3 ...
## $ nombre_tipo_animal_2f : Factor w/ 3 levels "Animal no identificado",..: 2 3 2 3 2 3 3 3 3 2 ...
## $ longitud : num -5.23 -2.42 -3.5 -7.62 -6.56 ...
## $ latitud : num 38.3 41.5 36.8 42.9 38.6 ...
## $ geom : chr "0101000020E6100000B75D68AED3E814C00C59DDEA39254340" "0101000020E6100000FB22A12DE75203C0C5E6E3DA50C54440" "0101000020E61000002766BD18CA090CC0F3716DA8186B4240" "0101000020E6100000982F2FC03E7A1EC03108AC1C5A784540" ...
## $ dia_semana : Factor w/ 7 levels "1","2","3","4",..: 1 1 1 3 2 4 4 1 1 2 ...
## $ nombre_dia_semana : Factor w/ 7 levels "Domingo","Jueves",..: 3 3 3 5 4 2 2 3 3 4 ...
## $ parte_dia : Factor w/ 4 levels "Amanecer","Anochecer",..: 1 4 4 1 3 3 4 4 3 3 ...
## $ luna : int NA 71 99 NA NA NA 93 69 NA NA ...
## $ prec : num NA NA NA 0 NA NA NA NA NA NA ...
## $ tmin : num NA NA NA 12.9 NA NA NA NA NA NA ...
## $ tmax : num NA NA NA 24.5 NA NA NA NA NA NA ...
## $ sol : num NA NA NA 10.1 NA NA NA NA NA NA ...
## $ uso_suelo : Factor w/ 14 levels "Agua","Artificial",..: 3 3 3 3 3 3 5 3 3 3 ...
## $ altitud : num 620 981 1840 612 570 ...
## $ pendiente : num 14.09 2.32 13.84 6.32 1.39 ...
## $ taxonkey : Factor w/ 21 levels "","2433433","2433875",..: 1 20 1 17 1 17 20 20 17 1 ...
## $ tipo_dia : Factor w/ 2 levels "Diario","Finde": 1 1 1 1 1 1 1 1 1 1 ...
## $ tmed : num NA NA NA 18.7 NA NA NA NA NA NA ...
## $ imd_total : num 5062 56 24787 15808 18331 ...
## $ maxspeed : Factor w/ 10 levels "20","30","40",..: 9 8 10 10 8 7 7 10 7 7 ...
Aunque no se trabajará con todos ellos en los modelos, se importan
todos a una tabla nueva de la base de datos, llamada
accidentes_sí, que será con la que se trabajará a partir de
este momento del proyecto.
Por último, se cierra la conexión a la bases de datos
tfm:
dbDisconnect(con)## [1] TRUE
ARRIBAS-BEL, Daniel. KDE for spatial data [en línea]. 2015. Fecha de consulta: 8 de diciembre de 2022. Disponible en: https://gist.github.com/darribas/9109901
BENGOECHEA ISASA, Jose Ignacio. NBA Gap Cleaning [en línea]. 1 julio 2018. Fecha de consulta: 7 de diciembre de 2022. Disponible en: https://github.com/Bengis/nba-gap-cleaning
BERNADÓ MANSILLA, Ester. Contrastes de hipótesis [en línea]. Barcelona: UOC, 2020 Disponible con acceso restringido desde el campus virtual de la UOC.
DALGAARD, Peter. Introductory Statistics with R. 2002, Springer New York, NY. ISBN 978-0-387-22632-3X.
DATANOVIA. Rename Data Frame Columns in R [en línea]. Fecha de consulta: 10 de diciembre de 2022. Disponible en: https://www.datanovia.com/en/lessons/rename-data-frame-columns-in-r/
FERNÁNDEZ DEL VISO, D.S. Correlación [en línea]. 24 de noviembre de 2018. Fecha de consulta: 17 de diciembre de 2022. Disponible en: https://rpubs.com/dsfernandez/442629
FERNÁNDEZ, Freddy y USUGA, Olga. Manual de R [en línea]. 26 de julio de 2021. Fecha de consulta: diciembre de 2022. Disponible en: https://fhernanb.github.io/Manual-de-R/
GIL BELLOSTA, Carlos J. Introducción a ggplot2 y ggmap [en línea]. Barcelona: UOC, sf. Disponible con acceso restringido desde el campus virtual de la UOC.
GOOGLE. RSeek [en línea]. Disponible en: https://rseek.org/
GROLEMUND, Garrett y WICKHAM, Hadley. R for Data Science. [en línea]. 2016, Sebastopol, California : O’Reilly Media. ISBN 978-1-491-91039-9. Disponible en: https://learning.oreilly.com/library/view/mastering-shiny/9781492047377
HAN, Jiawei, KAMBER, Micheline y PEI, Jian. Data Preprocessing. En: ‘Data Mining: Concepts and Techniques’. Morgan Kaufmann. pp. 83-124, 2012. ISBN 978-0-12-381479-1.
J. J. ALLAIRE, Garrett Grolemund y XIE, Yihui. R Markdown: The Definitive Guide. [en línea]. 2018, Boca Raton, Florida : Chapman; Hall/CRC. ISBN 9781138359338. Disponible en: https://bookdown.org/yihui/rmarkdown
KIM, Alex. How to Compare Two Distributions in Practice [en línea]. 25 de noviembre de 2019. Fecha de consulta: 20 de diciembre de 2022. Disponible en: https://towardsdatascience.com/how-to-compare-two-distributions-in-practice-8c676904a285
LOVELL, Christopher. Log-normal fitting and Q-Q plots in R [en línea]. 14 de mayo de 2016. Fecha de consulta: 19 de diciembre de 2021. Disponible en: https://www.christopherlovell.co.uk/blog/2016/05/14/lognormal-fit-QQ-R.html
LUQUE, Pedro. Cómo crear Tablas de información en R Markdown [en línea]. Sevilla: Universidad de Sevilla, 2019. Disponible en: https://www.uv.es/conesa/CursoR/material/Manual-R-commander.pdf
MATHWORKS. lillietest [en línea]. Fecha de consulta: 19 de diciembre de 2022. Disponible en: https://es.mathworks.com/help/stats/lillietest.html
MIT. Nonparametric statistics and model selection [en línea]. Fecha de consulta: 19 de diciembre de 2022. Disponible en: http://www.mit.edu/~6.s085/notes/lecture5.pdf
M. KELMANSKY, Diana. Gráficos Cuantil-Cuantil (Q-Q plots) [en línea]. Fecha de consulta: 19 de diciembre de 2022. Disponible en: http://www.dm.uba.ar/materias/analisis_de_datos/2008/1/teoricas/Teor5.pdf
OLAYINKA, Arimoro. A simple guide on connecting RStudio to a PostgreSQL database [en línea]. Fecha de consulta: 10 de diciembre de 2022. Disponible en: https://medium.com/geekculture/a-simple-guide-on-connecting-rstudio-to-a-postgresql-database-9e35ccdc08be
OSBORNE, Jason W. Data Cleaning Basics: Best Practices in Dealing with Extreme Scores. Newborn and Infant Nursing Reviews. 2010. Vol. 10, n° 1. DOI 10.1053/j.nainr.2009.12.009.
RDRR. ColSums: Form Row and Column Sums and Means [en línea].Fecha de consulta: 12 de diciembre de 2022. Disponible en: https://rdrr.io/r/base/colSums.html
RDRR. Plotly: Create Interactive Web Graphics via ‘plotly.js’ [en línea]. Fecha de consulta: diciembre de 2022. Disponible en: https://plotly.com/r/
ROBIRA ESCOFET, Carles. Contraste de hipótesis [en línea]. Barcelona: UOC, SF. Disponible con acceso restringido desde el campus virtual de la UOC.
RSTUDIO. Guía de estilo para R [en línea]. Fecha de consulta: diciembre de 2022. Disponible en: https://rpubs.com/FvD/guia-estilo-r
RSTUDIO. RStudio Cheatsheets [en línea]. Fecha de consulta: diciembre de 2022. Disponible en: https://www.rstudio.com/resources/cheatsheets/
SQUIRE, Megan. Clean Data. 2015, Packt Publishing Ltd. ISBN 978-1785284014.
SUBIRATS MATÉ, Laia, PÉREZ TRENARD, Diego Oswaldo y CALVO GONZÁLEZ, Mireia, 2019. Introducción a la limpieza y análisis de los datos. [en línea]. Editorial UOC. Disponible en: https://materials.campus.uoc.edu/daisy/Materials/PID_00265704/pdf/PID_00265704.pdf
VANDERPLAS, Jake. Kernel Density Estimation in Python [en línea]. Fecha de consulta: 8 de diciembre de 2022. Disponible en: http://jakevdp.github.io/blog/2013/12/01/kernel-density-estimation/
VENABLES, Bill. [R] plotting the lognormal density curve [en línea]. Fecha de consulta: 19 de diciembre de 2021. Disponible en: https://stat.ethz.ch/pipermail/r-help/2003-April/032058.html
YIHUI XIE, Christophe Dervieux y RIEDERER, Emily. R Markdown Cookbook. [en línea]. 2022, Boca Raton, Florida : Chapman; Hall/CRC. ISBN 9780367563837. Disponible en: https://bookdown.org/yihui/rmarkdown-cookbook/