Proyecto de Investigación:¶

Análisis de la diversidad de anfibios en España a partir de datos de biodiversidad primarios¶

PYTHON PARA CIENCIA DE DATOS

Instituto Tecnológico de Costa Rica (ITCR) y redbioma.

Participantes: Ana Fandiño Carro

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:

image.png

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

In [ ]:
# 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
In [ ]:
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from ydata_profiling import ProfileReport
In [ ]:
# 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.

In [ ]:
#Ver columnas del dataframe (223 columnas en el dataframe bruto, sin depurar)
df.columns
Out[ ]:
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)
In [ ]:
#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]
In [ ]:
profile.to_file("anfibios_España.html")
/usr/local/lib/python3.10/dist-packages/ydata_profiling/profile_report.py:363: UserWarning: Try running command: 'pip install --upgrade Pillow' to avoid ValueError
  warnings.warn(
Export report to file:   0%|          | 0/1 [00:00<?, ?it/s]
In [ ]:
# Se hace una lista con el nombre de las columnas seleccionadas y se seleccionan en 1 nuevo dataframe
headers = [
    "iucnRedListCategory" , "level0Name", "level1Name", "level2Name", "occurrenceID", "decimalLatitude", "decimalLongitude", "georeferencedDate", "species", "kingdom", "phylum", "class", "order", "family", "genus", "genericName", "acceptedScientificName"
    ]
df_seleccion = df[headers]


#Compruebo número columans y número datos antes selección
print("Antes: ", df.shape)

df = df_seleccion
print("Después: ", df.shape)
Antes:  (28716, 223)
Después:  (28716, 17)
In [ ]:
#level1Name es la Comunidad Autónoma. La mayor división administrativa de España.
#España consta de 19 CCAA y en el dataframe aparecen más.
df["level1Name"].describe()
Out[ ]:
count               27954
unique                 34
top       Castilla y León
freq                 5508
Name: level1Name, dtype: object
In [ ]:
#Se imprimen los nombres de las comunidades autónomas para comprobar los errores
df["level1Name"].unique()
Out[ ]:
array(['Andalucía', 'Castilla-La Mancha', 'Extremadura',
       'Castilla y León', 'Comunidad de Madrid', nan, 'Cataluña', 'Faro',
       'Occitanie', 'Comunidad Valenciana', 'Aragón',
       'Comunidad Foral de Navarra', 'Nouvelle-Aquitaine', 'La Rioja',
       'País Vasco', 'Principado de Asturias', 'Cantabria', 'Bragança',
       'Galicia', 'Vila Real', 'Guarda', 'Viana do Castelo',
       'Castelo Branco', 'Región de Murcia', 'Portalegre', 'Braga',
       'Beja', 'Ceuta y Melilla', 'Islas Baleares', 'Islas Canarias',
       'Escaldes-Engordany', 'La Massana', 'Sant Julià de Lòria',
       'Malatya', 'Évora'], dtype=object)
In [ ]:
#Se hace un dataframe con los datos que corresponden con nombres que son CCAA de España
ccaa = ['Andalucía', 'Castilla-La Mancha', 'Extremadura', 'Castilla y León',
        'Comunidad de Madrid', 'Cataluña', 'Comunidad Valenciana', 'Aragón',
        'Comunidad Foral de Navarra', 'La Rioja', 'País Vasco',
        'Principado de Asturias', 'Cantabria', 'Galicia', 'Región de Murcia',
        'Ceuta y Melilla', 'Islas Baleares', 'Islas Canarias',
       ]
condition = df["level1Name"].isin(ccaa)
ccaa_df = df[condition]
ccaa_df
Out[ ]:
iucnRedListCategory level0Name level1Name level2Name occurrenceID decimalLatitude decimalLongitude georeferencedDate species kingdom phylum class order family genus genericName acceptedScientificName
0 NT Spain Andalucía Jaén 29607 38.08 -3.97 1/1/2010 Triturus pygmaeus Animalia Chordata Amphibia Caudata Salamandridae Triturus Triturus Triturus pygmaeus (Wolterstorff, 1905)
1 NT Spain Castilla-La Mancha Ciudad Real 29606 38.80 -4.09 1/1/2002 Triturus pygmaeus Animalia Chordata Amphibia Caudata Salamandridae Triturus Triturus Triturus pygmaeus (Wolterstorff, 1905)
2 NT Spain Andalucía Jaén 29628 38.35 -3.29 1/1/2006 Triturus pygmaeus Animalia Chordata Amphibia Caudata Salamandridae Triturus Triturus Triturus pygmaeus (Wolterstorff, 1905)
3 NT Spain Castilla-La Mancha Toledo 29679 40.23 -4.70 1/1/2004 Triturus pygmaeus Animalia Chordata Amphibia Caudata Salamandridae Triturus Triturus Triturus pygmaeus (Wolterstorff, 1905)
4 NT Spain Castilla-La Mancha Ciudad Real 29627 38.62 -3.40 1/1/2002 Triturus pygmaeus Animalia Chordata Amphibia Caudata Salamandridae Triturus Triturus Triturus pygmaeus (Wolterstorff, 1905)
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
28709 LC Spain Andalucía Córdoba 21 38.43 -4.78 1/1/2002 Alytes cisternasii Animalia Chordata Amphibia Anura Alytidae Alytes Alytes Alytes cisternasii Boscá, 1879
28711 LC Spain Cataluña Barcelona 18 41.77 2.22 1/1/2002 Alytes obstetricans Animalia Chordata Amphibia Anura Alytidae Alytes Alytes Alytes obstetricans (Laurenti, 1768)
28713 LC Spain Castilla-La Mancha Ciudad Real 23 38.70 -4.78 1/1/2002 Alytes cisternasii Animalia Chordata Amphibia Anura Alytidae Alytes Alytes Alytes cisternasii Boscá, 1879
28714 LC Spain Castilla-La Mancha Ciudad Real 22 38.61 -4.78 1/1/2002 Alytes cisternasii Animalia Chordata Amphibia Anura Alytidae Alytes Alytes Alytes cisternasii Boscá, 1879
28715 LC Spain Cataluña Barcelona 20 41.95 2.22 1/1/2007 Alytes obstetricans Animalia Chordata Amphibia Anura Alytidae Alytes Alytes Alytes obstetricans (Laurenti, 1768)

27449 rows × 17 columns

In [ ]:
df = ccaa_df
In [ ]:
# Se comprueba si los datos "level2Name" son correctos. España tiene 52 provincias. Coincide
df["level2Name"].describe()
Out[ ]:
count       27449
unique         52
top       Badajoz
freq         1340
Name: level2Name, dtype: object
In [ ]:
#Se exploran las categorías de vulnerabilidad presentes en los datos
df["iucnRedListCategory"].describe()
Out[ ]:
count     27449
unique        6
top          LC
freq      23218
Name: iucnRedListCategory, dtype: object
In [ ]:
df["iucnRedListCategory"].unique()
Out[ ]:
array(['NT', 'LC', 'VU', 'EN', 'NE', 'CR'], dtype=object)
In [ ]:
# Convertir la variable georeferencedDate a datetime
new_df = df.copy()
new_df['georeferencedDate'] = pd.to_datetime(new_df['georeferencedDate'])

# Extraer el año y crear una nueva columna
new_df['year'] = new_df['georeferencedDate'].dt.year

# Mostrar el DataFrame
display(new_df[['year','georeferencedDate']])
year georeferencedDate
0 2010 2010-01-01
1 2002 2002-01-01
2 2006 2006-01-01
3 2004 2004-01-01
4 2002 2002-01-01
... ... ...
28709 2002 2002-01-01
28711 2002 2002-01-01
28713 2002 2002-01-01
28714 2002 2002-01-01
28715 2007 2007-01-01

27449 rows × 2 columns

In [ ]:
df = new_df
In [ ]:
# Información sobre tipos de datos y valores no nulos
df.info()
<class 'pandas.core.frame.DataFrame'>
Index: 27449 entries, 0 to 28715
Data columns (total 18 columns):
 #   Column                  Non-Null Count  Dtype         
---  ------                  --------------  -----         
 0   iucnRedListCategory     27449 non-null  object        
 1   level0Name              27449 non-null  object        
 2   level1Name              27449 non-null  object        
 3   level2Name              27449 non-null  object        
 4   occurrenceID            27449 non-null  int64         
 5   decimalLatitude         27449 non-null  float64       
 6   decimalLongitude        27449 non-null  float64       
 7   georeferencedDate       27449 non-null  datetime64[ns]
 8   species                 27449 non-null  object        
 9   kingdom                 27449 non-null  object        
 10  phylum                  27449 non-null  object        
 11  class                   27449 non-null  object        
 12  order                   27449 non-null  object        
 13  family                  27449 non-null  object        
 14  genus                   27449 non-null  object        
 15  genericName             27449 non-null  object        
 16  acceptedScientificName  27449 non-null  object        
 17  year                    27449 non-null  int32         
dtypes: datetime64[ns](1), float64(2), int32(1), int64(1), object(13)
memory usage: 4.9+ MB
In [ ]:
# Encontrar duplicados, considerando todas las columnas
duplicates = df.duplicated(keep=False)  # keep=False marca todos los duplicados
print("\nFilas duplicadas:")
df[duplicates]
Filas duplicadas:
Out[ ]:
iucnRedListCategory level0Name level1Name level2Name occurrenceID decimalLatitude decimalLongitude georeferencedDate species kingdom phylum class order family genus genericName acceptedScientificName year

3.-Análisis Exploratorio de Datos (EDA) y representaciones gráficas

Para el análisis exploratorio de los datos se utilizó la librería Pandas y para la representaciones gráficas la librería Matplotlib

Se investigaron tres niveles taxonómicos: orden, familia y especie

  • Órdenes de anfibios presentes en España: número de órdenes, nombre (taxonomía) y número de ocurrencias de cada orden. Se identificaron las familias y especies pertenecientes cada orden. Se representó gráficamente el porcentaje de ocurrencia de cada orden de anfibios en un diagrama de sectores.

  • Familias de anfibios presentes en España: número de familias nombre (taxonomía) y número de ocurrencias de cada familia. Se identificaron las especies pertenecientes cada familia. Se representó gráficamente el número de ocurrencias de cada familia de anfibios en un diagrama de barras.

  • Especies de anfibios presentes en España: número de especies, nombre (taxonomía) y número de ocurrencias de cada especie. Se análizó el número de especies presentes en cada comunidad autónoma (distribución de la riqueza de especies en el territorio) y se representó gráficamente en un diagrama de barras. Se estudió la vulnerabilidad de las especies: número de especies pertenecientes a cada categoría IUCN, lista de especies pertenecientes a cada categoría IUCN y número de ocurrencias.

A nivel territorial, se analizó la distribución de las observaciones por comunidad autónoma y se representó gráficamente en un diagrama de sectores.

A nivel temporal, se investigó el número de ocurrencias por año y se representó en un diagrama de sectores y un diagrama de barras. Finalmente, se hizo una selección de las especies de interés de acuerdo con su vulnerabilidad basado en la información oficial disponible en las páginas web del Ministerio de España y se visualizó su distribución gráficamente en mapas con Geopandas.

Órdenes de anfibios y su frecuencia

In [ ]:
df["order"].unique()
Out[ ]:
array(['Caudata', 'Anura'], dtype=object)
In [ ]:
df.order.describe()
Out[ ]:
count     27449
unique        2
top       Anura
freq      21268
Name: order, dtype: object
In [ ]:
order_data = df.groupby('order').nunique()
order_data
Out[ ]:
iucnRedListCategory level0Name level1Name level2Name occurrenceID decimalLatitude decimalLongitude georeferencedDate species kingdom phylum class family genus genericName acceptedScientificName year
order
Anura 4 1 18 52 21268 427 827 43 25 1 1 1 8 13 10 25 43
Caudata 4 1 16 48 6181 386 636 38 12 1 1 1 1 8 9 12 38
In [ ]:
order_fam = df.groupby('order')['family'].value_counts()

order_fam
Out[ ]:
order    family       
Anura    Ranidae          9212
         Alytidae         4014
         Bufonidae        3125
         Hylidae          1873
         Pelobatidae      1585
         Pelodytidae      1457
         Dendrobatidae       1
         Pipidae             1
Caudata  Salamandridae    6181
Name: count, dtype: int64
In [ ]:
order_sp = df.groupby('order')['species'].value_counts()

order_sp
Out[ ]:
order    species                
Anura    Pelophylax perezi          8215
         Epidalea calamita          3079
         Alytes obstetricans        1779
         Pelobates cultripes        1585
         Pelodytes punctatus        1094
         Hyla arborea                979
         Hyla meridionalis           894
         Discoglossus galganoi       776
         Alytes cisternasii          684
         Discoglossus jeanneae       547
         Rana temporaria             470
         Rana iberica                463
         Pelodytes ibericus          363
         Alytes dickhilleni          171
         Discoglossus pictus          49
         Bufotes viridis              42
         Rana dalmatina               34
         Rana pyrenaica               25
         Alytes muletensis             6
         Pelophylax saharicus          4
         Sclerophrys mauritanica       4
         Discoglossus scovazzi         2
         Oophaga pumilio               1
         Lithobates catesbeianus       1
         Xenopus laevis                1
Caudata  Salamandra salamandra      1375
         Pleurodeles waltl          1269
         Triturus marmoratus        1015
         Lissotriton boscai          803
         Lissotriton helveticus      589
         Triturus pygmaeus           521
         Calotriton asper            344
         Chioglossa lusitanica       149
         Ichthyosaura alpestris      112
         Cynops pyrrhogaster           2
         Calotriton arnoldi            1
         Salamandra algira             1
Name: count, dtype: int64
In [ ]:
# Contar las ocurrencias de cada valor único en la columna 'orden'
order_counts = df['order'].value_counts()
order_counts
Out[ ]:
order
Anura      21268
Caudata     6181
Name: count, dtype: int64
In [ ]:
# Agrupar datos por orden y obtener el número total de observaciones
order_obs = df.groupby('order')['occurrenceID'].nunique()
order_obs
Out[ ]:
order
Anura      21268
Caudata     6181
Name: occurrenceID, dtype: int64
In [ ]:
# Contar las ocurrencias de cada valor único en la columna 'orden'
order_counts = df['order'].value_counts()
order_counts

# Tamaño del gráfico
plt.figure(figsize=(6, 6))

# Crear la gráfica de pastel
plt.pie(order_counts, labels=order_counts.index, autopct='%1.1f%%')

# Título del gráfico
plt.title('Distribución de los ordenes de anfibios en España')

plt.show()
No description has been provided for this image
In [ ]:
# Tamaño del gráfico
plt.figure(figsize=(6, 6))

# Agrupar datos por orden y obtener el número total de observaciones
order_counts = df.groupby('order')['occurrenceID'].nunique()

# Crear gráfico de barras
# sepal_mean.plot(kind='bar')
order_counts.plot(kind='barh')

# Título del gráfico
plt.title('Número de observaciones por Orden anfibio')

# Etiqueta del eje Y
plt.ylabel('Orden anfibio')

# Etiqueta del eje X
plt.xlabel('Número de observaciones')
plt.grid()
plt.show()
No description has been provided for this image

Familias de anfibios

In [ ]:
df['family'].unique()
Out[ ]:
array(['Salamandridae', 'Pipidae', 'Ranidae', 'Pelodytidae',
       'Pelobatidae', 'Hylidae', 'Alytidae', 'Dendrobatidae', 'Bufonidae'],
      dtype=object)
In [ ]:
df['family'].describe()
Out[ ]:
count       27449
unique          9
top       Ranidae
freq         9212
Name: family, dtype: object
In [ ]:
# Contar las ocurrencias de cada valor único en la columna 'family'
family_counts = df['family'].value_counts()
family_counts
Out[ ]:
family
Ranidae          9212
Salamandridae    6181
Alytidae         4014
Bufonidae        3125
Hylidae          1873
Pelobatidae      1585
Pelodytidae      1457
Pipidae             1
Dendrobatidae       1
Name: count, dtype: int64
In [ ]:
# Agrupar datos por familia y obtener el número total de observaciones
family_obs = df.groupby('family')['occurrenceID'].nunique()
family_obs
Out[ ]:
family
Alytidae         4014
Bufonidae        3125
Dendrobatidae       1
Hylidae          1873
Pelobatidae      1585
Pelodytidae      1457
Pipidae             1
Ranidae          9212
Salamandridae    6181
Name: occurrenceID, dtype: int64
In [ ]:
# Contar las ocurrencias de cada valor único en la columna 'family'
family_counts = df['family'].value_counts()
family_counts

# Tamaño del gráfico
plt.figure(figsize=(6, 6))

# Crear la gráfica de pastel
plt.pie(family_counts, labels=family_counts.index, autopct='%1.1f%%')

# Título del gráfico
plt.title('Distribución de las familias de anfibios en España')

plt.show()
No description has been provided for this image
In [ ]:
# Tamaño del gráfico
plt.figure(figsize=(6, 6))

# Agrupar datos por familia y obtener el número total de observaciones
family_obs = df.groupby('family')['occurrenceID'].nunique()

# Crear gráfico de barras
# sepal_mean.plot(kind='bar')
family_obs.plot(kind='barh')

# Título del gráfico
plt.title('Número de observaciones por Familia anfibios')

# Etiqueta del eje Y
plt.ylabel('Familia anfibios')

# Etiqueta del eje X
plt.xlabel('Número de observaciones')
plt.grid()
plt.show()
No description has been provided for this image

Especies de anfibios

In [ ]:
df['species'].describe()
Out[ ]:
count                 27449
unique                   37
top       Pelophylax perezi
freq                   8215
Name: species, dtype: object
In [ ]:
df['acceptedScientificName'].describe() #coincide
Out[ ]:
count                                      27449
unique                                        37
top       Pelophylax perezi (López-Seoane, 1885)
freq                                        8215
Name: acceptedScientificName, dtype: object
In [ ]:
df['species'].unique()
Out[ ]:
array(['Triturus pygmaeus', 'Triturus marmoratus',
       'Salamandra salamandra', 'Xenopus laevis', 'Rana temporaria',
       'Salamandra algira', 'Pelophylax perezi', 'Rana pyrenaica',
       'Pelophylax saharicus', 'Rana iberica', 'Rana dalmatina',
       'Pleurodeles waltl', 'Lithobates catesbeianus',
       'Pelodytes punctatus', 'Pelodytes ibericus', 'Pelobates cultripes',
       'Ichthyosaura alpestris', 'Lissotriton helveticus',
       'Lissotriton boscai', 'Hyla meridionalis', 'Hyla arborea',
       'Calotriton asper', 'Discoglossus jeanneae',
       'Discoglossus scovazzi', 'Discoglossus galganoi',
       'Discoglossus pictus', 'Chioglossa lusitanica',
       'Cynops pyrrhogaster', 'Oophaga pumilio', 'Bufotes viridis',
       'Calotriton arnoldi', 'Epidalea calamita',
       'Sclerophrys mauritanica', 'Alytes obstetricans',
       'Alytes muletensis', 'Alytes dickhilleni', 'Alytes cisternasii'],
      dtype=object)
In [ ]:
especie_names = df.groupby('genericName')['species'].value_counts()
especie_names
Out[ ]:
genericName   species                
Alytes        Alytes obstetricans        1779
              Alytes cisternasii          684
              Alytes dickhilleni          171
              Alytes muletensis             6
Bufo          Epidalea calamita          3079
              Bufotes viridis              42
              Sclerophrys mauritanica       4
Calotriton    Calotriton asper            180
              Calotriton arnoldi            1
Chioglossa    Chioglossa lusitanica       149
Cynops        Cynops pyrrhogaster           2
Dendrobates   Oophaga pumilio               1
Discoglossus  Discoglossus galganoi       776
              Discoglossus jeanneae       547
              Discoglossus pictus          49
              Discoglossus scovazzi         2
Euproctus     Calotriton asper            164
Hyla          Hyla arborea                979
              Hyla meridionalis           894
Lissotriton   Lissotriton boscai          803
              Lissotriton helveticus      589
Mesotriton    Ichthyosaura alpestris      112
Pelobates     Pelobates cultripes        1585
Pelodytes     Pelodytes punctatus        1094
              Pelodytes ibericus          363
Pelophylax    Pelophylax perezi          4245
Pleurodeles   Pleurodeles waltl          1269
Rana          Pelophylax perezi          3970
              Rana temporaria             470
              Rana iberica                463
              Rana dalmatina               34
              Rana pyrenaica               25
              Pelophylax saharicus          4
              Lithobates catesbeianus       1
Salamandra    Salamandra salamandra      1375
              Salamandra algira             1
Triturus      Triturus marmoratus        1015
              Triturus pygmaeus           521
Xenopus       Xenopus laevis                1
Name: count, dtype: int64
In [ ]:
ccaa_agrupado = df.groupby('level1Name')

# Agrupar datos por provincia y obtener número de species (riqueza)
species_count = ccaa_agrupado['species'].nunique()
species_count
Out[ ]:
level1Name
Andalucía                     21
Aragón                        15
Cantabria                     11
Castilla y León               21
Castilla-La Mancha            18
Cataluña                      16
Ceuta y Melilla                7
Comunidad Foral de Navarra    18
Comunidad Valenciana           8
Comunidad de Madrid           17
Extremadura                   16
Galicia                       13
Islas Baleares                 6
Islas Canarias                 3
La Rioja                      13
País Vasco                    19
Principado de Asturias        13
Región de Murcia              11
Name: species, dtype: int64
In [ ]:
# Crear gráfico de barras
species_count.plot(kind='barh')

# Título del gráfico
plt.title('Nº de especies por Comunidad Autónoma')

# Etiqueta del eje Y
plt.ylabel('Comunidad Autónoma')

# Etiqueta del eje X
plt.xlabel('Número de especies')
plt.grid()
plt.show()
No description has been provided for this image
In [ ]:
# Comunidad autónoma con mayor número de obervaciones
# Contar las ocurrencias de cada valor único en la columna 'ccaa'
ccaa_counts = df['level1Name'].value_counts()
ccaa_counts

# Tamaño del gráfico
plt.figure(figsize=(6, 6))

# Crear la gráfica de pastel
plt.pie(ccaa_counts, labels= ccaa_counts.index, autopct='%1.1f%%')

# Título del gráfico
plt.title('Distribución de las observaciones por Comunidad Autónoma')

plt.show()
No description has been provided for this image
In [ ]:
# Año con mayor número de obervaciones
# Contar las ocurrencias de cada valor único en la columna 'año'
year_counts = df['year'].value_counts()
year_counts

# Tamaño del gráfico
plt.figure(figsize=(6, 6))

# Crear la gráfica de pastel
plt.pie(year_counts, labels= year_counts.index, autopct='%1.1f%%')

# Título del gráfico
plt.title('Distribución de las observaciones por año')

plt.show()
No description has been provided for this image
In [ ]:
# Crear gráfico de barras
year_counts.plot(kind='bar')

# Título del gráfico
plt.title('Nº de observaciones por año')

# Etiqueta del eje Y
plt.ylabel('Número de observaciones')

# Etiqueta del eje X
plt.xlabel('Año')
plt.grid()
plt.show()
No description has been provided for this image
In [ ]:
year_agrupado = df.groupby('year')
year_agrupado['occurrenceID'].count()
Out[ ]:
year
1934        1
1965        1
1968        1
1970        1
1971        2
1972        3
1973        1
1974        3
1975        5
1976        1
1977        6
1978        7
1979       10
1980       24
1981       11
1982        5
1983       35
1984       24
1985       35
1986       20
1987       35
1988       44
1989       23
1990      140
1991       27
1992       34
1993      221
1994      186
1995      451
1996       59
1997      246
1998      211
1999      131
2000      318
2001      606
2002    17789
2003      915
2004      586
2005     1223
2006      831
2007      545
2008      393
2009      469
2010      751
2011     1018
2024        1
Name: occurrenceID, dtype: int64
In [ ]:
iucn_agrupado = df.groupby('iucnRedListCategory')

# Agrupar datos por código iucn y obtener número de species pertenecientes a cada categoría
iucn_especies = iucn_agrupado['species'].nunique()
iucn_especies
Out[ ]:
iucnRedListCategory
CR     1
EN     3
LC    24
NE     2
NT     4
VU     3
Name: species, dtype: int64
In [ ]:
iucn_especies.sum() #Son 37. Es decir, ninguna especie tiene dos categorías IUCN (correcto)
Out[ ]:
37
In [ ]:
# Agrupar datos por código iunc y obtener lista de especies pertenecientes a cada categoría
species_vulnerability = df.groupby('iucnRedListCategory')['species'].value_counts()
species_vulnerability
Out[ ]:
iucnRedListCategory  species                
CR                   Calotriton arnoldi            1
EN                   Alytes dickhilleni          171
                     Rana pyrenaica               25
                     Alytes muletensis             6
LC                   Pelophylax perezi          8215
                     Epidalea calamita          3079
                     Alytes obstetricans        1779
                     Salamandra salamandra      1375
                     Pelodytes punctatus        1094
                     Triturus marmoratus        1015
                     Hyla arborea                979
                     Hyla meridionalis           894
                     Lissotriton boscai          803
                     Discoglossus galganoi       776
                     Alytes cisternasii          684
                     Lissotriton helveticus      589
                     Discoglossus jeanneae       547
                     Rana temporaria             470
                     Pelodytes ibericus          363
                     Calotriton asper            344
                     Ichthyosaura alpestris      112
                     Discoglossus pictus          49
                     Bufotes viridis              42
                     Sclerophrys mauritanica       4
                     Discoglossus scovazzi         2
                     Lithobates catesbeianus       1
                     Xenopus laevis                1
                     Oophaga pumilio               1
NE                   Rana dalmatina               34
                     Pelophylax saharicus          4
NT                   Pleurodeles waltl          1269
                     Triturus pygmaeus           521
                     Chioglossa lusitanica       149
                     Cynops pyrrhogaster           2
VU                   Pelobates cultripes        1585
                     Rana iberica                463
                     Salamandra algira             1
Name: count, dtype: int64
In [ ]:
especie_vul_names = df.groupby('iucnRedListCategory')['species'].value_counts()
especie_vul_names
Out[ ]:
iucnRedListCategory  species                
CR                   Calotriton arnoldi            1
EN                   Alytes dickhilleni          171
                     Rana pyrenaica               25
                     Alytes muletensis             6
LC                   Pelophylax perezi          8215
                     Epidalea calamita          3079
                     Alytes obstetricans        1779
                     Salamandra salamandra      1375
                     Pelodytes punctatus        1094
                     Triturus marmoratus        1015
                     Hyla arborea                979
                     Hyla meridionalis           894
                     Lissotriton boscai          803
                     Discoglossus galganoi       776
                     Alytes cisternasii          684
                     Lissotriton helveticus      589
                     Discoglossus jeanneae       547
                     Rana temporaria             470
                     Pelodytes ibericus          363
                     Calotriton asper            344
                     Ichthyosaura alpestris      112
                     Discoglossus pictus          49
                     Bufotes viridis              42
                     Sclerophrys mauritanica       4
                     Discoglossus scovazzi         2
                     Lithobates catesbeianus       1
                     Xenopus laevis                1
                     Oophaga pumilio               1
NE                   Rana dalmatina               34
                     Pelophylax saharicus          4
NT                   Pleurodeles waltl          1269
                     Triturus pygmaeus           521
                     Chioglossa lusitanica       149
                     Cynops pyrrhogaster           2
VU                   Pelobates cultripes        1585
                     Rana iberica                463
                     Salamandra algira             1
Name: count, dtype: int64

Lista de especies amenazadas de Anfibios recogida en la página oficial del Ministerio para la Transición Ecológica y el Reto demográfico del Gobierno de España.

https://www.miteco.gob.es/es/biodiversidad/temas/conservacion-de-especies-amenazadas/vertebrados/pbl_anfibios_amenazados.html

Familia: Salamandridae

Chioglossa lusitanica

S.s. almanzoris

Triturus alpestris

T.h. punctillatus

Familia: Discoglosidae

Alytes muletensis

Familia: Bufonidae

B.b.gredosicola

Bufo viridis

Familia: Ranidae

Rana dalmatina

R .t. parvipalmata

Otras referencias: https://www.miteco.gob.es/es/biodiversidad/temas/inventarios-nacionales/inventario-especies-terrestres/inventario-nacional-de-biodiversidad/ieet_anfib_reptl_lr_cap_iii_anf.html

Mapas de distribución especies vulnerables

En esta parte del proyecto se usó la librería geopandas para la elaboración de los mapas.

In [ ]:
# Importar geopandas y geodatasets
!pip install geodatasets
import geopandas as gpd
from matplotlib import pyplot as plt
Collecting geodatasets
  Downloading geodatasets-2023.12.0-py3-none-any.whl (19 kB)
Requirement already satisfied: pooch in /usr/local/lib/python3.10/dist-packages (from geodatasets) (1.8.1)
Requirement already satisfied: platformdirs>=2.5.0 in /usr/local/lib/python3.10/dist-packages (from pooch->geodatasets) (4.2.2)
Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.10/dist-packages (from pooch->geodatasets) (24.0)
Requirement already satisfied: requests>=2.19.0 in /usr/local/lib/python3.10/dist-packages (from pooch->geodatasets) (2.31.0)
Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests>=2.19.0->pooch->geodatasets) (3.3.2)
Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests>=2.19.0->pooch->geodatasets) (3.7)
Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests>=2.19.0->pooch->geodatasets) (2.0.7)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests>=2.19.0->pooch->geodatasets) (2024.2.2)
Installing collected packages: geodatasets
Successfully installed geodatasets-2023.12.0
In [ ]:
# Convertir las coordenadas a POINTS
df['coord'] = gpd.points_from_xy(df.decimalLongitude, df.decimalLatitude)
df['coord']
Out[ ]:
0        POINT (-3.97000 38.08000)
1        POINT (-4.09000 38.80000)
2        POINT (-3.29000 38.35000)
3        POINT (-4.70000 40.23000)
4        POINT (-3.40000 38.62000)
                   ...            
28709    POINT (-4.78000 38.43000)
28711     POINT (2.22000 41.77000)
28713    POINT (-4.78000 38.70000)
28714    POINT (-4.78000 38.61000)
28715     POINT (2.22000 41.95000)
Name: coord, Length: 27449, dtype: geometry
In [ ]:
#Hago un dataframe para cada especie
df_1 = df[df.species == 'Chioglossa lusitanica']
df_2 = df[df.species == 'Salamandra salamandra']
df_3 = df[df.species == 'Triturus pygmaeus']
df_4 = df[df.species == 'Alytes muletensis']
df_5 = df[df.species == 'Bufotes viridis']
df_6 = df[df.species == 'Rana dalmatina']
df_7 = df[df.species == 'Rana temporaria']
In [ ]:
gdfs_ES=[]
for i in range(3):
    gdf_ES = gpd.read_file(f'gadm41_ESP_{i}.shp')
    gdf_ES.plot( figsize = (10, 8))
    gdfs_ES.append(gdf_ES)
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
In [ ]:
es_mapa = gdfs_ES[1]
es_mapa.plot(figsize = (8,8), edgecolor="w", linewidth=0.3)
Out[ ]:
<Axes: >
No description has been provided for this image
In [ ]:
#Se incluye la geometría en un objeto
obvs_points = gpd.points_from_xy(df.decimalLongitude, df.decimalLatitude)
obvs_points
Out[ ]:
<GeometryArray>
[<POINT (-3.97 38.08)>,  <POINT (-4.09 38.8)>, <POINT (-3.29 38.35)>,
  <POINT (-4.7 40.23)>,  <POINT (-3.4 38.62)>, <POINT (-4.09 38.71)>,
 <POINT (-5.76 40.12)>, <POINT (-3.85 37.81)>, <POINT (-4.47 40.42)>,
 <POINT (-2.48 38.35)>,
 ...
  <POINT (2.22 41.86)>,  <POINT (-7.19 39.6)>, <POINT (-7.09 39.24)>,
 <POINT (-4.78 38.79)>,  <POINT (2.09 42.22)>, <POINT (-4.78 38.43)>,
  <POINT (2.22 41.77)>,  <POINT (-4.78 38.7)>, <POINT (-4.78 38.61)>,
  <POINT (2.22 41.95)>]
Length: 27449, dtype: geometry
In [ ]:
#Se crea el geodaframe
anfibios_gdf = gpd.GeoDataFrame(df, geometry=obvs_points)
In [ ]:
anfibios_gdf['coord']
Out[ ]:
0        POINT (-3.97000 38.08000)
1        POINT (-4.09000 38.80000)
2        POINT (-3.29000 38.35000)
3        POINT (-4.70000 40.23000)
4        POINT (-3.40000 38.62000)
                   ...            
28709    POINT (-4.78000 38.43000)
28711     POINT (2.22000 41.77000)
28713    POINT (-4.78000 38.70000)
28714    POINT (-4.78000 38.61000)
28715     POINT (2.22000 41.95000)
Name: coord, Length: 27449, dtype: geometry
In [ ]:
#Hago un dataframe para cada especie
gdf_1 = anfibios_gdf[anfibios_gdf.species == 'Chioglossa lusitanica']
gdf_2 = anfibios_gdf[anfibios_gdf.species == 'Salamandra salamandra']
gdf_3 = anfibios_gdf[anfibios_gdf.species == 'Triturus pygmaeus']
gdf_4 = anfibios_gdf[anfibios_gdf.species == 'Alytes muletensis']
gdf_5 = anfibios_gdf[anfibios_gdf.species == 'Bufotes viridis']
gdf_6 = anfibios_gdf[anfibios_gdf.species == 'Rana dalmatina']
gdf_7 = anfibios_gdf[anfibios_gdf.species == 'Rana temporaria']
In [ ]:
es_mapa.boundary.plot()
Out[ ]:
<Axes: >
No description has been provided for this image
In [ ]:
fig, ax = plt.subplots()
es_mapa.boundary.plot(ax=ax, color='k', edgecolor='black')
gdf_1.plot(ax=ax, marker='o', color='red', markersize = 1)
ax.set_title('Distribución de Chioglossa lusitanica')
Out[ ]:
Text(0.5, 1.0, 'Distribución de Chioglossa lusitanica')
No description has been provided for this image
In [ ]:
fig, ax = plt.subplots()
es_mapa.boundary.plot(ax=ax, color='k', edgecolor='black')
gdf_2.plot(ax=ax, marker='o', color='red', markersize = 1)
ax.set_title('Distribución de Salamandra salamandra')
Out[ ]:
Text(0.5, 1.0, 'Distribución de Salamandra salamandra')
No description has been provided for this image
In [ ]:
fig, ax = plt.subplots()
es_mapa.boundary.plot(ax=ax, color='k', edgecolor='black')
gdf_3.plot(ax=ax, marker='o', color='red', markersize = 1)
ax.set_title('Distribución de Triturus pygmaeus')
Out[ ]:
Text(0.5, 1.0, 'Distribución de Triturus pygmaeus')
No description has been provided for this image
In [ ]:
fig, ax = plt.subplots()
es_mapa.boundary.plot(ax=ax, color='k', edgecolor='black')
gdf_4.plot(ax=ax, marker='o', color='red', markersize = 1)
ax.set_title('Distribución de Alytes muletensis')
Out[ ]:
Text(0.5, 1.0, 'Distribución de Alytes muletensis')
No description has been provided for this image
In [ ]:
fig, ax = plt.subplots()
es_mapa.boundary.plot(ax=ax, color='k', edgecolor='black')
gdf_5.plot(ax=ax, marker='o', color='red', markersize = 1)
ax.set_title('Distribución de Bufotes viridis')
Out[ ]:
Text(0.5, 1.0, 'Distribución de Bufotes viridis')
No description has been provided for this image
In [ ]:
fig, ax = plt.subplots()
es_mapa.boundary.plot(ax=ax, color='k', edgecolor='black')
gdf_6.plot(ax=ax, marker='o', color='red', markersize = 1)
ax.set_title('Distribución de Rana dalmatina')
Out[ ]:
Text(0.5, 1.0, 'Distribución de Rana dalmatina')
No description has been provided for this image
In [ ]:
fig, ax = plt.subplots()
es_mapa.boundary.plot(ax=ax, color='k', edgecolor='black')
gdf_7.plot(ax=ax, marker='o', color='red', markersize = 1)
ax.set_title('Distribución de Rana temporaria')
Out[ ]:
Text(0.5, 1.0, 'Distribución de Rana temporaria')
No description has been provided for this image

RESULTADOS Y DISCUSIÓN¶

Diversidad de especies

El análisis de la base de datos descargada de la plataforma del Fondo Mundial de Información sobre Biodiversidad (GBIF) mostró la presencia de 2 órdenes (Caudata y Anura), 9 familias (Salamandridae, Pipidae, Ranida, Pelodytida, Pelobatidae, Hylidae, Alytidae, Dendrobatidae y Bufonidae) y 37 especies diferentes ('Triturus pygmaeus', 'Triturus marmoratus', 'Salamandra salamandra', 'Xenopus laevis', 'Rana temporaria', 'Salamandra algira', 'Pelophylax perezi', 'Rana pyrenaica', 'Pelophylax saharicus', 'Rana iberica', 'Rana dalmatina', 'Pleurodeles waltl', 'Lithobates catesbeianus', 'Pelodytes punctatus', 'Pelodytes ibericus', 'Pelobates cultripes', 'Ichthyosaura alpestris', 'Lissotriton helveticus', 'Lissotriton boscai', 'Hyla meridionalis', 'Hyla arborea', 'Calotriton asper', 'Discoglossus jeanneae', 'Discoglossus scovazzi', 'Discoglossus galganoi', 'Discoglossus pictus', 'Chioglossa lusitanica', 'Cynops pyrrhogaster', 'Oophaga pumilio', 'Bufotes viridis', 'Calotriton arnoldi', 'Epidalea calamita', 'Sclerophrys mauritanica', 'Alytes obstetricans', 'Alytes muletensis', 'Alytes dickhilleni', 'Alytes cisternasii')

El orden más representado ha sido Anura (77.5% de los datos), mientras que la familia con mayor número de ocurrencias corresponde con Ranidae (9212 ocurrencias, 33.6 % de los datos) seguida por Salamandridae (6181 ocurrencias, 22.5% de los datos). La especie con mayor número de ocurrencias es Pelophylax perezi.

A partir de los datos se observa que el número de especies varía entre las comunidades autónomas, siendo las Islas Canarias y las Islas Baleares las comunidades con menor riqueza de especies de anfibios (3-4 especies diferentes), mientras que el País Vasco, la Comunidad Foral de Navarra, Castilla y León y Andalucía son las comunidades autónomas con mayor número de especies (18-20 especies diferentes). Por otro, lado el mayor número de ocurrencias pertenecen a Castilla y León (20.1%), Andalucía (18.6%) y Castilla la Mancha (11%).

Escala temporal de los datos

Tras analizar el número de ocurrencias por año se observó que la mayoría de los datos se tomaron en el año 2002 (aprox. 65%). Desde entonces, la vulnerabilidad y distribución de estas especies en España ha podido cambiar significativamente. Un estudio en el que participan más de cien investigadores, basado en la segunda evaluación mundial de anfibios de la Unión Internacional para la Conservación de la Naturaleza (UICN), se ha documentado la extinción de cuatro especies de anfibios desde 2004: el sapo arlequín de Chiriquí de Costa Rica, Atelopus chiriquiensis; la rana diurna de hocico afilado de Australia, Taudactylus acutirostris; la rana, Craugastor myllomyllon y la falsa salamandra de arroyo de Jalpa, Pseudoeurycea exspectata, ambas de Guatemala. Otras 27 especies calificadas en peligro crítico se consideran ahora posiblemente extintas, lo que eleva el total a más de 160. La evaluación también constató que 120 especies mejoraron su situación en la Lista Roja desde 1980. Más de la mitad de este grupo, 63 especies, aumentaron sus poblaciones gracias a las medidas de conservación, protección y gestión de hábitats que se han desarrollado en este tiempo (CSIC).

Vulnerabilidad de las especies

La Lista Roja de la Unión Internacional para la Conservación de la Naturaleza (UICN, 2023) es el inventario más reconocido mundialmente sobre el estado de amenaza de las especies. La Lista Roja incluye nueve categorías: Extinta (EX), Extinta en estado silvestre (EW), En peligro crítico (CR), En peligro (EN), Vulnerable (VU), Casi amenazada (NT), Preocupación menor (LC), Datos insuficientes (DD), No evaluado (NE) De las nueve categorías sólo tres son consideradas como amenazadas: "En Peligro Crítico", "En Peligro" y "Vulnerable" (MITECO). Se registraron 7 especies bajo algún grado de amenaza importante según la Unión Internacional para la Conservación de la Naturaleza (UICN, 2023). El resto de las especies (30) se encuentran fuera de las categorías de amenazas importantes.

CR: Calotriton arnoldi (1)

EN : Alytes dickhilleni (171); Rana pyrenaica (25), Alytes muletensis (6)

VU: Pelobates cultripes (1585), Rana iberica (463), Salamandra algira (1)

De acuerdo con la lista de especies amenazadas de Anfibios recogida en la página oficial del Ministerio para la Transición Ecológica y el Reto demográfico del Gobierno de España https://www.miteco.gob.es/es/biodiversidad/temas/conservacion-de-especies-amenazadas/vertebrados/pbl_anfibios_amenazados.html Familia: Salamandridae Chioglossa lusitanica Salamandra salamandra almanzoris Triturus alpestris T.h. punctillatus Familia: Discoglosidae Alytes muletensis Familia: Bufonidae B.b.gredosicola Bufo viridis Familia: Ranidae Rana dalmatina R .t. parvipalmata

Sin embargo, sólo Alytes muletensis coincide con la lista de especies amenazadas de Anfibios recogida en la página oficial del Ministerio para la Transición Ecológica y el Reto demográfico del Gobierno de España https://www.miteco.gob.es/es/biodiversidad/temas/conservacion-de-especies-amenazadas/vertebrados/pbl_anfibios_amenazados.html

Distribución de las especies vulnerables

En base a esta lista oficial del MITECO del Gobierno de España, se han seleccionado siete especies, para el análisis de su distribución en el territorio español.

Chioglossa lusitanica (Salamandra rabilarga). Es una especie endémica de la Península Ibérica que se distribuye por su región Noroccidental. Vive en zonas montañosas con altitudes inferiores a 1100 m, asociada generalmente a arroyos y masas forestales diversas. Por lo tanto, la distribución de esta especie coincide con las fuentes oficiales.

Triturus pygmaeus (Tritón pigmeo). Solo presente en el cuadrante suroccidental y centro de la Península, de donde es endémico. Sin embargo, en los datos de ocurrencia se observa que se distribuye a lo largo de todo el territorio español. Por lo tanto, su distribución coincide con las fuentes oficiales.

Salamandra salamandra (Salamandra común). Como queda reflejado en el mapa de la Península Ibérica, la especie está presente en todas las regiones húmedas de Galicia, la cornisa Cantábrica y todos los Pirineos. Sigue los contornos de las sierras del Sistema Central, Montes de Toledo, Sierra Morena y las sierras Béticas. Por lo tanto, la distribución de esta especie coincide con las fuentes oficiales.

Bufotes viridis (Sapo verde). Únicamente se ha confirmado su presencia en las Islas Baleares: Mallorca, Menorca e Ibiza. Por lo tanto, su distribución coincide con las fuentes oficiales.

Rana dalmatina (Rana ágil). En España es una especie vulnerable, aunque no está categorizada como amaenazada a nivel mundial. En España es una especie muy escasa, conociéndose con seguridad sólo en algunas zonas del País Vasco y Navarra. Por lo tanto, la distribución de esta especie coincide con las fuentes oficiales.

Rana temporaria (Rana bermeja) En España se distribuye de forma continua por toda la franja norte, donde encuentra un alto grado de humedad y un clima fresco. Por lo tanto, la distribución de esta especie coincide con las fuentes oficiales.

Alytes mulatensis (Sapillo balear). Ocupa un área de unos 200 km2 en la isla de Mallorca, en Baleares. Por lo tanto, la distribución de esta especie coincide con las fuentes oficiales.

Conclusiones¶

Las diversas herramientas utilzadas en el tratamiento de la base de datos obtenida del GBIF ha contribuído al conocimiento acerca de la biodiversidad de anfibios presentes en España. Por otro lado, han permitido obtener información sobre la calidad y limitaciones de los datos.

El análisis realizado indica que es necesaria la búsqueda o recolección de nuevos datos más recientes procedentes de otras fuentes para completar la serie temporal y poder estudiar los cambios en las poblaciones de anfibios a la largo del tiempo.

Las plataforma GBIF mostró ser una herramienta eficaz para estudiar la distribución espacial de la biodiversidad dado que la distribución de especies es coherente con la información oficial disponibles sobre las especies seleccionadas.

Los resultados podrían estar obsoletos en lo referente a la vulnerabilidad de las especies, ya que son más representativos del año 2002. Es posible que la vulnerabilidad haya cambiado a lo largo de estos 20 años. Por lo tanto, se debería profundizar más en este aspecto antes de usar estos datos en posteriores análisis de biodiversidad.

Referencias

Du T, Ding C, Yang K, Chen J, Liu X, Lv W, Ding L, He D, Tao J. (2024) A global dataset on species occurrences and functional traits of Schizothoracinae fish. Sci Data. Mar 6;11(1):272. doi: 10.1038/s41597-024-03098-2. PMID: 38448551; PMCID: PMC10918187.

Caitlin P Mandeville, Wouter Koch, Erlend B Nilsen, Anders G Finstad,(2021) Open Data Practices among Users of Primary Biodiversity Data, BioScience, Volume 71, Issue 11, November 2021, Pages 1128–1147, https://doi.org/10.1093/biosci/biab072

Rodriguez Rivas, J. G., & Rodríguez Castillo, S. (2022). Uso de Python para el análisis de datos aplicado en la investigación . Investigación Y Ciencia Aplicada a La Ingeniería, 5(34), 33–40. Recuperado a partir de http://ojs.incaing.com.mx/index.php/ediciones/article/view/188

Soberon, J. and Peterson,A.T. (2004) Biodiversity informatics: managing and applying primary biodiversity data. Philos. Trans. R. Soc. Lond. Ser. B Biol. Sci., 359, 689–698

Vijay Barve, Javier Otegui, bdvis: visualizing biodiversity data in R (2016) Bioinformatics, Volume 32, Issue 19, October 2016, Pages 3049–3050, https://doi.org/10.1093/bioinformatics/btw333

Araújo MB, Anderson RP, Márcia Barbosa A, Beale CM, Dormann CF, Early R, Garcia RA, Guisan A, Maiorano L, Naimi B, O'Hara RB, Zimmermann NE, Rahbek C. Standards for distribution models in biodiversity assessments. (2019) Sci Adv. Jan 16;5(1):eaat4858. doi: 10.1126/sciadv.aat4858. PMID: 30746437; PMCID: PMC6357756.

Gadelha, Luiz & Correia de Siracusa, Pedro & Dalcin, Eduardo & Silva, Luís & Augusto, Douglas & Krempser, Eduardo & Affe, Helen & Costa, Raquel & Mondelli, Maria Luiza & Meirelles, Pedro & Thompson, Fabiano & Chame, Marcia & Ziviani, Artur & Siqueira, Marinez. (2020). A survey of biodiversity informatics: Concepts, practices, and challenges. Wiley Interdisciplinary Reviews: Data Mining and Knowledge Discovery. 11. e1394. 10.1002/widm.1394.

Luedtke JA, Chanson J, Neam K, Hobin L, Maciel AO, Catenazzi A, Borzée A, Hamidy A, Aowphol A, Jean A, Sosa-Bartuano Á, Fong G A, de Silva A, Fouquet A, Angulo A, Kidov AA, Muñoz Saravia A, Diesmos AC, Tominaga A, Shrestha B, Gratwicke B, Tjaturadi B, Martínez Rivera CC, Vásquez Almazán CR, Señaris C, Chandramouli SR, Strüssmann C, Cortez Fernández CF, Azat C, Hoskin CJ, Hilton-Taylor C, Whyte DL, Gower DJ, Olson DH, Cisneros-Heredia DF, Santana DJ, Nagombi E, Najafi-Majd E, Quah ESH, Bolaños F, Xie F, Brusquetti F, Álvarez FS, Andreone F, Glaw F, Castañeda FE, Kraus F, Parra-Olea G, Chaves G, Medina-Rangel GF, González-Durán G, Ortega-Andrade HM, Machado IF, Das I, Dias IR, Urbina-Cardona JN, Crnobrnja-Isailović J, Yang JH, Jianping J, Wangyal JT, Rowley JJL, Measey J, Vasudevan K, Chan KO, Gururaja KV, Ovaska K, Warr LC, Canseco-Márquez L, Toledo LF, Díaz LM, Khan MMH, Meegaskumbura M, Acevedo ME, Napoli MF, Ponce MA, Vaira M, Lampo M, Yánez-Muñoz MH, Scherz MD, Rödel MO, Matsui M, Fildor M, Kusrini MD, Ahmed MF, Rais M, Kouamé NG, García N, Gonwouo NL, Burrowes PA, Imbun PY, Wagner P, Kok PJR, Joglar RL, Auguste RJ, Brandão RA, Ibáñez R, von May R, Hedges SB, Biju SD, Ganesh SR, Wren S, Das S, Flechas SV, Ashpole SL, Robleto-Hernández SJ, Loader SP, Incháustegui SJ, Garg S, Phimmachak S, Richards SJ, Slimani T, Osborne-Naikatini T, Abreu-Jardim TPF, Condez TH, De Carvalho TR, Cutajar TP, Pierson TW, Nguyen TQ, Kaya U, Yuan Z, Long B, Langhammer P, Stuart SN. (2023)Ongoing declines for the world's amphibians in the face of emerging threats. Nature. Oct;622(7982):308-314. doi: 10.1038/s41586-023-06578-4. Epub 2023 Oct 4. Erratum in: Nature. 2024 Jan;625(7993):E2. PMID: 37794184; PMCID: PMC10567568.

https://www.miteco.gob.es/content/dam/miteco/es/biodiversidad/temas/conservacion-de-especies-amenazadas/CATEGORIA_E_V_tcm30-195338.pdf

https://www.miteco.gob.es/es/biodiversidad/temas/conservacion-de-especies-amenazadas/vertebrados/pbl_anfibios_amenazados.html

https://www.miteco.gob.es/es/biodiversidad/temas/inventarios-nacionales/inventario-especies-terrestres/inventario-nacional-de-biodiversidad/ieet_anfib_reptl_lr_cap_iii_anf.html

https://www.csic.es/es/actualidad-del-csic/el-cambio-climatico-acelera-la-desaparicion-de-los-anfibios