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.

In [36]:
!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)
In [37]:
# 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.

In [38]:
# 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.

In [39]:
# 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.

In [40]:
# 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.

In [41]:
# 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.

In [34]:
# 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()
No description has been provided for this image
In [35]:
# 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()
No description has been provided for this image

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