Proyecto, Curso de Acceso de Datos Geoespaciales¶

Escrito por:
Jeffrey Tapia (jeffreytapia@gmail.com)
2025-07-03

Introducción¶

El presente proyecto tiene como objetivo analizar la distribución de especies arbóreas en las provincias de Heredia y San José, Costa Rica, a partir de un dataset con datos recolectados en los últimos 50 años. Este conjunto de datos proporciona información valiosa sobre la diversidad y distribución espacial de las especies, permitiendo evaluar patrones ecológicos a lo largo del tiempo.

Para facilitar la interpretación de estos datos, el análisis incluye diversas representaciones visuales y espaciales:

Gráficos de distribución de especies por provincia, que permiten comparar la riqueza arbórea entre Heredia y San José. Gráfico de distribución altitudinal de especies, para analizar cómo varían las especies en función de la altitud. Mapa con un polígono de países y puntos de registro, donde se visualizan las ubicaciones de los árboles registrados. Mapa con un raster recortado de variables biológicas y puntos de presencia de las especies, proporcionando un análisis geoespacial de los factores ambientales que pueden influir en la distribución de la vegetación. Este estudio no solo contribuye a la comprensión de la biodiversidad arbórea en la región, sino que también puede servir como insumo para futuras investigaciones en conservación y manejo sostenible de los ecosistemas forestales.

Instalación¶

In [ ]:
# Instalación de leafmap
!pip install leafmap --quiet

# Instalación de rasterio
!pip install rasterio --quiet

# Instalación de mapclassify
!pip install mapclassify --quiet

# Instalación de localtileserver
!pip install localtileserver --quiet
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/519.2 kB ? eta -:--:--
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╺ 512.0/519.2 kB 15.8 MB/s eta 0:00:01
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 519.2/519.2 kB 10.0 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 219.1/219.1 kB 12.6 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 7.7/7.7 MB 73.8 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 41.4/41.4 kB 2.5 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 108.6/108.6 kB 6.6 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.7/2.7 MB 69.9 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 765.5/765.5 kB 29.5 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 194.2/194.2 kB 12.1 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 74.0/74.0 kB 3.9 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.6/1.6 MB 16.2 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 22.2/22.2 MB 50.9 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 59.1/59.1 kB 103.7 kB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 17.1/17.1 MB 16.3 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.8/2.8 MB 40.7 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 267.5/267.5 kB 9.5 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 52.8/52.8 kB 2.2 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 49.5/49.5 kB 1.2 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 195.0/195.0 kB 10.3 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 62.3/62.3 kB 3.6 MB/s eta 0:00:00

Carga de Librerías y Datos¶

In [ ]:
import pandas as pd
import seaborn as sns
import folium
# Para mapas interactivos
import leafmap

# Para datos vectoriales
import geopandas as gpd

# Para datos raster
import rasterio

# Para gráficos
import matplotlib.pyplot as plt

# Para crear rampas de colores
from matplotlib.colors import LinearSegmentedColormap

# Para álgebra lineal
import numpy as np

# Para permitir widgets de JavaScript
from google.colab import output
output.enable_custom_widget_manager()
In [ ]:
from google.colab import drive
drive.mount('/content/drive')
Mounted at /content/drive
In [ ]:
!ls /content/drive/MyDrive/Procesamiento_Datos_Geograficos/
 Arboles_combinado.csv	 paises.gpkg			      'Tarea3 Procesamiento DG.ipynb'
 NE1_CostaRica.tif	 pinguinos.csv
 NE1.tif		'Proyecto Datos Geoespaciales.ipynb'
In [ ]:
# Ruta del archivo (ajusta si es necesario)
ruta_csv = '/content/drive/MyDrive/Procesamiento_Datos_Geograficos/Arboles_combinado.csv'

# Cargando el CSV
df = pd.read_csv(ruta_csv, sep=';',
    thousands='.')

# Mostrando las primeras filas
df.head()
Out[ ]:
Numero de catalogo Familia Genero Especie rango Provincia Canton Distrito Localidad Area protegida ... Altitud max. Notas de campo Fenologia Procedencia Descripcion diagnostica Distribucion Nacional Distribucion altitudinal Forma de crecimiento Habitat Nombres comunes
0 47 Solanaceae Cestrum Cestrum aurantiacum Especie San José San José Pavas Bords des fossés à San José. NaN ... 1160.0 NaN NaN Nativa Arbusto o árbol, 0.9–6 m, a veces tendido o (p... NaN NaN Arbustos a árboles, terrestres, autótrofos, er... NaN NaN
1 57 Papaveraceae Bocconia Bocconia frutescens Especie San José Curridabat Curridabat Taillis et buissons à Curridabat, près San José. NaN ... 1200.0 NaN NaN Nativa Arbusto o árbol, ca. 0.7–7 m. ambas verts. todas las cords. principales, ver... (100–)400–2800(–3300) m Arbustos, terrestres, autótrofos, erectos Bosque muy húmedo, pluvial, nuboso y de roble,... Cacho de venado, Guacamaya, Guacamayo, Papayil...
2 84 Solanaceae Solanum Solanum umbellatum Especie San José San José Pavas Haies et bords des chemins autour de San José. NaN ... 1135.0 NaN NaN Nativa Sufrútice, arbusto o árbol, 0.75–5 m, densamen... NaN NaN Sufrútices, arbustos o árboles, terrestres, au... NaN Bodoque, Zorrillo
3 293 Euphorbiaceae Croton Croton hoffmannii Especie San José San José Pavas Dans les haie autour de San José. NaN ... 1135.0 N. V. targuá. NaN Nativa Arbusto o árbol, 1.5–6 m, con indumento de tri... vert. Carib. Cord. de Guanacaste, N Cord. de T... 700–1350+ m Arbustos o árboles, terrestres, autótrofos, er... Bosque húmedo y muy humedo Colpachí, Targuá
4 294 Rubiaceae Palicourea Palicourea pubescens Especie San José San José Pavas Dans les haie autour de San José. NaN ... 1135.0 NaN NaN Nativa NaN NaN NaN Sufrútices, arbustos o árboles, terrestres, au... NaN NaN

5 rows × 23 columns

Pre Procesado de Datos¶

In [ ]:
# Verificando valores nulos
print("\nValores Nulos por Columna:")
print(df.isnull().sum())

# Eliminando filas sin coordenadas geográficas
df = df.dropna(subset=['Latitud Decimal', 'Longitud Decimal'])

# Resumen estadístico de columnas numéricas
df.describe()
Valores Nulos por Columna:
Numero de catalogo             0
Familia                        0
Genero                         0
Especie                        0
rango                          0
Provincia                      0
Canton                         6
Distrito                     270
Localidad                     49
Area protegida              6299
Longitud Decimal               0
Latitud Decimal                0
Altitud min.                 463
Altitud max.                 463
Notas de campo               484
Fenologia                   2804
Procedencia                    0
Descripcion diagnostica     1451
Distribucion Nacional       6668
Distribucion altitudinal    6296
Forma de crecimiento         554
Habitat                     6807
Nombres comunes             9853
dtype: int64
Out[ ]:
Numero de catalogo Longitud Decimal Latitud Decimal Altitud min. Altitud max.
count 2.249200e+04 2.249200e+04 2.249200e+04 22029.000000 22029.000000
mean 1.457922e+06 -8.391551e+11 9.906269e+10 1152.800309 1223.712697
std 1.587106e+06 4.477704e+10 3.322643e+09 817.799289 853.052176
min 4.700000e+01 -8.672889e+11 8.006111e+10 0.000000 0.000000
25% 1.886028e+05 -8.419722e+11 9.700000e+10 480.000000 500.000000
50% 2.672265e+05 -8.409447e+11 9.873250e+10 1000.000000 1100.000000
75% 2.913551e+06 -8.401632e+11 1.013483e+11 1740.000000 1800.000000
max 5.154992e+06 8.409361e+11 2.550000e+11 3741.000000 21888.000000
In [ ]:
# Contar la cantidad de registros por especie
conteo_por_especie = df['Especie'].value_counts()

# Obtener las especies con 50 o más registros
especies_mas_50 = conteo_por_especie[conteo_por_especie >= 50].index

# Filtrar el dataset original para incluir solo estas especies
df_filtrado = df[df['Especie'].isin(especies_mas_50)]

# Verificar el tamaño del nuevo dataframe
print(f'Tamaño del nuevo dataset filtrado: {df_filtrado.shape}')
Tamaño del nuevo dataset filtrado: (3700, 23)
In [ ]:
# Redondear las columnas Longitud decimal y Latitud decimal a 2 decimales
df_filtrado['Longitud Decimal'] = df_filtrado['Longitud Decimal'] / 1e10
df_filtrado['Longitud Decimal'] = df_filtrado['Longitud Decimal'].round(2)
df_filtrado['Latitud Decimal'] = df_filtrado['Latitud Decimal'] / 1e10
df_filtrado['Latitud Decimal'] = df_filtrado['Latitud Decimal'].round(2)
df_filtrado.head()
Out[ ]:
Numero de catalogo Familia Genero Especie rango Provincia Canton Distrito Localidad Area protegida ... Altitud max. Notas de campo Fenologia Procedencia Descripcion diagnostica Distribucion Nacional Distribucion altitudinal Forma de crecimiento Habitat Nombres comunes
0 47 Solanaceae Cestrum Cestrum aurantiacum Especie San José San José Pavas Bords des fossés à San José. NaN ... 1160.0 NaN NaN Nativa Arbusto o árbol, 0.9–6 m, a veces tendido o (p... NaN NaN Arbustos a árboles, terrestres, autótrofos, er... NaN NaN
1 57 Papaveraceae Bocconia Bocconia frutescens Especie San José Curridabat Curridabat Taillis et buissons à Curridabat, près San José. NaN ... 1200.0 NaN NaN Nativa Arbusto o árbol, ca. 0.7–7 m. ambas verts. todas las cords. principales, ver... (100–)400–2800(–3300) m Arbustos, terrestres, autótrofos, erectos Bosque muy húmedo, pluvial, nuboso y de roble,... Cacho de venado, Guacamaya, Guacamayo, Papayil...
8 445 Solanaceae Cestrum Cestrum aurantiacum Especie San José San José Pavas Bords des fossés à San José. NaN ... 1200.0 NaN NaN Nativa Arbusto o árbol, 0.9–6 m, a veces tendido o (p... NaN NaN Arbustos a árboles, terrestres, autótrofos, er... NaN NaN
11 514 Solanaceae Cestrum Cestrum aurantiacum Especie San José San José Pavas Environs à San José. NaN ... NaN NaN NaN Nativa Arbusto o árbol, 0.9–6 m, a veces tendido o (p... NaN NaN Arbustos a árboles, terrestres, autótrofos, er... NaN NaN
22 1099 Solanaceae Cestrum Cestrum aurantiacum Especie San José San José Pavas Bords d' un chemin à San José. NaN ... 1160.0 NaN NaN Nativa Arbusto o árbol, 0.9–6 m, a veces tendido o (p... NaN NaN Arbustos a árboles, terrestres, autótrofos, er... NaN NaN

5 rows × 23 columns

In [ ]:
# Lista con los números de catálogo que deseas eliminar
numeros_a_eliminar = [129440,155966,4469155,228606,91767,203988,5151892,299687]  # Reemplaza estos valores con los que necesites eliminar

# Eliminando los registros
df_filtrado = df_filtrado[~df_filtrado['Numero de catalogo'].isin(numeros_a_eliminar)]

# Verificando si se eliminaron correctamente
print("Registros después de la eliminación:")
print(df[df['Numero de catalogo'].isin(numeros_a_eliminar)])
Registros después de la eliminación:
       Numero de catalogo         Familia      Genero  \
2427                91767      Clusiaceae   Symphonia   
3313               129440      Clusiaceae   Symphonia   
6232               203988    Siparunaceae    Siparuna   
7923               228606    Siparunaceae    Siparuna   
17483             4469155        Fagaceae     Quercus   
17538             5151892        Moraceae       Ficus   
21257              155966  Phyllanthaceae   Hieronyma   
24427              299687     Monimiaceae  Mollinedia   

                        Especie    rango Provincia         Canton    Distrito  \
2427      Symphonia globulifera  Especie  San José            NaN         NaN   
3313      Symphonia globulifera  Especie  San José            NaN         NaN   
6232      Siparuna gesnerioides  Especie  San José  Pérez Zeledón        Barú   
7923      Siparuna gesnerioides  Especie  San José     Turrubares      Carara   
17483       Quercus bumelioides  Especie  San José           Dota       Copey   
17538             Ficus pertusa  Especie  San José  Montes de Oca  San Rafael   
21257         Hieronyma oblonga  Especie   Heredia          Barva         NaN   
24427  Mollinedia costaricensis  Especie   Heredia      Sarapiquí         NaN   

                                               Localidad   Area protegida  \
2427   P.N. Amistad, Las Tablas , near the upper Río ...              NaN   
3313   P.N. Braulio Carrillo; alrededores Estacion Ca...              NaN   
6232   Secondary groth and evergreen tropical wet for...              NaN   
7923                                                 NaN              NaN   
17483  Área de Conservación Amistad Pacífico, orillas...  R.F. Los Santos   
17538  Parque Recreativo del Este. Sobre el sendero q...     No protegida   
21257  P.N. Braulio Carrillo. Paso Llano, Reserva de ...              NaN   
24427      E.B. La Selva.  Jardines de Laboratorios 0 m.              NaN   

       ...  Altitud max.                                     Notas de campo  \
2427   ...        1500.0                             Tree approx. 15 m tal.   
3313   ...         700.0  Arbusto de 3.5 m. Inflorescencia de color rosa...   
6232   ...         500.0  Slender treelet about 3 m tall arching from a ...   
7923   ...         361.0  Arbusto de 3.5 m. A la orilla del camino.  Fru...   
17483  ...        1824.0  Tree of 10 m high, 25 cm dbh., trunk with scal...   
17538  ...        1375.0  Arbolito. 4 m de alto. Con savia lechosa. Tall...   
21257  ...        2000.0  Árbol de 15 m x 30 cm DAP. Inflorescencia café...   
24427  ...         150.0  Arbusto, alt. 4 m., DAP 5 cm. Flores amarillas.     

       Fenologia  Procedencia  \
2427         NaN       Nativa   
3313        Flor       Nativa   
6232        Flor       Nativa   
7923       Fruto       Nativa   
17483    Estéril       Nativa   
17538      Fruto       Nativa   
21257       Flor       Nativa   
24427       Flor       Nativa   

                                 Descripcion diagnostica  \
2427   Arbusto o árbol, 1.3–40 m, terrestre o (rara v...   
3313   Arbusto o árbol, 1.3–40 m, terrestre o (rara v...   
6232   Arbusto o árbol, 1–8 m, a veces escandente, di...   
7923   Arbusto o árbol, 1–8 m, a veces escandente, di...   
17483  Arbolito o (más frecuente) árbol, (3–)6–40 m, ...   
17538  Arbusto o árbol de hasta 14 m. de altura, a ve...   
21257  Arbusto o árbol, 3–40 m; estípulas sésiles, ha...   
24427  Arbusto o arbolito, 2–10 m, ocasionalmente tre...   

                                   Distribucion Nacional  \
2427                                                 NaN   
3313                                                 NaN   
6232   Vert. Carib. Cord. de Guanacaste, N Cord. de T...   
7923   Vert. Carib. Cord. de Guanacaste, N Cord. de T...   
17483  Ambas verts. Cords. Central y de Talamanca, ve...   
17538  Ampliamente distribuido en todo el país hasta ...   
21257  Ambas verts. de las Cords. (principalmente); v...   
24427  Vert. Carib. y cerca de la División Continenta...   

      Distribucion altitudinal  \
2427                       NaN   
3313                       NaN   
6232        0–2000(–2300) msnm   
7923        0–2000(–2300) msnm   
17483             1600-2600 m.   
17538              0-2000 msnm   
21257                 500-2500   
24427                0-1900 m.   

                                    Forma de crecimiento  \
2427   Arbustos a árboles, terrestres, autótrofos, er...   
3313   Arbustos a árboles, terrestres, autótrofos, er...   
6232   Arbustos o árboles, terrestres, autótrofos, er...   
7923   Arbustos o árboles, terrestres, autótrofos, er...   
17483           Árboles, terrestres, autótrofos, erectos   
17538  Arbustos a árboles, hemi-epífitas, autótrofos,...   
21257  Arbustos o árboles, terrestres, autótrofos, er...   
24427  Arbustos a árboles, terrestres, autótrofos, er...   

                                                 Habitat  \
2427                                                 NaN   
3313                                                 NaN   
6232   Bosque húmedo, muy húmedo, pluvial, nuboso y d...   
7923   Bosque húmedo, muy húmedo, pluvial, nuboso y d...   
17483  Bosque primario, bosque secundario, áreas alte...   
17538               Bosque muy húmedo, pluvial y nuboso.   
21257                      Bosques húmedos y muy humedos   
24427       Bosque húmedo, muy húmedo, pluvial y nuboso.   

                                         Nombres comunes  
2427   Amarillo, Botoncillo, Caraña, Cerillo, Leche a...  
3313   Amarillo, Botoncillo, Caraña, Cerillo, Leche a...  
6232                                           Limoncilo  
7923                                           Limoncilo  
17483  Barcino blanco, Encino, Roble, Roble barsino, ...  
17538                                  Higuerón, Higuito  
21257  Algodoncillo, Ascá, Campano, Comenegro, Cucara...  
24427                                         Limoncillo  

[8 rows x 23 columns]

Gráficos¶

In [ ]:
# Gráfico de barras para ver la distribución de especies por provincia
plt.figure(figsize=(10, 6))
sns.countplot(y='Provincia', data=df, order=df_filtrado['Provincia'].value_counts().index, palette='viridis')
plt.title('Distribución de Especies por Provincia')
plt.xlabel('Cantidad de Registros')
plt.ylabel('Provincia')
plt.show()
No description has been provided for this image
In [ ]:
# Gráfico de dispersión para altitud mínima y máxima
plt.figure(figsize=(10, 6))
sns.scatterplot(x='Altitud min.', y='Altitud max.', hue='Provincia', data=df_filtrado, palette='coolwarm')
plt.title('Distribución Altitudinal de las Especies')
plt.xlabel('Altitud Mínima (m)')
plt.ylabel('Altitud Máxima (m)')
plt.show()
No description has been provided for this image
In [ ]:
# Crear un geodataframe con datos y polígonos de paises
paises_gdf = gpd.read_file(
    'https://raw.githubusercontent.com/datos-geoespaciales-biodiversidad/python/refs/heads/main/datos/otros/naturalearth/paises.gpkg'
)
In [ ]:
# Verificando el geodataframe de países
print("Columnas del GeoDataFrame de países:")
print(paises_gdf.columns)
Columnas del GeoDataFrame de países:
Index(['featurecla', 'scalerank', 'LABELRANK', 'SOVEREIGNT', 'SOV_A3',
       'ADM0_DIF', 'LEVEL', 'TYPE', 'TLC', 'ADMIN',
       ...
       'FCLASS_TR', 'FCLASS_ID', 'FCLASS_PL', 'FCLASS_GR', 'FCLASS_IT',
       'FCLASS_NL', 'FCLASS_SE', 'FCLASS_BD', 'FCLASS_UA', 'geometry'],
      dtype='object', length=169)
In [ ]:
# Mapa interactivo con coordenadas corregidas
mapa = folium.Map(location=[9.7489, -83.7534], zoom_start=8)

# Agregando la capa de polígonos de países
folium.GeoJson(
    paises_gdf,
    name='Países',
    style_function=lambda x: {
        'fillColor': 'green',
        'color': 'black',
        'weight': 1,
        'fillOpacity': 0.2
    }
).add_to(mapa)

for _, row in df_filtrado.iterrows():
    folium.Marker(
        location=[row['Latitud Decimal'], row['Longitud Decimal']],
        popup=f"Especie: {row['Numero de catalogo']}, Provincia: {row['Provincia']}"
    ).add_to(mapa)

# Agregando control de capas
folium.LayerControl().add_to(mapa)

# Mostrando el mapa
mapa
Out[ ]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [ ]:
# Carga de datos de temperatura media anual
variablesBiologicas = rasterio.open(
    '/content/drive/MyDrive/Procesamiento_Datos_Geograficos/NE1.tif'
)

print(variablesBiologicas)
<open DatasetReader name='/content/drive/MyDrive/Procesamiento_Datos_Geograficos/NE1.tif' mode='r'>
In [ ]:
import rasterio

# Abrir el archivo raster
with rasterio.open('/content/drive/MyDrive/Procesamiento_Datos_Geograficos/NE1.tif') as src:
    print("Sistema de coordenadas:", src.crs)
    print("Extensión del raster:", src.bounds)
    print("Resolución:", src.res)
Sistema de coordenadas: EPSG:4326
Extensión del raster: BoundingBox(left=-179.99999999999997, bottom=-89.99999999998201, right=179.99999999996405, top=90.0)
Resolución: (0.03333333333333, 0.03333333333333)
In [ ]:
import rasterio
from rasterio.mask import mask
from shapely.geometry import box
import geopandas as gpd

# Definir los límites de Costa Rica
bounds = box(-86, 8, -82, 11)

# Abrir el raster original
with rasterio.open('/content/drive/MyDrive/Procesamiento_Datos_Geograficos/NE1.tif') as src:
    out_image, out_transform = mask(src, [bounds], crop=True)
    out_meta = src.meta.copy()

# Actualizar metadatos del raster recortado
out_meta.update({
    "driver": "GTiff",
    "height": out_image.shape[1],
    "width": out_image.shape[2],
    "transform": out_transform
})

# Guardar el raster recortado
recortado_path = '/content/drive/MyDrive/Procesamiento_Datos_Geograficos/NE1_CostaRica.tif'
with rasterio.open(recortado_path, 'w', **out_meta) as dest:
    dest.write(out_image)

print("Raster recortado guardado en:", recortado_path)
Raster recortado guardado en: /content/drive/MyDrive/Procesamiento_Datos_Geograficos/NE1_CostaRica.tif
In [ ]:
df_filtrado.reset_index(drop=True, inplace=True)
In [ ]:
import leafmap
import pandas as pd

# Verificar si df_filtrado es un DataFrame
if not isinstance(df_filtrado, pd.DataFrame):
    raise TypeError("Error: df_filtrado no es un DataFrame de Pandas.")

# Verificar nombres de columnas
print("Nombres de columnas:", df_filtrado.columns.tolist())

# Eliminar espacios en los nombres de las columnas
df_filtrado.rename(columns=lambda x: x.strip(), inplace=True)

# Revisar si existen las columnas correctas
if "Latitud Decimal" not in df_filtrado.columns or "Longitud Decimal" not in df_filtrado.columns:
    raise KeyError("Las columnas 'Latitud Decimal' y 'Longitud Decimal' no se encuentran en df_filtrado.")

# Asegurar que las columnas son numéricas
df_filtrado["Latitud Decimal"] = pd.to_numeric(df_filtrado["Latitud Decimal"], errors="coerce")
df_filtrado["Longitud Decimal"] = pd.to_numeric(df_filtrado["Longitud Decimal"], errors="coerce")

# Verificar si hay valores NaN después de la conversión
if df_filtrado[["Latitud Decimal", "Longitud Decimal"]].isna().sum().sum() > 0:
    print("Advertencia: Hay valores NaN en las columnas de coordenadas. Revisa los datos.")

# Crear el objeto Map de leafmap
m = leafmap.Map(
    height="800px",
    location=[9.7489, -83.7534],  # Centro aproximado de Costa Rica
    zoom=10  # Ajusta el zoom según sea necesario
)

# Establecer los límites del mapa con fit_bounds
bounds = [
    [8.0, -86.0],  # Coordenadas del suroeste (Sur, Oeste)
    [11.0, -82.0]  # Coordenadas del noreste (Norte, Este)
]
m.fit_bounds(bounds)

# Agregar el raster local (si es necesario)
m.add_raster(
    '/content/drive/MyDrive/Procesamiento_Datos_Geograficos/NE1_CostaRica.tif',
    colormap='viridis',
    layer_name='Variables Biológicas'
)


# Agregar los puntos al mapa
m.add_points_from_xy(
    df_filtrado,
    x="Longitud Decimal",
    y="Latitud Decimal",
    layer_name="Especies de Árboles",
    icon_colors="red",
)

# Desplegar el mapa
m
Nombres de columnas: ['Numero de catalogo', 'Familia', 'Genero', 'Especie', 'rango', 'Provincia', 'Canton', 'Distrito', 'Localidad', 'Area protegida', 'Longitud Decimal', 'Latitud Decimal', 'Altitud min.', 'Altitud max.', 'Notas de campo', 'Fenologia', 'Procedencia', 'Descripcion diagnostica', 'Distribucion Nacional', 'Distribucion altitudinal', 'Forma de crecimiento', 'Habitat', 'Nombres comunes']
Map(center=[9.4833335, -83.9833335], controls=(ZoomControl(options=['position', 'zoom_in_text', 'zoom_in_title…