La base de datos seleccionada contiene extensa información sobre los incendios forestales que han ocurrido en territorio español entre los años 1968 y 2016. Esta ha sido obtenida en la plataforma Kaggle, que es una es una plataforma de ciencia de datos que proporciona acceso de forma libre a una amplia variedad de conjuntos de datos.
A pesar de haber sido extraída de la anterior herramienta, los datos que esta base de datos contiene son proporcionados por el Ministerio para la Transición Ecológica y el Reto Demográfico en su sección ESTADÍSTICA GENERAL DE INCENDIOS FORESTALES (EGIF). En ella se puede tener acceso a los partes remitidos por las comunidades autónomas recogidos en la Base de datos Histórica de EGIF, que es la base de datos nacional de los incendios forestales, iniciada en 1968. Aunque se dispone de información consolidada hasta el año 2021 de diferentes provincias, a nivel nacional, es 2016 el último año consolidado en su totalidad.
Dada la complejidad con la que se presentan los datos desde el Ministerio, se ha optado por escoger la base de datos encontrada en Kaggle.
Descripción
En primer lugar, carguemos las librerías necesarias para manipular el conjunto de datos.
Warning: package 'purrr' was built under R version 4.4.3
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.4 ✔ readr 2.1.5
✔ forcats 1.0.0 ✔ stringr 1.5.1
✔ ggplot2 3.5.1 ✔ tibble 3.2.1
✔ lubridate 1.9.4 ✔ tidyr 1.3.1
✔ purrr 1.0.4
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
Linking to GEOS 3.12.2, GDAL 3.9.3, PROJ 9.4.1; sf_use_s2() is TRUE
Como se puede observar, el conjuntos de datos es muy extenso. Cuenta con un total de 585399 observaciones y 51 columnas. Dado que el objetivo del trabajo es la visualización espacial del área quemada en España por los grandes incendios forestales, vamos a comenzar seleccionando aquellas observaciones que son consideradas “Grandes Incendios Forestales” (>500 Hectáreas), eliminando de esta forma conatos (<1 Ha) e incendios (entre 1 y 500 Ha).
Nos quedamos tan solo con 1876 incendios. Ahora pasemos a observar qué información nos proporcionan algunas de las columnas importantes para nuestra tarea.
Todas ellas parecen ser específicas en lo que representan. Sin embargo, si se quiere obtener más información acerca del significado de los valores que puede tomar cada una de ellas recomiendo entrar en Base de datos Histórica de EGIF o para una interpretación más explicativa en el propio enlace de descarga de Kaggle, donde la autora ha publicado información muy completa sobre ellas.
Antes de hablar sobre algunas de ellas, observemos si alguna de ellas está falta de información y debemos quitarla.
#Observemos la proporción de valores NO NULOS.conteo_NA <-t(data.frame(num_no_NAs =colSums(!is.na(incendios))))round((conteo_NA)/nrow(incendios)*100, 1)
Como podemos observar, el conjunto de datos parece contener mucha información de la mayoría de variables. Sin embargo, hay 6 de ellas que no sobrepasa el 1% de valores no nulos por lo que en la fase de tratamiento eliminaremos estas variables.
Entre el resto que sí que mantendremos podemos destacar el año del incendio, los códigos y nombres de la comunidad autónoma y provincia y el código de municipio (información básica sobre el mismo que podemos presentar en la visualización). Así pues, nos damos cuenta que el nombre del municipio no existe en el conjunto de datos, cuando representa una información importante para observar de una mejor forma donde se produjeron estos incendios.
Como parte esencial del trabajo, necesitamos contar con las coordenadas de cada uno de los incendios. Sin embargo, en vez de proporcionarnos la geometría ideal para observar el área de cada incendio (polígonos), la base de datos nos proporciona coordenadas geográficas (longitud y latitud), por lo que en principio contamos tan solo con puntos. Además, cabe resaltar que el conjunto también nos ofrece “huso”, “x” e “y” (coordenadas en formato UTM) para los puntos de inicio del fuego. Además del resto de columnas que proporcionan información adicional e importante para otros tipos de análisis, será de especial importancia la columna “perdidassuperficiales”, que representa el total de superficie quemada en el incendio en Ha, clave para poder mapear correctamente el área incendiada.
Dicho esto podemos concluir que nuestro conjunto de datos nos presenta principalmente 3 retos para nuestro objetivo:
Obtener aquellos incendios con coordenadas en un formato adecuado para el sistema WGS 84.
Obtener el nombre del municipio afectado para cada incendio.
Configurar una geometría a partir de las columnas existentes que nos permita observar el área afectada por cada uno de los incendios.
Tratamiento
Antes de comenzar con lo que será el grueso del trabajo, eliminemos aquellas columnas comentadas previamente.
Para la visualización de los incendios necesitamos aquellos que nos proporcionan las coordenadas para situarlos. Las dos alternativas que encontramos son:
-1. Incendios con coordenadas geográficas (latitud y longitud), que son la mayoría y los que nos interesan dada su utilidad para mapear.
-2. Incedios sin coordenadas geográficas pero con coordenadas en formato UTM que indican donde se originó el fuego.
#Seleccionamos solo aquellas observaciones que nos proporcionan coordenadadas geográficasincendios_con_coords <- incendios[(!is.na(incendios$longitud) &!is.na(incendios$latitud)),]#Observamos que tenemos 1210 incendios y todos ellos son posteriores a 1982 (desde 1968 hasta 1963 no registraban las coordenadas de los incendios).#Ahora seleccionamos aquellas observaciones que no tienen coordenadas geográficas pero sí en formato UTM sobre el inicio del fuego.incendios_sin_coords <- incendios[(is.na(incendios$longitud) &!is.na(incendios$x)) ,] #Todos las que tienen "x", tienen "y" y huso.#Un total de 16.
Aquellos incendios con coordenadas geográficas podemos situarlos fácilmente dado que tenemos las coordenadas necesarias para crear objetos sf con el sistema WGS 84. Sin embargo, de aquellas observaciones que solo conocemos las coordenadas en formato UTM debemos obtener su latitud y longitud.
#Añadimos la columna EPSG según el huso de cada incendioincendios_sin_coords <- incendios_sin_coords %>%mutate(epsg =as.integer(paste0("326", huso)))#Obtenemos las coordenadas transformadas en latitud y longitud con un bucle.for (i in (1:nrow(incendios_sin_coords))) { sf_obs <-st_as_sf(incendios_sin_coords[i, ], coords =c("x", "y"), crs = incendios_sin_coords$epsg[i])# Creamos un objeto sf para la observación actual sf_obs_transformado <-st_transform(sf_obs, crs =4326) coords <-st_coordinates(sf_obs_transformado) #Extraemos las coordenadas transformadas incendios_sin_coords$longitud[i] = coords[1] incendios_sin_coords$latitud[i] = coords[2]}#Eliminamosla columna creada anteriormente "EPSG"incendios_sin_coords <- incendios_sin_coords %>%select(-epsg)
Ahora que todas nuestras observaciones tienen coordenadas adecuadas debemos añadir el nombre del municipio. Empecemos por aquellos incendios de los que acabamos de obtener latitud y longitud.
#Antes de obtener el nombre, observamos que necesitamos corregir el código del municipio de estas observaciones dado que los que tienen actualmente no existen.incendios_sin_coords$idmunicipio
#En primer lugar cargamos el dataset con los municipios en España para poder situar cada punto en uno de ellos.spain_mun <- mapSpain::esp_get_munic()spain_mun <-st_transform(spain_mun, crs=4326)#Creamos el objeto sf de los puntos con la longitud y latitud obtenidas previamenteincendios_sin_coords_sf <-st_as_sf(incendios_sin_coords, coords =c("longitud", "latitud"), crs =4326)#Lo interseccionamos con los municipiosincendios_sin_coords_mun <-st_intersection(spain_mun, incendios_sin_coords_sf)
Warning: attribute variables are assumed to be spatially constant throughout
all geometries
Tras realizar la intersección observamos que hay dos incendios que han desaparecido. Esto debe ser debido a que las coordenadas no se enuentran dentro de los límites de España. Comprobémoslo con un mapa.
leaflet() %>%addTiles() %>%addCircles(data=incendios_sin_coords_sf, color ="black")
Tal y como vemos hay dos incendios identificados en Zamora y Cáceres que se iniciaron en Portugal. Dado que no tenemos por tanto el municipio en el que comenzaron no podemos asignar ninguno en concreto así que estas dos observaciones se van a añadir al dataset con los otros 1210 con el único inconveniente que no podremos saber el municipio, solo la provincia y comunidad a la que afectaron.
#Los identificamosincendios_portugal <- incendios_sin_coords %>%filter(idpif ==959488| idpif ==956595)#Ponemos como no conocido el municipio mal asignado inicialmenteincendios_portugal$idmunicipio=NA#Los añadimos a los incendios con coordenadasincendios_con_coords <-rbind(incendios_con_coords, incendios_portugal)
Además de este hecho observamos que el municipio que obtenemos a partir de las coordenadas donde se inició el incendio no se encuentra en la provincia que teníamos en el dataset original.
Simple feature collection with 14 features and 2 fields
Geometry type: POINT
Dimension: XY
Bounding box: xmin: -8.436426 ymin: 37.51362 xmax: 2.712784 ymax: 42.54299
Geodetic CRS: WGS 84
First 10 features:
ine.prov.name provincia geometry
4460 Madrid Toledo POINT (-4.425469 40.28462)
5517 Salamanca Caceres POINT (-6.415577 40.45754)
1661 Cáceres Caceres POINT (-7.140159 39.39377)
1028 Barcelona Girona POINT (2.712784 41.69452)
3261 Huelva Sevilla POINT (-6.386817 37.51362)
1749 Cáceres Toledo POINT (-5.023756 39.44766)
5288 Pontevedra Pontevedra POINT (-8.436426 42.54299)
1643 Cáceres Toledo POINT (-5.236421 39.62811)
2900 Guadalajara Soria POINT (-2.430068 41.0528)
4912 Ourense Ourense POINT (-7.991608 41.87453)
Tras investigar sobre ellos hemos encontrado que estos 14 incendios se dieron en varias zonas de distintas provincias. En estos el fuego atravesó en todos ellos más de 1 municipio que marcan frontera entre provincias por lo que tal vez es por ello por lo que estos incendios no tenían coordenadas ni municipio asignado. Para resolver esto y asignar una localidad a cada municipio utilizaremos el municipio de origen del fuego (el obtenido con la intersección) y asignaremos como provincia y comunidad las correspondientes a este municipio.
#Para la comunidadincendios_sin_coords_mun$idcomunidad <- incendios_sin_coords_mun$codautoincendios_sin_coords_mun$comunidad <- incendios_sin_coords_mun$ine.ccaa.name#Para la provinciaincendios_sin_coords_mun$idprovincia <- incendios_sin_coords_mun$cproincendios_sin_coords_mun$provincia <- incendios_sin_coords_mun$ine.prov.name#Para el municipioincendios_sin_coords_mun$idmunicipio <- incendios_sin_coords_mun$cmunincendios_sin_coords_mun$municipio <- incendios_sin_coords_mun$name #No teníamos una columna para el nombre del municipio así que la creamos.#Eliminamos aquellas columnas del objeto de municipios que ya hemos utilizado para obtener el municipio, la provincia y la comunidad.incendios_sin_coords_mun <- incendios_sin_coords_mun[,-c(0:7)]
Ya hemos arreglado aquellos incendios que no tenían coordenadas geográficas y hemos obtenido el nombre y código correctos de su municipio, provincia y comunidad. Ahora vamos a obtener el nombre del municipio para aquellas observaciones que sí que tenían coordenadas y por tanto el código de municipio, provincia y comunidad bien asignado.
#Creamos el objeto sf para la intersecciónincendios_con_coords_sf <-st_as_sf(incendios_con_coords, coords =c("longitud", "latitud"), crs =4326)#Hacemos un join del conjunto de datos con los municipios y los incendiosincendios_con_coords_mun <-st_join(incendios_con_coords_sf, spain_mun)#Renombramos la columna con el nombre del municipio, eliminamos aquellas columnas de nuestro dataset duplicadas y nos quedamos solo con el nombre del municipio, que es lo que nos faltaba. Lo situamos en la posición en la que se encontraba en el el otro conjunto de datos (la última).incendios_con_coords_mun <- incendios_con_coords_mun%>%rename(municipio=name)%>%select(-ine.ccaa.name, -codauto, -ine.prov.name, -cpro, -cmun, -LAU_CODE)%>%relocate(geometry, .before=municipio)
Ahora que ambos datasets tienen las mismas columnas en el mismo orden (incluido el nombre del municipio) y ambos tienen sus correspondientes geometrías en puntos podemos unirlos.
Ya hemos convertido en puntos las coordenadas geográficas, salvado aquellos incendios de los que solo conocíamos sus coordenadas en formato UTM (también corregido su municipio) y obtenido el nombre del municipio al que afectaron o en el que se iniciaron. El siguiente objetivo es obtener el área que devastaron. Como esto es imposible dado que no tenemos una geometría como un polígono que nos ayude, vamos a crear un buffer alrededor de los puntos.
El radio empleado para ello va a utilizar la columna perdidassuperficiales, que representa el número de hectáreas quemadas. Dado que el área de un círculo es:
\[ A = \pi r^2 \] La fórmula para obtener el radio de cada incendio será: \[ r = \sqrt{\frac{A}{\pi}} \] siendo A = “perdidassuperficiales”.
#Creamos la nueva variable para el radio del incendio en m2.incendios_area <- incendios %>%mutate(radio =sqrt(perdidassuperficiales *10000/ pi))#Activamos la opción para que las operaciones geométricas se efectúen en metrossf_use_s2(TRUE)#Creamos el nuevo objeto sf que tiene como geometría un polígono en forma de círculo que representa el área real devastada.incendios_area <-st_buffer(incendios_area, dist = incendios_area$radio)#Eliminamos la columna creada "radio" necesaria para crear el polígonoincendios_area <- incendios_area %>%select(-radio)
Output
A pesar de que durante el tratamiento se han detectado nuevos problemas distintos a los previamente encontrados en la fase de detección, finalmente se han conseguido los objetivos que nos planteamos inicialmente. En primer lugar, hemos eliminado aquellas columnas que no aportaban apenas información. Hemos podido encontrar el nombre del municipio para aquellas observaciones que ya disponían de él y corregido el municipio, provincia y comunidad para otras observaciones que no era correcto. Finalmente, hemos podido crear una geometría que nos permitiera reflejar sobre el mapa el área real afectada por los distintos incendios.