INTRODUCCIÓN¶
Antecedentes, descripción del proyecto y justificación
La información sobre la presencia de especies es fundamental para comprender los patrones de distribución de la biodiversidad, predecir las respuestas biológicas al cambio climático así como para promover medidas de conservación y gestión apropiadas (Du et al., 2024).
Actualmente, la información de los registros de ocurrencias está disponible en una amplia gama de fuentes, siendo el Global Biodiversity Information Facility (GBIF), una de las redes más importantes de datos de biodiversidad a nivel mundial. Sólo en España, a través de su Portal de Datos de Biodiversidad (https://datos.gbif.es/) se da acceso a más de 57 millones de registros de biodiversidad (datos de enero de 2024), bajo un estándar común que incluye procedimientos de control de calidad, licencias de acceso abierto y mecanismos para dar crédito a las fuentes de los datos (DOIs) (https://gbif.es/). Del mismo modo, importantes iniciativas de ciencia ciudadana como eBird (ebird.org) e iNaturalist (inaturalist.org) se han sumado al proyecto y han impulsado en gran medida el crecimiento de GBIF en los últimos años (Barbe and Otegui, 2016).
Las herramientas informáticas se están volviendo esenciales en la ciencia de la biodiversidad para una mejor gestión, exploración, análisis y presentación de la información biológica y ecológica (Soberon y Peterson, 2004).
Debido a la dificultad a la hora de descubrir patrones en largas bases de datos, como GBIF, surge la demanda de otros métodos de analísis de los datos biológicos (Gadelha et al., 2021). Por otro lado, los investigadores deben ser conscientes de las fortalezas y debilidades de sus datos antes de ser utilizados en el estudio de la biodiversidad.
Como consecuencia, la creciente aplicación del uso de datos de ocurrencias ha ido acompañada de una explosión de enfoques para evaluar y mejorar tanto la accesibilidad de los datos como su calidad y también métodos de análisis que tienen en cuenta las limitaciones específicas asociadas con este tipo de datos (Ball-Damerow et al. 2019, Araújo et al. 2019, Kelling et al. 2019 in Mandevilleet al., 2021).
Python es una excelente herramienta para el análisis de los datos, la computación exploratoria e interactiva, así como en la visualización de datos, lo convierten en una alternativa sólida para las tareas de manipulación de datos (Rodriguez Rivas & Castillo, 2022).
En este proyecto se descargado una base de datos de GBIF para las ocurrencias de especies de anfibios registrados en el territorio español. Se ha utilizado Python para la depuración y limpieza de los datos, así como para la su análisis exploratorio y visualización. Se han analizado los anfibios presentes en España, su vulnerabilidad, así como la distribución de las especies consideradas como amenazadas a partir de datos de ocurrencias. El listado de especies obtenido tras el análisis de los datos se ha comparado con la información oficial disponible en el ministerio del gobierno de España. Se han discutido las limitaciones de los datos, así como su potencialidad para posteriores estudios de la biodiversidad de anfibios.
Objetivos
El objetivo de este proyecto es el desarrollo de un código basado en el lenguaje de progración de Phyton para el preprocesamiento, análisis exploratorio y visualización de una base de datos de libre acceso con las ocurrencias de anfibios en España. Se pretende explorar la calidad y las limitaciones de los datos así como obtener información sobre la biodiversidad de anfibios presentes en España.
MATERIALES Y MÉTODOS¶
Área de estudio
Se considera el área de estudio todo el territorio español.
España es un país europeo que cuenta con una extensión de 505.944 kilómetros cuadrados y que está localizado en la Península Ibérica , Las Islas Canarias, Las Islas Baleares y el norte de África en las ciudades de Ceuta y Melilla.
Está organizada en tres niveles administrativos: comunidad autónoma, provincia y municipio (de mayor a menor). España está formada por 17 comunidades autónomas que se dividen, a su vez, en un total de 52 provincias.
Obtención de los datos de ocurrencia de anfibios
Los datos de ocurrencia de anfibios se obtuvieron a través de del portal Global Biodiversity Information Facility (https://www.gbif.org/es/):
GBIF.org (24 May 2024) GBIF Occurrence Download https://doi.org/10.15468/dl.d4mhdh
En la siguiente imagen se muestran los filtros utilizados:
Mapa base de España
Los mapas base de España utilizados en el mapeo de la distribución de especies vulnerables han sido descargados de https://gadm.org/.
Preprocesamiento y visualización de datos:
Esta fase consistió en:
1.- Importación de librerías y carga de datos
2.- Limpieza y depuración de datos (EDA inicial)
3.- Análisis exploratorio de datos (EDA) y representaciones gráficas
4.- Elaboración de mapas de distribución de especies
1- Importación de librerías y carga de datos
En la primera parte del proyecto se utilzaron las librerías Pandas, matplotlib e ydata_profiling
# Importar librerías para depuración, análisis exploratorio de datos y representaciones gráficas
!pip install pandas
!pip install ydata-profiling
Requirement already satisfied: pandas in /usr/local/lib/python3.10/dist-packages (2.0.3) Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.10/dist-packages (from pandas) (2.8.2) Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas) (2023.4) Requirement already satisfied: tzdata>=2022.1 in /usr/local/lib/python3.10/dist-packages (from pandas) (2024.1) Requirement already satisfied: numpy>=1.21.0 in /usr/local/lib/python3.10/dist-packages (from pandas) (1.25.2) Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.8.2->pandas) (1.16.0) Collecting ydata-profiling Downloading ydata_profiling-4.8.3-py2.py3-none-any.whl (359 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 359.5/359.5 kB 4.6 MB/s eta 0:00:00 Requirement already satisfied: scipy<1.14,>=1.4.1 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (1.11.4) Requirement already satisfied: pandas!=1.4.0,<3,>1.1 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (2.0.3) Requirement already satisfied: matplotlib<3.9,>=3.2 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (3.7.1) Requirement already satisfied: pydantic>=2 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (2.7.2) Requirement already satisfied: PyYAML<6.1,>=5.0.0 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (6.0.1) Requirement already satisfied: jinja2<3.2,>=2.11.1 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (3.1.4) Collecting visions[type_image_path]<0.7.7,>=0.7.5 (from ydata-profiling) Downloading visions-0.7.6-py3-none-any.whl (104 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 104.8/104.8 kB 4.3 MB/s eta 0:00:00 Requirement already satisfied: numpy<2,>=1.16.0 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (1.25.2) Collecting htmlmin==0.1.12 (from ydata-profiling) Downloading htmlmin-0.1.12.tar.gz (19 kB) Preparing metadata (setup.py) ... done Collecting phik<0.13,>=0.11.1 (from ydata-profiling) Downloading phik-0.12.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (686 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 686.1/686.1 kB 7.8 MB/s eta 0:00:00 Requirement already satisfied: requests<3,>=2.24.0 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (2.31.0) Requirement already satisfied: tqdm<5,>=4.48.2 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (4.66.4) Requirement already satisfied: seaborn<0.14,>=0.10.1 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (0.13.1) Collecting multimethod<2,>=1.4 (from ydata-profiling) Downloading multimethod-1.11.2-py3-none-any.whl (10 kB) Requirement already satisfied: statsmodels<1,>=0.13.2 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (0.14.2) Collecting typeguard<5,>=3 (from ydata-profiling) Downloading typeguard-4.3.0-py3-none-any.whl (35 kB) Collecting imagehash==4.3.1 (from ydata-profiling) Downloading ImageHash-4.3.1-py2.py3-none-any.whl (296 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 296.5/296.5 kB 8.7 MB/s eta 0:00:00 Requirement already satisfied: wordcloud>=1.9.1 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (1.9.3) Collecting dacite>=1.8 (from ydata-profiling) Downloading dacite-1.8.1-py3-none-any.whl (14 kB) Requirement already satisfied: numba<1,>=0.56.0 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (0.58.1) Requirement already satisfied: PyWavelets in /usr/local/lib/python3.10/dist-packages (from imagehash==4.3.1->ydata-profiling) (1.6.0) Requirement already satisfied: pillow in /usr/local/lib/python3.10/dist-packages (from imagehash==4.3.1->ydata-profiling) (9.4.0) Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.10/dist-packages (from jinja2<3.2,>=2.11.1->ydata-profiling) (2.1.5) Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (1.2.1) Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (0.12.1) Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (4.52.4) Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (1.4.5) Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (24.0) Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (3.1.2) Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.10/dist-packages (from matplotlib<3.9,>=3.2->ydata-profiling) (2.8.2) Requirement already satisfied: llvmlite<0.42,>=0.41.0dev0 in /usr/local/lib/python3.10/dist-packages (from numba<1,>=0.56.0->ydata-profiling) (0.41.1) Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas!=1.4.0,<3,>1.1->ydata-profiling) (2023.4) Requirement already satisfied: tzdata>=2022.1 in /usr/local/lib/python3.10/dist-packages (from pandas!=1.4.0,<3,>1.1->ydata-profiling) (2024.1) Requirement already satisfied: joblib>=0.14.1 in /usr/local/lib/python3.10/dist-packages (from phik<0.13,>=0.11.1->ydata-profiling) (1.4.2) Requirement already satisfied: annotated-types>=0.4.0 in /usr/local/lib/python3.10/dist-packages (from pydantic>=2->ydata-profiling) (0.7.0) Requirement already satisfied: pydantic-core==2.18.3 in /usr/local/lib/python3.10/dist-packages (from pydantic>=2->ydata-profiling) (2.18.3) Requirement already satisfied: typing-extensions>=4.6.1 in /usr/local/lib/python3.10/dist-packages (from pydantic>=2->ydata-profiling) (4.12.0) Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2.24.0->ydata-profiling) (3.3.2) Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2.24.0->ydata-profiling) (3.7) Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2.24.0->ydata-profiling) (2.0.7) Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2.24.0->ydata-profiling) (2024.2.2) Requirement already satisfied: patsy>=0.5.6 in /usr/local/lib/python3.10/dist-packages (from statsmodels<1,>=0.13.2->ydata-profiling) (0.5.6) Requirement already satisfied: attrs>=19.3.0 in /usr/local/lib/python3.10/dist-packages (from visions[type_image_path]<0.7.7,>=0.7.5->ydata-profiling) (23.2.0) Requirement already satisfied: networkx>=2.4 in /usr/local/lib/python3.10/dist-packages (from visions[type_image_path]<0.7.7,>=0.7.5->ydata-profiling) (3.3) Requirement already satisfied: six in /usr/local/lib/python3.10/dist-packages (from patsy>=0.5.6->statsmodels<1,>=0.13.2->ydata-profiling) (1.16.0) Building wheels for collected packages: htmlmin Building wheel for htmlmin (setup.py) ... done Created wheel for htmlmin: filename=htmlmin-0.1.12-py3-none-any.whl size=27080 sha256=4ec572c83550aed6f22b72ee841ac5d50f6e02e04abdb0f7a15c8e52cb95c408 Stored in directory: /root/.cache/pip/wheels/dd/91/29/a79cecb328d01739e64017b6fb9a1ab9d8cb1853098ec5966d Successfully built htmlmin Installing collected packages: htmlmin, typeguard, multimethod, dacite, imagehash, visions, phik, ydata-profiling Successfully installed dacite-1.8.1 htmlmin-0.1.12 imagehash-4.3.1 multimethod-1.11.2 phik-0.12.4 typeguard-4.3.0 visions-0.7.6 ydata-profiling-4.8.3
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from ydata_profiling import ProfileReport
# Importar datos como dataframe pandas
df = pd.read_csv('anfibios_spain.csv')
2.- Limpieza y depuración de datos (EDA inicial)
Se realizó una limpieza de los datos que consistió en un análisis exploratorio inicial con pandas e ydata_profiling centrado en:
- Análisis de datos duplicados y datos nulos.
- Análisis de variables que no aportan información
- Análisis de registros fuera de los límites del país
Se eliminaron todos los registros y variables que cumplieron los anteriores criterios. De acuerdo con el screening en panda profiling la base de datos de anfibios consta de 223 variables y 28716 observaciones. No hay ningún dato duplicado, pero sí muchas variables que no aportaban información (con alto porcentaje de datos nulos o valores constantes)
Para la creación del dataframe de trabajo selecionaron las siguientes variables: "iucnRedListCategory" (contiene la categoría de vulnerabilidad según IUCN), "level0Name" (Pais: España), "level1Name" (Comunidad Autónoma), "level2Name" (Provincia), "occurrenceID" (identificador de los datos), "decimalLatitude" (coordenada latitudinal), "decimalLongitude" (coordenada longitudinal), "georeferencedDate" (fecha toma coordenadas, equivalente a fecha registro), "species" (especie), "kingdom" (reino), "phylum", "class" (clase), "order" (orden), "family" (familia), "genus" (género), "genericName" (nombre genérico), "acceptedScientificName" (nombre científico).
Se extrajo la información del año de la variable para crear la columna año y ser utilizada en posteriores análisis.
Las coordenadas de las ocurrencias se expresaron en grados decimales (coordenadas sin proyectar) en dos variables, una con la longitud y otra con la latitud.Ambas variables se usaron para la geometría de los geodataframes.
Aunque en este proyecto no se investigaron las redundancias taxonómicas, sí se hizo una comprobación superficial de los datos, obervando que eran coherentes.
#Ver columnas del dataframe (223 columnas en el dataframe bruto, sin depurar)
df.columns
Index(['gbifID', 'accessRights', 'bibliographicCitation', 'language', 'license', 'modified', 'publisher', 'references', 'rightsHolder', 'type', ... 'publishedByGbifRegion', 'level0Gid', 'level0Name', 'level1Gid', 'level1Name', 'level2Gid', 'level2Name', 'level3Gid', 'level3Name', 'iucnRedListCategory'], dtype='object', length=223)
#EDA inicial con ydata_Profiling
nombre = "Observaciones anfibios en España"
profile = ProfileReport(df, title=nombre, explorative=True)
# Mostrar el informe en un notebook (para Jupyter o similares)
profile.to_notebook_iframe()
Summarize dataset: 0%| | 0/5 [00:00<?, ?it/s]
Generate report structure: 0%| | 0/1 [00:00<?, ?it/s]
Render HTML: 0%| | 0/1 [00:00<?, ?it/s]