Trabajo Final¶

Estudiantes:

Dawa Méndez Álvarez

Daniel Villavicencio Serrano

Distribución natural de Bothriechis schlegelli en Costa Rica¶

Introducción¶

Bothriechis schlegelii, conocida como la víbora de pestañas o bocaracá, es una especie de serpiente venenosa ampliamente distribuida en los bosques húmedos de Costa Rica. Se caracteriza por su cuerpo esbelto, su variabilidad de color que va desde el verde brillante hasta tonos amarillos y marrones, y sus distintivas escamas supraoculares alargadas, que le dan la apariencia de "pestañas".

Bocaraca amarilla

Esta serpiente es un depredador eficiente que utiliza la caza al acecho, camuflándose entre la vegetación para emboscar pequeños vertebrados. Su importancia en los ecosistemas radica en su papel como regulador de poblaciones de presas y como indicador de la salud de los bosques tropicales. En Costa Rica, además, es una especie emblemática dentro de la herpetofauna y es clave en el ecoturismo y la educación ambiental, generando conciencia sobre la conservación de los ecosistemas donde habita.

Bocaraca colores

Se buscó una base de datos de GBIF, donde se filtró para tener registros solo de Costa Rica.

GBIF.org (03 March 2025) GBIF Occurrence Download https://doi.org/10.15468/dl.vqa2ch

Desarrollo¶

I Parte¶

Definir librerías y complementos a utilizar

In [ ]:
#Cargar e importar librerías
import geopandas as gpd
import pandas as pd
import plotly.express as px
import folium
from folium import Choropleth
import matplotlib.pyplot as plt
!pip install mapclassify --quiet
import mapclassify
import rasterio
import geopandas as gpd
import matplotlib.pyplot as plt
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/59.1 kB ? eta -:--:--
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 59.1/59.1 kB 1.6 MB/s eta 0:00:00

II Parte¶

Cargar base de datos y crear los dataframes y geodataframes a utilizar

In [ ]:
# Importar datos desde un CSV.
bocaraca_df = pd.read_csv(
    'https://raw.githubusercontent.com/villa27/GBIF/refs/heads/main/Bocaraca_CR.csv',
    sep='\t'
)

# Crear un GeoDataFrame a partir del DataFrame
bocaraca_gdf = gpd.GeoDataFrame(
    bocaraca_df,
    geometry=gpd.points_from_xy(bocaraca_df.decimalLongitude, bocaraca_df.decimalLatitude),
    crs='EPSG:4326'
)

# Mostrar los primeros registros del GeoDataFrame,
# incluyendo la columna de geometría
bocaraca_gdf[['gbifID', 'species', 'decimalLongitude', 'decimalLatitude', 'geometry']].head()
Out[ ]:
gbifID species decimalLongitude decimalLatitude geometry
0 911921901 Bothriechis schlegelii -84.689033 10.503133 POINT (-84.68903 10.50313)
1 894770240 Bothriechis schlegelii -84.300000 10.933333 POINT (-84.3 10.93333)
2 786457126 Bothriechis schlegelii -82.830000 9.630000 POINT (-82.83 9.63)
3 786457123 Bothriechis schlegelii -82.830000 9.630000 POINT (-82.83 9.63)
4 786449863 Bothriechis schlegelii -82.830000 9.630000 POINT (-82.83 9.63)
In [ ]:
# Mapa estático de registros de bocaraca
bocaraca_gdf.plot()
Out[ ]:
<Axes: >
No description has been provided for this image
In [ ]:
# Crear un geodataframe con datos y Área de Conservación
AC_gdf = gpd.read_file(
    'https://raw.githubusercontent.com/villa27/GBIF/refs/heads/main/AC.gpkg'
)

# Crear un geodataframe con datos y Área Silvestre Protegida
ASP_gdf = gpd.read_file(
    'https://raw.githubusercontent.com/villa27/GBIF/refs/heads/main/ASP.gpkg'
)

# Mostrar los primeros registros del GeoDataFrame,
# incluyendo la columna de geometría
#AC_gdf[['fid', 'nombre_ac', 'siglas_ac', 'geometry']].head()
AC_gdf.plot()
ASP_gdf.plot()
Out[ ]:
<Axes: >
No description has been provided for this image
No description has been provided for this image
In [ ]:
# Convertir el DataFrame de especies a un GeoDataFrame

df = bocaraca_df.dropna(subset=['decimalLongitude', 'decimalLatitude'])  # Eliminar filas sin coordenadas # Asignar bocaraca_df a df

gdf_especies = gpd.GeoDataFrame(df,
                                geometry=gpd.points_from_xy(df['decimalLongitude'], df['decimalLatitude']),
                                crs="EPSG:4326")  # Asegurar sistema de coordenadas WGS84

III Parte¶

Estadístiscos para demostrar la distribución natural de la Bocaracá en Costa Rica.

Nota: se consideró riqueza como el conteó de cada registro de la serpiente Bocaracá por provincia

In [ ]:
# Realizar el cruce espacial entre los registros y los polígonos
gdf_joined = gpd.sjoin(bocaraca_gdf, AC_gdf, how="left", predicate="within")

# Contar el número total de registros por Área de Conservación
registros_por_AC = gdf_joined.groupby('siglas_ac').size().reset_index()

# Renombrar las columnas
registros_por_AC.columns = ['siglas_ac', 'Cantidad de Registros']

# Ordenar los datos de mayor a menor
registros_por_AC = registros_por_AC.sort_values(by='Cantidad de Registros', ascending=False)

# Mostrar la tabla final
print(registros_por_AC)
  siglas_ac  Cantidad de Registros
0     ACAHN                    104
4     ACLAC                     93
2       ACC                     64
9      ACTo                     34
1      ACAT                     20
7     ACOSA                     10
5     ACLAP                      8
3       ACG                      5
6    ACOPAC                      5
8       ACT                      1

-Mediante plotly, genere un gráfico interactivo (ej. de barras) que muestre la riqueza de especies en cada polígono.

Según los datos del código anterior.

In [ ]:
# Crear un gráfico de barras interactivo
fig = px.bar(registros_por_AC,
             x='siglas_ac', # Changed from 'siglas_AC' to 'siglas_ac'
             y='Cantidad de Registros',
             title="Riqueza de Especies por Área de Conservación en Costa Rica",
             labels={'Riqueza de Especies': 'Número de Especies'},
             color='Cantidad de Registros',
             color_continuous_scale='viridis')

# Mostrar el gráfico
fig.show()

Según el gráfico el Área de Conservación Arenal Huétar Norte (ACAHN) es la región donde más registros se han presentado de la serpiente Bothriechis schlegelii, mientras que el Área de Conservación Tempisque es la zona con menos registros.

Se puede interpretar que los factores climáticos de cada zona tienen influencia sobre la distribución de la espcie (Pizzigalli et al., 2020; Ramírez et al., 2019).

In [ ]:
# Realizar el cruce espacial entre los registros y los polígonos
gdf_joined = gpd.sjoin(bocaraca_gdf, ASP_gdf, how="left", predicate="within")

# Contar el número total de registros por Área Silvestre Protegida
registros_por_ASP = gdf_joined.groupby('nombre_asp').size().reset_index()

# Renombrar las columnas
registros_por_ASP.columns = ['nombre_asp', 'Cantidad de Registros']

# Ordenar los datos de mayor a menor
registros_por_ASP = registros_por_ASP.sort_values(by='Cantidad de Registros', ascending=False)

# Mostrar la tabla final
print(registros_por_ASP)
                       nombre_asp  Cantidad de Registros
4                         Cahuita                     36
10                       La Selva                     24
1                          Arenal                     20
17                     Tortuguero                     11
2              Barra del Colorado                     10
6              Gandoca Manzanillo                      7
7                     Golfo Dulce                      3
8                      Guanacaste                      3
9        Internacional La Amistad                      2
11                   La Tirimbina                      2
14  Miravalles-Jorge Manuel Dengo                      1
16             Rincon de la Vieja                      1
15                 Pacuare Matina                      1
0      Acuiferos Guacimo y Pococi                      1
13                      Maquenque                      1
12                 Manuel Antonio                      1
5                       Corcovado                      1
3                Braulio Carrillo                      1
18               Volcan Turrialba                      1

Mediante folium, genere un mapa de coropletas interactivo que muestre la riqueza de especies en cada polígono.

In [ ]:
# Crear un gráfico de lineas interactivo
fig = px.line(registros_por_ASP,
             x='nombre_asp',
             y='Cantidad de Registros',
             title="Riqueza de Especies por Área de Conservación en Costa Rica",
             labels={'Riqueza de Especies': 'Número de Especies'},
                   color_discrete_sequence=['blue']
             )

# Mostrar el gráfico
fig.show()

En cuanto a las Áreas Silvestres Protegidas se observa un comportamiento similar, donde Cahuita, La Selva, Arenal y Tortuguero son las zonas con mayor incidencia de la serpiente.

In [ ]:
from google.colab import output
output.enable_custom_widget_manager()
In [ ]:
# Crear mapa leafmap
m = leafmap.Map(center=[9.6, -84.2], zoom=7, height="400px")  # Zoom to Costa Rica

m.add_data(
    ASP_gdf,
    column="siglas_cat",
    scheme="NaturalBreaks",
    cmap="gist_earth",
    legend_title="Categoría de manejo",
    categorical=True
)

# Desplegar el mapa
m
Map(center=[9.6, -84.2], controls=(ZoomControl(options=['position', 'zoom_in_text', 'zoom_in_title', 'zoom_out…

Support for third party widgets will remain active for the duration of the session. To disable support:

In [ ]:
from google.colab import output
output.disable_custom_widget_manager()
In [ ]:
# Mapa interactivo de registros de Bocaraca
bocaraca_gdf[(bocaraca_gdf['decimalLongitude'] < 0) & (bocaraca_gdf['decimalLatitude'] < 16)].explore()
Out[ ]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [ ]:
# Mapa de coropletas
AC_gdf.plot(
    column='siglas_ac',
    cmap='YlOrRd', # https://matplotlib.org/stable/gallery/color/colormap_reference.html
    legend=True,
    legend_kwds={
        'title': "Áreas de Conservación", # Changed 'label' to 'title'
        # Removed 'orientation': "horizontal" as it is not a valid keyword argument here
        # You can use plt.gca().legend().set_bbox_to_anchor((x,y)) for positioning the legend or
    },
    figsize=(12, 8)
)
Out[ ]:
<Axes: >
No description has been provided for this image
In [ ]:
# Instalación de rasterio
!pip install rasterio --quiet
In [ ]:
# Carga de rasterio
import rasterio

# Carga de rasterio.plot (para graficar datos raster)
import rasterio.plot

# Carga de numpy (para álgebra lineal)
import numpy as np

# Carga de matplotlib.pyplot
import matplotlib.pyplot as plt
In [ ]:
# Carga de datos de elevacion
elevacion = rasterio.open(
    'https://raw.githubusercontent.com/villa27/GBIF/refs/heads/main/wc2.1_2.5m_elev.tif'
)

print(elevacion)
print(f"Ancho: {elevacion.width}")
print(f"Alto: {elevacion.height}")
print(f"Número de bandas: {elevacion.count}")
print(f"CRS: {elevacion.crs}")
print(f"Transformación: {elevacion.transform}")
print(f"Tipos de datos: {elevacion.dtypes}")
print(f"Límites: {elevacion.bounds}")
<open DatasetReader name='https://raw.githubusercontent.com/villa27/GBIF/refs/heads/main/wc2.1_2.5m_elev.tif' mode='r'>
Ancho: 8640
Alto: 4320
Número de bandas: 1
CRS: EPSG:4326
Transformación: | 0.04, 0.00,-180.00|
| 0.00,-0.04, 90.00|
| 0.00, 0.00, 1.00|
Tipos de datos: ('int16',)
Límites: BoundingBox(left=-180.0, bottom=-90.0, right=180.0, top=90.0)
In [ ]:
# Mapa de elevación
rasterio.plot.show(elevacion)
No description has been provided for this image
Out[ ]:
<Axes: >
In [ ]:
fig, ax = plt.subplots(figsize=(8, 8))

# Mapa de elevacion
rasterio.plot.show(
    elevacion,
    cmap="terrain", # colores
    ax=ax,
    title="Elevación"
)

# Agregar una leyenda
cbar = fig.colorbar(ax.images[0], ax=ax, shrink=1)
cbar.set_label('msnm')

# Limitar el rango de los ejes
ax.set_xlim(-86, -82)
ax.set_ylim(8, 11)

plt.show()
No description has been provided for this image
In [ ]:
# Cargar datos de elevación
with rasterio.open('https://raw.githubusercontent.com/villa27/GBIF/refs/heads/main/wc2.1_2.5m_elev.tif') as elevacion:

    # Cargar datos de ubicaciones
    ubicaciones = gpd.read_file('https://raw.githubusercontent.com/villa27/GBIF/refs/heads/main/Bocaraca_CR.csv',
                                 sep='\t',  # Asumiendo valores separados por tabulaciones en el CSV
                                 encoding='latin-1'  # Manejar posibles problemas de codificación
                                 )
    # Convertir 'decimalLongitude' y 'decimalLatitude' a numérico
    ubicaciones['decimalLongitude'] = pd.to_numeric(ubicaciones['decimalLongitude'], errors='coerce')
    ubicaciones['decimalLatitude'] = pd.to_numeric(ubicaciones['decimalLatitude'], errors='coerce')

    # Crear columna de geometría si no existe
    if 'geometry' not in ubicaciones.columns:
        ubicaciones = gpd.GeoDataFrame(
            ubicaciones,
            geometry=gpd.points_from_xy(ubicaciones.decimalLongitude, ubicaciones.decimalLatitude),
            crs='EPSG:4326'
        )
    else:
        # Asegurar que la columna de geometría esté en el formato correcto
        ubicaciones['geometry'] = gpd.GeoSeries.from_wkt(ubicaciones['geometry'])
        ubicaciones = ubicaciones.set_crs('EPSG:4326')


    # Crear la gráfica
    fig, ax = plt.subplots(figsize=(10, 10))

    # Mostrar datos de elevación
    rasterio.plot.show(elevacion, ax=ax, cmap='terrain')

    # Mostrar datos de ubicaciones
    ubicaciones.plot(ax=ax, marker='o', color='red', markersize=5, label='Observaciones')

    # Agregar título, etiquetas y leyenda
    plt.title('Distribución de la Bocaraca según la elevación en Costa Rica')
    plt.xlabel('Longitud')
    plt.ylabel('Latitud')
    plt.legend()

    # Hacer zoom en Costa Rica
    ax.set_xlim(-86, -82)
    ax.set_ylim(8, 11)

    plt.show()
No description has been provided for this image

Conclusiones¶

Realizar estudios sobre la distribución y riqueza de las especies, permite tomar desiciones para su conservación y manejo

El uso de herramientas y plataformas como GBIF, en conjunto con Python facilita el análisis y estudio de las especies, más en paises como Costa Rica con alta diversidad y politicas de conservación

Referencias bibliográficas¶

Díaz Gómez, S. M., & Molina Betancourth, K. J. (2022). Modelos de distribución potencial de las serpientes venenosas Bothrops asper, Bothrops punctatus y Bothriechis schlegelii con aportes al conocimiento del accidente ofídico en el departamento Caldas, Colombia.

Sorrell, G. G. (2009). Diel movement and predation activity patterns of the eyelash palm-pitviper (Bothriechis schlegelii). Copeia, 2009(1), 105-109.

Ramirez-Arce, D., Vega-Coto, J. O. N. A. T. H. A. N., Zúñiga-Ortiz, A., Artavia-León, A., Baaijen, W., & WasKo, D. K. (2019). Snake diversity (Squamata: Serpentes) in Quebrada González Sector of Braulio Carrillo National Park, Costa Rica. Herpetological Conservation and Biology, 14(1), 212-222.

Pizzigalli, C., Banfi, F., Ficetola, G. F., Falaschi, M., Mangiacotti, M., Sacchi, R., ... & Scali, S. (2020). Eco-geographical determinants of the evolution of ornamentation in vipers. Biological Journal of the Linnean Society, 130(2), 345-358.

Instituto Clodomiro Picado. () Serpientes venenosas de C. Disponible en: https://www.icp.ucr.ac.cr/es/informacion-y-materiales/serpientes-venenosas-de-costa-rica/bothriechis-schlegelii