Título del Proyecto : Análisis de observaciones realizadas en iNaturalist, para clase Aves - Una muestra para 7 países¶
Integrante: Cynthia Tercero
Descripción y justificación del proyecto¶
Los países que integran el istmo centroméricano, tienen en común condiciones climáticas, geográficas que permiten albergar o ser el refugio temporal (en caso de las aves migratorias) para diversas especies.
La observación de aves, es una actividad ampliamente difundida a nivel internacional. Se ha reconocido que el registro sistemático de la avifauna permite evaluar el estado de los ecosistemas.
Como parte de las herramientas que facilitan el registro de observaciones se encuentra iNaturalist.
iNaturalist es una plataforma ampliamente conocida, su principal objetivo es registrar los hallazgos de la naturaleza en todo el mundo, sobre prácticamente todos los seres vivos, debidamente clasificados según por taxones, de manera jerárquica.
La plataforma permite la consulta de los registros, por país, especie, o por su clasificación jerárquica respectiva: reino, clase, orden, familia, género, especie.
La información que contiene iNaturalist es de acceso público. Tomado como punto de partida los datos que contien esta plataforma, resulta interesante poder tener un cuadro comparativo sobre las 5 especies de aves más observadas en cada uno de los países centromericanos. Así como conocer cuales son las 5 especies más observadas en toda la región. Poder observar gráficamente qué país de la región tiene la mayor diversidad de especies, entre otros datos de interés para la comunidad observadores de aves.
Este proyecto, tiene por objetivo facilitar este tipo de consultas, partiendo de una muestra tomada de iNaturalist, sobre los registros realizados para clase Aves en cada uno de los países del istmo centromericano, durante el año 2023, específicamente en el período que va desde el 1ro de Enero del 2023 al 31 de diciembre del 2023.
Antecedentes¶
Como fue indicado al inicio de este documento, iNaturalist rica en información sobre la biodiversidad mundial. iNaturalist la cual est´a articulada con la plataforma abierta de registros de biodiversidad m´as grande del mundo: la Infraestructura Mundial de Informaci´on sobre Biodiversidad GBIF (Carmona JA, 2024) facilita el registro de observaciones, partiendo de evidencias, tales como imágenes o sonidos.
Es importante mencionar que iNaturalist no es la plataforma más usada por la comunidad de observadores de aves, conocidos como birders, sin embargo, la utilidad de “iNaturalist” se incrementará en la medida que se acumulen más datos en la plataforma y más individuos se involucren en la observación y reporte de biodiversidad a través de esta (Zapata Branda, 2020)
Sobre iNaturalist, ya se han realizado algunos estudios que indican que la información que se registra, en el caso de la avifauna, puede tener ciertos sesgos. Por ejemplo: Los usuarios de iNaturalist informan preferentemente sobre especies que son nuevas para ellos o que observan con poca frecuencia. (Stoudt, S., B. R. et all, 2022)
Habiendo indicado algunos elementos que deben ser considerados sobre el uso de esta plataforma, no podemos obviar su importancia. Uno de sus grandes fortalezas, es que le permite a usuarios con poca experiencia, aprender a identificar la biodiversidad.
Con relación a la avifauna y la muestra de datos utilizada, la bibliografía consultada expresa que Centroamérica alberga una cantidad desproporcionada de la diversidad biológica de la Tierra, y la La biodiversidad en la región puede ser mayor de lo que se refleja en los resúmenes regionales actuales y listas de verificación. (Vallely, 2018, p23)
La difusión del análisis de los datos que poseen las plataformas digitales, que facilitan la ciencia ciudada, el conocimiento de sus fortalezas y limitaciones, es importante. El procesamiento de datos se ve enriquecido con el uso de lenguajes de programción como Python, que le permite a la comunidad científica sintetizar e identificar información valiosa sobre tendencias, crecimiento, dispersión de la biodiversidad.
Descripción del problema y objetivo¶
Problema: La necesidad comparar los registros de observaciones de aves a nivel centromaricano y evaluar el tipo de información que se ha registrado para la clase aves en iNaturalist en Centromérica.
Objetivo: Usando los datos obtenidos de los registros de observaciones en iNaturalist, crear un mecanismo que permita comparar las estadísticas de observaciones de cada país del istmo centroamericano.
Conjunto de Datos¶
Los datos objeto de análisis de este proyecto, corresponden a observaciones realizadas en iNatuaralist, de la clase aves, en el período comprendido del 1ro de enero de 2023 al 31 de diciembre de 2023.
Se realizaron consultas por separado para cada país:
- Guatemala
- Belize
- El Salvador
- Honduras
- Nicaragua
- Costa Rica
- Panamá
Cada una de las consultas fue descargadas como un archivo .cvs, los registros de estos archivos, son el insumo que ha sido análizado utilizando python y las librerias que hemos utilizado en clase.
iNaturalist. Disponible en https://www.inaturalist.org. Consultado el Mayo 04, 2024
Comunidad de iNaturalist. Observaciones de Aves de Guatemala, Belize El Salvador, Honduras, Nicaragua, Costa Rica y Panama observado en/entre enero 01, 2023 y diciembre 31, 203. Exportado desde https://www.inaturalist.org en Mayo 04, 2024
Primera sección - Configuración de ambiente de trabajo¶
La primera sección tiene todas las intrucciones necesarias para configurar el ambiente de trabajo.
La primera tarea consiste en instalar las librerías que serán utilizadas.
La segunda tarea es importar las librerías necesarias para el procesamiento de los datos que serán objeto de este proyecto.
La tercera tarea es importar los registros obtenidos para cada uno de los países: Guatemala, Belice, Honduras, El Salvador, Nicaragua, Costa Rica y Panamá. Estos registros se encuentran originalmente en archivos .csv Los archivos se encuentran deberán ser instalados en el ambiente en el cual se procesen los datos.
Crear un dataframe por país.
Debe imprimir el DataFrame generado.
!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) Requirement already satisfied: ydata-profiling in /usr/local/lib/python3.10/dist-packages (4.8.3) 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.1) 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) Requirement already satisfied: visions[type_image_path]<0.7.7,>=0.7.5 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (0.7.6) Requirement already satisfied: numpy<2,>=1.16.0 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (1.25.2) Requirement already satisfied: htmlmin==0.1.12 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (0.1.12) Requirement already satisfied: phik<0.13,>=0.11.1 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (0.12.4) 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) Requirement already satisfied: multimethod<2,>=1.4 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (1.11.2) Requirement already satisfied: statsmodels<1,>=0.13.2 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (0.14.2) Requirement already satisfied: typeguard<5,>=3 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (4.2.1) Requirement already satisfied: imagehash==4.3.1 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (4.3.1) Requirement already satisfied: wordcloud>=1.9.1 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (1.9.3) Requirement already satisfied: dacite>=1.8 in /usr/local/lib/python3.10/dist-packages (from ydata-profiling) (1.8.1) 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.51.0) 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.6.0) Requirement already satisfied: pydantic-core==2.18.2 in /usr/local/lib/python3.10/dist-packages (from pydantic>=2->ydata-profiling) (2.18.2) Requirement already satisfied: typing-extensions>=4.6.1 in /usr/local/lib/python3.10/dist-packages (from pydantic>=2->ydata-profiling) (4.11.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)
# Definir las librerías que serán importadas
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from ydata_profiling import ProfileReport
#Instrucción para ver la cantidad total de registros de un DataFrame, sino se coloca, muestra solo los 30 primeros y luego los últimos 30 (o algo por ahi)
pd.set_option('display.max_rows', None)
pd.set_option('display.max_columns', None)
# Lectura de cada uno de los csv correspondientes a las observaciones de aves del año 2023 para cada país de Centro América
pCR = pd.read_csv('observationsCR2023.csv')
pPN = pd.read_csv('observationsPN2023.csv')
pNI = pd.read_csv('observationsNI2023.csv')
pHN = pd.read_csv('observationsHN2023.csv')
pGT = pd.read_csv('observationsGT2023.csv')
pES = pd.read_csv('observationsES2023.csv')
pBZ = pd.read_csv('observationsBZ2023.csv')
Segunda sección - Exploración del contenido de los dataframes objeto de estudio de este proyecto.¶
La segunda sección tiene por objetivo presentar la contabilización de registros por país, sin ningún tipo de procesamiento.
Los resultados de ejecutar las intrucciones de esta sección deberán ser analizados a fin de poder identificar qué tipo de preprocesamiento requieren los datos importados.
# Contabilizar la cantidad registros de cada DataFrame
# Como se vio en clases durante la sesión de la quinta semana - PreProcesamiento de Datos
# la visualización de cada DataFrame permite identificar la calidad de los datos
# no todos los campos de información pueden ser necesarios
# mediante estas intrucciones, por simple inspección podremos identificar qué información
# es relevante para el proyecto
df1 = pCR.nunique()
print("Cantidad Total de Registros Costa Rica")
print(df1)
print("\n")
df2 = pNI.nunique()
print("Cantidad Total de Registros Nicaragua")
print(df2)
print("\n")
df3 = pPN.nunique()
print("Cantidad Total de Registros Panamá")
print(df3)
print("\n")
df4 = pES.nunique()
print("Cantidad Total de Registros El Salvador")
print(df4)
print("\n")
df5 =pHN.nunique()
print("Cantidad Total de Registros Honduras")
print(df5)
print("\n")
df6 = pGT.nunique()
print("Cantidad Total de Registros Guatemla")
print(df6)
print("\n")
df7 = pBZ.nunique()
print("Cantidad Total de Registros Belice")
print(df7)
print("\n")
Cantidad Total de Registros Costa Rica id 54738 observed_on_string 47760 observed_on 365 time_observed_at 47008 time_zone 3 user_id 2971 user_login 2971 user_name 1739 created_at 41893 updated_at 52396 quality_grade 2 license 7 url 54738 image_url 53741 sound_url 1058 tag_list 850 description 2110 num_identification_agreements 10 num_identification_disagreements 4 captive_cultivated 1 oauth_application_id 8 place_guess 5196 latitude 36086 longitude 35755 positional_accuracy 3066 private_place_guess 0 private_latitude 0 private_longitude 0 public_positional_accuracy 2934 geoprivacy 1 taxon_geoprivacy 2 coordinates_obscured 2 positioning_method 1 positioning_device 3 species_guess 3168 scientific_name 1048 common_name 938 iconic_taxon_name 1 taxon_id 1048 dtype: int64 Cantidad Total de Registros Nicaragua id 5298 observed_on_string 4371 observed_on 299 time_observed_at 4334 time_zone 2 user_id 169 user_login 169 user_name 114 created_at 3186 updated_at 5228 quality_grade 2 license 4 url 5298 image_url 5260 sound_url 41 tag_list 69 description 123 num_identification_agreements 12 num_identification_disagreements 3 captive_cultivated 1 oauth_application_id 4 place_guess 486 latitude 3156 longitude 3177 positional_accuracy 1068 private_place_guess 6 private_latitude 9 private_longitude 9 public_positional_accuracy 1073 geoprivacy 1 taxon_geoprivacy 2 coordinates_obscured 2 positioning_method 1 positioning_device 1 species_guess 877 scientific_name 480 common_name 467 iconic_taxon_name 1 taxon_id 480 dtype: int64 Cantidad Total de Registros Panamá id 23558 observed_on_string 20748 observed_on 365 time_observed_at 20558 time_zone 3 user_id 1107 user_login 1107 user_name 718 created_at 18169 updated_at 23097 quality_grade 2 license 6 url 23558 image_url 23130 sound_url 448 tag_list 210 description 717 num_identification_agreements 8 num_identification_disagreements 4 captive_cultivated 1 oauth_application_id 3 place_guess 2391 latitude 14404 longitude 14256 positional_accuracy 1673 private_place_guess 0 private_latitude 0 private_longitude 0 public_positional_accuracy 1652 geoprivacy 1 taxon_geoprivacy 2 coordinates_obscured 2 positioning_method 1 positioning_device 3 species_guess 1985 scientific_name 964 common_name 876 iconic_taxon_name 1 taxon_id 964 dtype: int64 Cantidad Total de Registros El Salvador id 6185 observed_on_string 5212 observed_on 351 time_observed_at 5177 time_zone 2 user_id 187 user_login 187 user_name 135 created_at 5577 updated_at 6164 quality_grade 2 license 4 url 6185 image_url 5862 sound_url 361 tag_list 23 description 350 num_identification_agreements 8 num_identification_disagreements 3 captive_cultivated 1 oauth_application_id 2 place_guess 797 latitude 3312 longitude 3315 positional_accuracy 600 private_place_guess 0 private_latitude 0 private_longitude 0 public_positional_accuracy 604 geoprivacy 1 taxon_geoprivacy 2 coordinates_obscured 2 positioning_method 1 positioning_device 1 species_guess 863 scientific_name 455 common_name 443 iconic_taxon_name 1 taxon_id 455 dtype: int64 Cantidad Total de Registros Honduras id 7168 observed_on_string 6790 observed_on 361 time_observed_at 6655 time_zone 2 user_id 579 user_login 579 user_name 431 created_at 5683 updated_at 7030 quality_grade 2 license 5 url 7168 image_url 7090 sound_url 92 tag_list 22 description 365 num_identification_agreements 9 num_identification_disagreements 3 captive_cultivated 1 oauth_application_id 3 place_guess 1101 latitude 5575 longitude 5558 positional_accuracy 695 private_place_guess 0 private_latitude 0 private_longitude 0 public_positional_accuracy 683 geoprivacy 1 taxon_geoprivacy 2 coordinates_obscured 2 positioning_method 1 positioning_device 2 species_guess 1470 scientific_name 667 common_name 640 iconic_taxon_name 1 taxon_id 667 dtype: int64 Cantidad Total de Registros Guatemla id 5852 observed_on_string 5495 observed_on 355 time_observed_at 5447 time_zone 2 user_id 471 user_login 471 user_name 341 created_at 4404 updated_at 5694 quality_grade 2 license 6 url 5852 image_url 5670 sound_url 190 tag_list 11 description 271 num_identification_agreements 11 num_identification_disagreements 3 captive_cultivated 1 oauth_application_id 3 place_guess 761 latitude 4335 longitude 4341 positional_accuracy 752 private_place_guess 0 private_latitude 0 private_longitude 0 public_positional_accuracy 723 geoprivacy 1 taxon_geoprivacy 2 coordinates_obscured 2 positioning_method 1 positioning_device 2 species_guess 1154 scientific_name 603 common_name 591 iconic_taxon_name 1 taxon_id 603 dtype: int64 Cantidad Total de Registros Belice id 5949 observed_on_string 5479 observed_on 341 time_observed_at 5453 time_zone 2 user_id 355 user_login 355 user_name 195 created_at 4755 updated_at 5798 quality_grade 2 license 4 url 5949 image_url 5768 sound_url 176 tag_list 30 description 389 num_identification_agreements 9 num_identification_disagreements 2 captive_cultivated 1 oauth_application_id 3 place_guess 381 latitude 4036 longitude 4023 positional_accuracy 650 private_place_guess 0 private_latitude 0 private_longitude 0 public_positional_accuracy 637 geoprivacy 1 taxon_geoprivacy 2 coordinates_obscured 2 positioning_method 1 positioning_device 2 species_guess 802 scientific_name 486 common_name 470 iconic_taxon_name 1 taxon_id 486 dtype: int64
Tercera sección - Preprocesamiento de la información¶
La tercera sección tiene por objetivo realizar un preprocesamiento de los dataframes.
Como resultado de la ejecución de las instrucciones de la segunda sección, se puedo realizar una exploración visual del tipo de dato que contiene cada dataframe. Todos tienen los mismos campos definidos, sin embargo no todos los campos son relevantes para el proyecto.
Poniendo en práctica los conocimientos adquiridos se incluirán instrucciones que permitan eliminar aquellos campos que no son necesarios para el proyecto.
De igual manera, se identificarán los registros (filas) que cuya información no está completa o bien, no corresponde con observaciones que han sido confirmadas.
# Convertir la información obtenida de los csvs en DataFrames, uno para cada país
dfNI = pd.DataFrame(pNI)
dfHN = pd.DataFrame(pHN)
dfCR = pd.DataFrame(pCR)
dfGT = pd.DataFrame(pGT)
dfPN = pd.DataFrame(pPN)
dfES = pd.DataFrame(pES)
dfBZ = pd.DataFrame(pBZ)
# Instrucción para cambiar en cada DataFrame el valor del campo time_observed_at sino tiene ningún valor, colocar NA - No Aplica
# Esta sección tiene caracter temporal
dfGT['Country']=np.where(dfGT['time_observed_at'] != None, "GT", "NA")
dfBZ['Country']=np.where(dfBZ['time_observed_at'] != None, "BZ", "NA")
dfHN['Country']=np.where(dfHN['time_observed_at'] != None, "HN", "NA")
dfES['Country']=np.where(dfES['time_observed_at'] != None, "ES", "NA")
dfNI['Country']=np.where(dfNI['time_observed_at'] != None, "NI", "NA")
dfCR['Country']=np.where(dfCR['time_observed_at'] != None, "CR", "NA")
dfPN['Country']=np.where(dfPN['time_observed_at'] != None, "PN", "NA")
# Limpieza de Datos
# Como resultado de la ejecución de las instrucciones de la sección anterior, se ha podido identificar por simple exploración
# que los datos de cada DataFrame no están totalmente limpios, o bien que no todos los campos son necesarios.
# Se ha decidido realizar una limpieza en dos fases:
# - Re-estructurar la información eliminando aquellos campos con información que no es relevante para el proyecto
# - Hacer una revisión general de la información de los campos que quedan, para identificar qué tipo de tratamiento será necesario.
# Para eliminar columnas se podría utilizar una instrucción condicional para que de manera automática elimine todo las las columunas que tengan
# valor NaN, sin embargo se ha decidido hacer una valoración campo a campo, por la importancia que podrían tener algunas campos.
# Previa exploración de los datos obtenidos en la sección anterior, se ha determinado los campos que serán eliminados por ser irrelevantes para este proyecto
camposSinUso = ['observed_on_string', 'time_observed_at', 'user_login', 'user_name','created_at', 'updated_at', 'license', 'image_url',
'sound_url','tag_list','description','num_identification_agreements','num_identification_disagreements','oauth_application_id',
'private_place_guess','private_latitude','private_longitude','public_positional_accuracy','geoprivacy','positioning_method',
'positioning_device','species_guess','common_name','iconic_taxon_name']
# Elimnar los campos sin uso en cada uno de los DataFrames - quizás podría hacerse con un ciclo - REVISAR
dfGT = dfGT.drop(camposSinUso, axis=1)
dfBZ = dfBZ.drop(camposSinUso, axis=1)
dfES = dfES.drop(camposSinUso, axis=1)
dfHN = dfHN.drop(camposSinUso, axis=1)
dfNI = dfNI.drop(camposSinUso, axis=1)
dfCR = dfCR.drop(camposSinUso, axis=1)
dfPN = dfPN.drop(camposSinUso, axis=1)
# Tratamiento de la información
# Serán eliminadas todas aquellas aquellos registros cuyo grado de investigación no esté certificado mediante el valor 'research'
# Los nombres cientificos deben estar completos, al eliminar los que no tiene qualitiy_grade = research, quedan eliminados los registros
# cuyos nombres cientificos no son correctos o están incompletos
# Contabilizar y mostrar la cantidad de registros eliminados por país
totalNoResearch =(dfGT['quality_grade'] != 'research').sum()
print("Registros no válidos para Guatemala : ", totalNoResearch)
totalNoResearch =(dfBZ['quality_grade'] != 'research').sum()
print("Registros no válidos para Belize: ", totalNoResearch)
totalNoResearch =(dfHN['quality_grade'] != 'research').sum()
print("Registros no válidos para Honduras : ", totalNoResearch)
totalNoResearch =(dfES['quality_grade'] != 'research').sum()
print("Registros no válidos para El Salvador : ", totalNoResearch)
totalNoResearch =(dfNI['quality_grade'] != 'research').sum()
print("Registros no válidos para Nicaragua : ", totalNoResearch)
totalNoResearch =(dfCR['quality_grade'] != 'research').sum()
print("Registros no válidos para Costa Rica: ", totalNoResearch)
totalNoResearch =(dfPN['quality_grade'] != 'research').sum()
print("Registros no válidos para Panamá: ", totalNoResearch)
# Eliminar los registros que no son válidos para el proyecto, según la condición
# descrita previamente
dfGT.drop(dfGT[(dfGT['quality_grade'] != 'research')].index, inplace=True)
dfBZ.drop(dfBZ[(dfBZ['quality_grade'] != 'research')].index, inplace=True)
dfHN.drop(dfHN[(dfHN['quality_grade'] != 'research')].index, inplace=True)
dfES.drop(dfES[(dfES['quality_grade'] != 'research')].index, inplace=True)
dfNI.drop(dfNI[(dfNI['quality_grade'] != 'research')].index, inplace=True)
dfCR.drop(dfCR[(dfCR['quality_grade'] != 'research')].index, inplace=True)
dfPN.drop(dfPN[(dfPN['quality_grade'] != 'research')].index, inplace=True)
# Obtener un DataFrame con todos cuyos registros son los las observaciones comunes a los siete países del istmo centromericano
commonCA = \
set.intersection(
set(dfHN.scientific_name),
set(dfNI.scientific_name),
set(dfCR.scientific_name),
set(dfGT.scientific_name),
set(dfBZ.scientific_name),
set(dfES.scientific_name),
set(dfPN.scientific_name))
pdComunCA = pd.concat([
dfBZ[dfBZ.scientific_name.isin(commonCA)],
dfGT[dfGT.scientific_name.isin(commonCA)],
dfES[dfES.scientific_name.isin(commonCA)],
dfHN[dfHN.scientific_name.isin(commonCA)],
dfNI[dfNI.scientific_name.isin(commonCA)],
dfPN[dfPN.scientific_name.isin(commonCA)],
dfCR[dfCR.scientific_name.isin(commonCA)]]).sort_values(by='scientific_name')
# Realizar un merge de los siete DataFrames
pdCA = pd.concat([dfGT,dfBZ,dfHN, dfES, dfNI, dfCR, dfPN])
# Convertir el la estructura del merge en un DataFrame
dfCA = pd.DataFrame(pdCA)
# Este Dataframe contiene la intersección de todas las especies comunes a los 7 países
# del istmo centromericano, tomando como punto de referencia las observaciones registradas
# en iNaturalist en el año 2023
dfComun = pd.DataFrame(pdComunCA)
totalCA = dfCA.nunique()
print("\nEl total de registros correspondientes a aves en el año 2023 en Centro America es:\n", totalCA)
# Agrupación de los registros comunes por nombre científico - En este momento aún no se ha realizado limpieza de datos
especiesComunes = ((dfComun.groupby(['scientific_name'])['scientific_name'].count()).sort_values(ascending=False))
totalespeciesComunes = len(especiesComunes)
print("\nA continuación tenemos un listado de las especies comunes observadas en Centro América con la cantidad total de observaciones:\n", especiesComunes)
print("\nLa cantidad total de especies observadas comunes a los 7 países de Centro América es:\n", totalespeciesComunes)
Registros no válidos para Guatemala : 364 Registros no válidos para Belize: 733 Registros no válidos para Honduras : 461 Registros no válidos para El Salvador : 726 Registros no válidos para Nicaragua : 223 Registros no válidos para Costa Rica: 6129 Registros no válidos para Panamá: 1977 El total de registros correspondientes a aves en el año 2023 en Centro America es: id 98135 observed_on 365 time_zone 9 user_id 5186 quality_grade 1 url 98135 captive_cultivated 1 place_guess 10348 latitude 63968 longitude 63524 positional_accuracy 4309 taxon_geoprivacy 2 coordinates_obscured 2 scientific_name 1230 taxon_id 1230 Country 7 dtype: int64 A continuación tenemos un listado de las especies comunes observadas en Centro América con la cantidad total de observaciones: scientific_name Quiscalus mexicanus 1537 Turdus grayi 1362 Pitangus sulphuratus 1337 Coragyps atratus 1256 Tyrannus melancholicus 1170 Thraupis episcopus 1079 Momotus lessonii 870 Tigrisoma mexicanum 816 Ardea alba 801 Butorides virescens 748 Myiozetetes similis 713 Egretta caerulea 686 Pteroglossus torquatus 685 Cyanerpes cyaneus 648 Pelecanus occidentalis 645 Zenaida asiatica 643 Cathartes aura 632 Actitis macularius 632 Piranga rubra 629 Fregata magnificens 589 Jacana spinosa 588 Icterus galbula 577 Nyctanassa violacea 555 Rupornis magnirostris 553 Columbina talpacoti 498 Dendrocygna autumnalis 472 Eudocimus albus 471 Nannopterum brasilianum 458 Mimus gilvus 450 Caracara plancus 446 Crotophaga sulcirostris 439 Setophaga petechia 431 Leiothlypis peregrina 429 Egretta thula 426 Buteogallus anthracinus 414 Egretta tricolor 414 Piaya cayana 406 Anhinga anhinga 403 Megaceryle torquata 391 Campylopterus hemileucurus 390 Tityra semifasciata 386 Troglodytes aedon 381 Tachycineta albilinea 371 Mycteria americana 366 Chloroceryle americana 366 Columbina inca 366 Sporophila morelleti 332 Numenius phaeopus 326 Pandion haliaetus 312 Dives dives 312 Dryocopus lineatus 311 Todirostrum cinereum 309 Bubulcus ibis 306 Himantopus mexicanus 306 Ardea herodias 305 Tiaris olivaceus 305 Patagioenas flavirostris 302 Trogon caligatus 299 Cochlearius cochlearius 299 Leptotila verreauxi 298 Chloroceryle amazona 289 Patagioenas cayennensis 276 Buteo platypterus 274 Megarynchus pitangua 265 Thalasseus maximus 263 Progne chalybea 261 Leucophaeus atricilla 256 Tringa semipalmata 244 Nycticorax nycticorax 241 Glaucidium brasilianum 240 Volatinia jacarina 231 Columba livia domestica 228 Thamnophilus doliatus 221 Nyctidromus albicollis 217 Myiarchus tuberculifer 216 Platalea ajaja 209 Pheucticus ludovicianus 207 Calidris minutilla 204 Herpetotheres cachinnans 200 Mniotilta varia 187 Melanerpes formicivorus 179 Spatula discors 175 Saltator grandis 175 Rostrhamus sociabilis 172 Icterus spurius 156 Setophaga virens 155 Myiodynastes luteiventris 154 Pachyramphus aglaiae 150 Buteo brachyurus 149 Tachybaptus dominicus 149 Saltator atriceps 148 Sayornis nigricans 147 Setophaga coronata 146 Parkesia noveboracensis 140 Anthracothorax prevostii 140 Tolmomyias sulphurescens 137 Archilochus colubris 137 Molothrus aeneus 137 Arenaria interpres 136 Strix virgata 136 Tringa melanoleuca 128 Elanoides forficatus 126 Colaptes rubiginosus 122 Aramus guarauna 117 Tyrannus savana 115 Chloroceryle aenea 110 Pachysylvia decurtata 107 Setophaga ruticilla 107 Cairina moschata domestica 105 Catharus ustulatus 100 Passerina caerulea 99 Vireo flavifrons 97 Calidris alba 96 Mionectes oleagineus 95 Sturnella magna 91 Streptopelia decaocto 89 Tringa flavipes 85 Elanus leucurus 80 Cyclarhis gujanensis 80 Geothlypis poliocephala 77 Tringa solitaria 77 Empidonax flaviventris 75 Tyrannus tyrannus 75 Contopus bogotensis 74 Stelgidopteryx serripennis 74 Falco peregrinus 72 Parkesia motacilla 65 Passerina ciris 62 Turdus assimilis 60 Leucophaeus pipixcan 57 Chordeiles acutipennis 56 Aythya affinis 55 Buteogallus urubitinga 49 Vireo olivaceus 47 Charadrius vociferus 46 Megaceryle alcyon 46 Streptoprocne zonaris 44 Tyto alba 41 Coccyzus minor 39 Basileuterus culicivorus 39 Myiopagis viridicata 38 Anarhynchus wilsonia 36 Podilymbus podiceps 32 Tapera naevia 31 Columba livia 26 Amblycercus holosericeus 26 Botaurus pinnatus 26 Name: scientific_name, dtype: int64 La cantidad total de especies observadas comunes a los 7 países de Centro América es: 147
Cuarta sección -¶
Una vez que se han hecho las actividades necesarias para configurar el ambiente de trabajo, recopilación de la información objeto de estudio, identificación de datos que no son relevantes, se procede con el procesamiento propiamente dicho, obtener piezas de información que permitan realizar comparaciones de los registros a nivel centromericano.
La cuarta sección tiene por objetivo mostrar:
a. Las cinco especies más observadas en cada país. b. Las cinco especies más observadas a nivel centromericano. c. Las cinco especies menos observadas a nivel centroamericano. b. Las cinco especies menos observadas en la región centromericana.
# Imprimir las 5 especies más observadas por país
# Obtener los valores de las 5 especies más observadas por país
gcGT = (((dfGT.groupby('scientific_name')).size()).sort_values(ascending=False)).head()
gcBZ = (((dfBZ.groupby('scientific_name')).size()).sort_values(ascending=False)).head()
gcES = (((dfES.groupby('scientific_name')).size()).sort_values(ascending=False)).head()
gcHN = (((dfHN.groupby('scientific_name')).size()).sort_values(ascending=False)).head()
gcNI = (((dfNI.groupby('scientific_name')).size()).sort_values(ascending=False)).head()
gcCR = (((dfCR.groupby('scientific_name')).size()).sort_values(ascending=False)).head()
gcPN = (((dfPN.groupby('scientific_name')).size()).sort_values(ascending=False)).head()
print("Las 5 especies más observadas son: ")
print("Guatemala: ", gcGT, "\n")
print("Belize: ", gcBZ, "\n")
print("Honduras: ", gcHN, "\n")
print("El Salvador: ", gcES, "\n")
print("Nicaragua: ", gcNI, "\n")
print("Costa Rica: ", gcCR, "\n")
print("Panama: ", gcPN)
dfCAEspecies = dfCA.groupby('scientific_name').count()
#Obtener las 5 especies más observadas en toda la región
group_countsMax = (((dfCA.groupby('scientific_name')).size()).sort_values(ascending=False)).head()
group_countsMin = (((dfCA.groupby('scientific_name')).size()).sort_values(ascending=False)).tail()
print("\n Las cinco especies más observadas en Centro América son: ", group_countsMax)
print("\n Las cinco especies menos observadas en Centro América son: ", group_countsMin)
print("\n")
Las 5 especies más observadas son: Guatemala: scientific_name Quiscalus mexicanus 115 Meleagris ocellata 109 Turdus grayi 90 Coragyps atratus 64 Momotus lessonii 57 dtype: int64 Belize: scientific_name Pelecanus occidentalis 108 Pitangus sulphuratus 107 Quiscalus mexicanus 98 Pteroglossus torquatus 95 Sporophila morelleti 90 dtype: int64 Honduras: scientific_name Quiscalus mexicanus 163 Zenaida asiatica 107 Coragyps atratus 99 Melanerpes aurifrons 95 Eumomota superciliosa 92 dtype: int64 El Salvador: scientific_name Tyrannus melancholicus 107 Quiscalus mexicanus 92 Eumomota superciliosa 85 Melanerpes aurifrons 81 Icterus galbula 79 dtype: int64 Nicaragua: scientific_name Butorides virescens 88 Ardea alba 79 Egretta caerulea 69 Tyrannus melancholicus 67 Jacana spinosa 66 dtype: int64 Costa Rica: scientific_name Ramphocelus passerinii 955 Pitangus sulphuratus 816 Turdus grayi 721 Ramphastos ambiguus 695 Quiscalus mexicanus 651 dtype: int64 Panama: scientific_name Quiscalus mexicanus 364 Tyrannus melancholicus 346 Ramphocelus dimidiatus 329 Daptrius chimachima 321 Turdus grayi 304 dtype: int64 Las cinco especies más observadas en Centro América son: scientific_name Quiscalus mexicanus 1537 Turdus grayi 1362 Pitangus sulphuratus 1337 Coragyps atratus 1256 Tyrannus melancholicus 1170 dtype: int64 Las cinco especies menos observadas en Centro América son: scientific_name Daptrius chimachima cordatus 1 Dactylortyx thoracicus salvadoranus 1 Sporophila torqueola 1 Cypseloides cryptus 1 Zonotrichia leucophrys 1 dtype: int64
Quinta sección - Uso de pandas profile¶
La quinta sección contiene las instrucciones requeridas para generar un informe con pandas-profiles.
El informe de pandas profile es una herramienta muy útil para hacer un diagnóstico sobre la información que contiene un dataframe.
En nuestro caso lo utilizaremos para tener una represención visual de las especies más observadas.
Confirmar la cantidad total de registros de observaciones correspondientes a la clase aves durante en el año 2023 (previa limpieza de datos)
Identificar mediante la variable Country, cuales son los países con el mayor porcentaje de observaciones.
# Cargar datos
dfCA["scientific_name"] = dfCA["scientific_name"].str.replace(" ", "_")
# Creamos el informe con pandas-profiling
nombre = "Datos de iNaturalist de Centro América"
profile = ProfileReport(dfCA, title=nombre, explorative=True)
# Mostrar el informe en un notebook (si estás usando Jupyter o similares)
profile.to_notebook_iframe()
Output hidden; open in https://colab.research.google.com to view.
Sexta sección - Herramientas de gráficación¶
En esta sección utilizamos dos tipos de gráficos para:
a. Idenficar visualmente la distribución del número de especies únicas observadas en los diferente países, esto se realizará mediante un gráfico de barras.
b. Explorar la distribución geográfica de la especie más observada en el istmo centromericano mediante un gráfico de dispersión según las coordenadas geográficas.
# Tamaño del gráfico
plt.figure(figsize=(6, 6))
# Agrupar el dataframe por país y contar el número de especies
species_num = dfCA.groupby('Country')['scientific_name'].nunique()
# Crear gráfico de barras
species_num.plot(kind='barh')
# Título del gráfico
plt.title('Número de Especies únicas por País')
# Etiqueta del eje Y
plt.ylabel('País')
# Etiqueta dLoel eje X
plt.xlabel('Cantidad de Especies')
plt.grid()
plt.show()
# Tamaño del grafico
figura = plt.figure(figsize=(6, 6))
# Filtrar los datos del dataframe para la familia con mayor cantidad de observaciones
# Incluir instrucción para obtener la especie con la mayor cantidad de observaciones
counts = dfCA.groupby(dfCA['scientific_name']).size()
maxCounts = max(counts)
# Tenemos la serie con la cantidad total de registros para cada especie
#Obtener el indice del mayor número de ocurencias
index = pd.Index(counts).get_loc(maxCounts)
#Convertir los datos en un DataFrame para poder tener acceso a la etiqueta
#convertidas en filas y columnas
df2 = pd.DataFrame(counts)
rown_names = (list(df2.index.values))
nombreEspecie = rown_names[index]
especieDisp = dfCA.loc[dfCA['scientific_name']== nombreEspecie]
# Utilizando la función scatterplot de la biblioteca seaborn que se puede # graficar usando dataframe
ax = sns.scatterplot(data=especieDisp, x='longitude', y='latitude', hue='scientific_name', palette='viridis', alpha=0.8)
# Agregar las etiquetas de los ejes
ax.set(xlabel='Longitud', ylabel='Latitud')
plt.grid()
# Título del gráfico
plt.title('Dispersión de latitud y longitud para explorar la distribución geográfica de la especie más observada')
plt.show()
Descripción de los resultados obtenidos¶
Al hacer un análisis previo de los datos obtenidos de iNaturalist utilizando diversas librerías de Python hemos podido constatar lo siguiente:
La mayor cantidad de observaciones corresponden a la especie Quiscalus mexicanus
El país del istmo centromaricano con la mayor cantidad de registros es Costa Rica, 48609 registros, que corresponde al 49.5% del total de las observaciones de la región.
De la cantidad total de especies únicas registradas durante el año 2023 que fue de 1230, 147 fueron observadas en todos los países del istmo, lo que corresponde al 12.39%
La mayor diversidad de especies se ha registrado en Costa Rica.
Panamá es el segundo país con la mayor cantidad de registros y de especies.
Conclusiones¶
Al realizar este proyecto tenemos conclusiones tanto sobre la información procesada, como la importancia del uso de herramientas como python y sus librerías para el análsis de datos.
a. La información que contienen las plataformas digitales requiere siempre algún tipo de preprocesamiento para que los datos obtenidos sean relevantes.
b. iNaturalist es una plataforma que facilita el registro de observaciones, pero sus datos deben acompañarse de la información proveniente de otras plataformas o estudios de especialistas en la mataria.
c. Tal y como fue descrito por uno de los artículos consultados, la mayor cantidad de observaciones, no siempre corresponde con la mayor frecuencia de aves para un país determinado, al analizar la muestra de datos, puede comprobarse esta teoría.
d. La información que contienen las plataformas digitales, será de valor en la medida la comunidad de usuarios lo sea. Estas herramientas facilitan mucho la ciencia ciudadana, pero es importante tener el apoyo de los expertos en la materia, como los curadores de datos.
Referencias¶
Gariz´abal-Carmona & Casta˜no-Rivas (2024) El Papel de las Observaciones de Aves en la Ciencia Ciudadana: Historia, Oportunidades y Desafíos en Colombia. Bolet´ın SAO Vol. 33
Zapata Branda N (2020) Diagnóstico de inventarios de aves usando plataformas de ciencia ciudadana en tres parques nacionales de Panamá. Escuela Agrícola Panamericana, Zamorano Honduras
Vallely, A. & Dyer, D.: (2018). Birds of Central America: Belize, Guatemala, Honduras, El Salvador, Nicaragua, Costa Rica, and Panama. Princeton: Princeton University Press
Stoudt S, Goldstein BR, de Valpine P. (2022) Identifying engaging bird species and traits with community science observations. pnas.2110156119