folium: paquete para desarrollo de mapas web#

Descripción general#

folium es una biblioteca de Python para el desarrollo de mapas web, basada en la biblioteca Leaflet de JavaScript. Así, es posible manipular los datos con bibliotecas de Python (ej. pandas, GeoPandas) y presentarlos en mapas Leaflet a través de folium.

folium sigue el paradigma de Programación Orientada a Objetos, por lo que se implementa a través de un conjunto de clases. Algunas de las principales son:

  • Map: para crear y configurar un mapa folium.

  • TileLayer: para crear una capa de teselas y agregarla a un mapa.

  • LayerControl: para crear un control de capas para un mapa.

Instalación#

folium puede instalarse con pip, conda o mamba, desde la línea de comandos del sistema operativo. Solo es necesario hacerlo de una forma.

# Con pip:
pip install folium

# Con conda:
conda install folium -c conda-forge

# Con mamba:
mamba install folium -c conda-forge

Carga#

# Carga de folium
import folium

# Versión de folium
folium.__version__
'0.12.1.post1'

Opciones básicas de configuración#

Las siguientes son algunas de las opciones de configuración que provee la clase Map.

# Creación de un mapa con un centro x, y (argumento location)
m = folium.Map(location=[10, -84])

# Despliegue del mapa en el notebook
m
Make this Notebook Trusted to load map: File -> Trust Notebook
# Especificación del ancho y del largo (en pixeles) del mapa (argumentos width y height)
m = folium.Map(
    location=[10, -84], 
    width=650, height=400)

m
Make this Notebook Trusted to load map: File -> Trust Notebook
# Especificación del nivel inicial de acercamiento (argumento zoom_start)
m = folium.Map(
    location=[10, -84], 
    width=650, height=400, 
    zoom_start=7)

m
Make this Notebook Trusted to load map: File -> Trust Notebook

Manejo de capas base#

Las capas base que se usan en los mapas web, suelen estar implementadas mediante tiles (mosaicos, teselas). Unen múltiples fragmentos rectangulares del mapa y los despliegan de manera conjunta, siguiendo acciones como acercamientos (zoom in) y alejamientos (zoom out). Ejemplos populares de servicios web geoespaciales que utilizan esta arquitectura son OpenStreetMap y Google Maps, entre muchos otros.

Los mapas de teselas utilizan un estándar “de facto” conocido como slippy map o XYZ. Según este, los archivos de las teselas (ej. PNG) se referencian a través de coordenadas X, Y e Z (de zoom).

folium ofrece un conjunto de capas de teselas predeterminadas y también la posibilidad de utilizar otras.

Capas predeterminadas#

Por defecto, folium utiliza OpenStreetMap como mapa base. Pueden elegirse otros mapas base mediante el argumento tiles, el cual tiene un conjunto de valores predeterminados:

  • “OpenStreetMap”

  • “Mapbox Bright”

  • “Mapbox Control Room”

  • “Stamen” (“Terrain”, “Toner” y “Watercolor”)

  • “Cloudmade” (Requiere una llave del API)

  • “Mapbox” (Requiere una llave del API)

  • “CartoDB” (“positron” y “dark_matter”)

# Mapa de Stamen Terrain
m = folium.Map(
    location=[10, -84], 
    width=650, height=400, 
    zoom_start=5, 
    tiles='Stamen Terrain')
m
Make this Notebook Trusted to load map: File -> Trust Notebook
# Mapa de Stamen Toner
m = folium.Map(
    location=[10, -84], 
    width=650, height=400, 
    zoom_start=7, 
    tiles='Stamen Toner')

m
Make this Notebook Trusted to load map: File -> Trust Notebook
# Mapa de Stamen Watercolor
m = folium.Map(
    location=[10, -84], 
    width=650, height=400, 
    zoom_start=7, 
    tiles='Stamen Watercolor')

m
Make this Notebook Trusted to load map: File -> Trust Notebook
# Mapa de CartoDB positron
m = folium.Map(
    location=[10, -84], 
    width=650, height=400, 
    zoom_start=7, 
    tiles='CartoDB positron')

m
Make this Notebook Trusted to load map: File -> Trust Notebook
# Mapa de CartoDB dark_matter
m = folium.Map(
    location=[10, -84], 
    width=650, height=400, 
    zoom_start=7, 
    tiles='CartoDB dark_matter')

m
Make this Notebook Trusted to load map: File -> Trust Notebook

Otras capas XYZ#

El siguiente es un ejemplo que utiliza como capa base el mapa “World Imagery” de ESRI. Pueden verse más ejemplos de mapas de ESRI en https://ocefpaf.github.io/python4oceanographers/blog/2015/03/23/wms_layers/.

# Mapa "World Imagery "de ESRI
m = folium.Map(
    location=[10, -84], 
    width=650, height=400, 
    zoom_start=7, 
    tiles='http://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/MapServer/tile/{z}/{y}/{x}', 
    attr='ESRI World Imagery')

m
Make this Notebook Trusted to load map: File -> Trust Notebook

Registros de presencia de especies en la Infraestructura Mundial de Información en Biodiversidad (GBIF). Pueden verse más ejemplos de uso de este tipo de información en la documentación del API de mapas de GBIF.

# Registros de presencia de especies en GBIF
m = folium.Map(
    location=[0, 0],
    width=650, height=400,
    zoom_start=1,
    tiles='https://api.gbif.org/v2/map/occurrence/density/{z}/{x}/{y}@1x.png?style=purpleYellow.point',
    attr='GBIF')

m
Make this Notebook Trusted to load map: File -> Trust Notebook

Pueden encontrarse más fuentes de mapas XYZ en, por ejemplo:

Controles#

folium proporciona un conjunto de controles que le permiten al usuario interactuar con el mapa.

# Control de escala (argumento control_scale)
m = folium.Map(
    location=[10, -84], 
    width=650, height=400, 
    zoom_start=7, 
    control_scale=True)

m
Make this Notebook Trusted to load map: File -> Trust Notebook
# Control de capas (clase LayerControl)

# Creación de un mapa
m = folium.Map(
    location=[10, -84], 
    width=650, height=400, 
    zoom_start=7, 
    control_scale=True)

# Se añaden capas base adicionales
folium.TileLayer(
    tiles='CartoDB positron', 
    name='CartoDB positron').add_to(m)

folium.TileLayer(
    tiles='Stamen Terrain', 
    name='Stamen Terrain').add_to(m)


# ESRI NatGeo World Map
folium.TileLayer(
    tiles='http://services.arcgisonline.com/arcgis/rest/services/NatGeo_World_Map/MapServer/MapServer/tile/{z}/{y}/{x}',
    name='NatGeo World Map',
    attr='ESRI NatGeo World Map').add_to(m)

# Densidad de registros de presencia de especies
folium.TileLayer(
    tiles='https://api.gbif.org/v2/map/occurrence/density/{z}/{x}/{y}@1x.png?&bin=hex&hexPerTile=28&style=classic.poly',
    name='Densidad de registros de presencia de especies',
    attr='GBIF').add_to(m)

# Se añade un control de capas
folium.LayerControl().add_to(m)

m
Make this Notebook Trusted to load map: File -> Trust Notebook
# Grabación del mapa en el disco
m.save("/home/mfvargas/mapa-folium.html")

Mapas con múltiples capas#

# Mapa con capa base y capa vectorial

# Creación del mapa
m = folium.Map(location=[10, -84], tiles='CartoDB positron', zoom_start=7)

# Se añaden al mapa las capas GeoJson
folium.GeoJson(data="https://raw.githubusercontent.com/gf0657-programacionsig/2022-ii/main/contenido/4/datos/ign/red_vial.geojson", name='Red vial').add_to(m)

# Control de capas
folium.LayerControl().add_to(m)

# Despliegue del mapa
m
Make this Notebook Trusted to load map: File -> Trust Notebook

Mapeo de puntos de un archivo CSV#

import pandas as pd

# Lectura del archivo
felinos = pd.read_csv("https://raw.githubusercontent.com/gf0657-programacionsig/2022-ii/main/contenido/4/datos/gbif/felinos.csv", sep="\t")

felinos.head()
gbifID datasetKey occurrenceID kingdom phylum class order family genus species ... identifiedBy dateIdentified license rightsHolder recordedBy typeStatus establishmentMeans lastInterpreted mediaType issue
0 3925480525 50c9509d-22c7-4a22-a47d-8c48425ef4a7 https://www.inaturalist.org/observations/13825... Animalia Chordata Mammalia Carnivora Felidae Puma Puma concolor ... jstivelman 2022-10-10T13:29:08 CC_BY_NC_4_0 jstivelman jstivelman NaN NaN 2022-11-04T15:59:34.595Z StillImage COORDINATE_ROUNDED
1 3925334445 50c9509d-22c7-4a22-a47d-8c48425ef4a7 https://www.inaturalist.org/observations/13822... Animalia Chordata Mammalia Carnivora Felidae Panthera Panthera onca ... Nate Hartley 2022-10-10T06:25:40 CC_BY_NC_4_0 Nate Hartley Nate Hartley NaN NaN 2022-11-04T15:59:14.888Z StillImage COORDINATE_ROUNDED
2 3923678823 50c9509d-22c7-4a22-a47d-8c48425ef4a7 https://www.inaturalist.org/observations/13680... Animalia Chordata Mammalia Carnivora Felidae Panthera Panthera onca ... Michelle Monge-Velazquez 2022-09-28T14:11:46 CC_BY_4_0 Michelle Monge-Velazquez Michelle Monge-Velazquez NaN NaN 2022-11-04T16:02:44.606Z StillImage COORDINATE_ROUNDED
3 3915559071 50c9509d-22c7-4a22-a47d-8c48425ef4a7 https://www.inaturalist.org/observations/13645... Animalia Chordata Mammalia Carnivora Felidae Leopardus Leopardus tigrinus ... NaN NaN CC_BY_NC_4_0 Walter Bello Villalobos Walter Bello Villalobos NaN NaN 2022-11-04T15:59:10.275Z StillImage COORDINATE_ROUNDED
4 3915502418 50c9509d-22c7-4a22-a47d-8c48425ef4a7 https://www.inaturalist.org/observations/10796... Animalia Chordata Mammalia Carnivora Felidae Puma Puma yagouaroundi ... Osa Conservation 2022-03-05T17:52:45 CC_BY_NC_4_0 Osa Conservation Osa Conservation NaN NaN 2022-11-04T16:01:59.562Z StillImage COORDINATE_ROUNDED

5 rows × 50 columns

from folium import Marker

# Creación del mapa
m = folium.Map(location=[9.6, -84.2], tiles='CartoDB positron', zoom_start=8)

# Adición de marcadores
for idx, row in felinos.iterrows():
    Marker([row['decimalLatitude'], row['decimalLongitude']], popup=row['species']).add_to(m)

# Despliegue del mapa
m
Make this Notebook Trusted to load map: File -> Trust Notebook

Ejercicio: incluya en la ventana emergente (“popup”) de los puntos, la información relacionda con la localidad y la fecha.

Mapas de puntos agrupados (“cluster maps”)#

import math
from folium.plugins import MarkerCluster

# Creación del mapa base
m = folium.Map(location=[9.6, -84.2], tiles='CartoDB positron', zoom_start=8)

# Adición de puntos agrupados
mc = MarkerCluster()
for idx, row in felinos.iterrows():
    if not math.isnan(row['decimalLongitude']) and not math.isnan(row['decimalLatitude']):
        mc.add_child(Marker([row['decimalLatitude'], row['decimalLongitude']], popup=row['species']))
m.add_child(mc)

# Despliegue del mapa
m
Make this Notebook Trusted to load map: File -> Trust Notebook

Mapas de burbuja (“bubble maps”)#

from folium import Circle

# Creación del mapa base
m = folium.Map(location=[9.6, -84.2], tiles='CartoDB positron', zoom_start=8)

# Adición de las "burbujas"
for i in range(0,len(felinos)):
    Circle(
        location=[felinos.iloc[i]['decimalLatitude'], felinos.iloc[i]['decimalLongitude']],
        radius=1000,
        color="black", 
        popup=row['species']).add_to(m)

# Despliegue del mapa
m
Make this Notebook Trusted to load map: File -> Trust Notebook

El tamaño y el color de los puntos puede utilizarse para diferenciar algún atributo de los datos.

# Creación del mapa base
m = folium.Map(location=[9.6, -84.2], tiles='CartoDB positron', zoom_start=8)

def color_especie(especie):
    if especie == "Panthera onca":
        return 'orange'
    else:
        return 'black'

# Adición de las "burbujas"
for i in range(0,len(felinos)):
    Circle(
        location=[felinos.iloc[i]['decimalLatitude'], felinos.iloc[i]['decimalLongitude']],
        radius=1000,
        color=color_especie(felinos.iloc[i]['species']),
        popup=felinos.iloc[i]['species']).add_to(m)

# Despliegue del mapa
m
Make this Notebook Trusted to load map: File -> Trust Notebook

Ejercicio: Modifique la función color_especie() para que retorne un color diferente por cada especie de felino.

Mapas de calor (“heatmaps”)#

from folium.plugins import HeatMap


# Creación del mapa base
m = folium.Map(location=[9.6, -84.2], tiles='CartoDB positron', zoom_start=8)

# Mapa de color
HeatMap(data=felinos[['decimalLatitude', 'decimalLongitude']], radius=10).add_to(m)

# Despliegue del mapa
m
Make this Notebook Trusted to load map: File -> Trust Notebook

Mapas de coropletas (“choropleth maps”)#

# Cantidades de especies de murciélagos en ASP
especies_asp = pd.read_csv("https://raw.githubusercontent.com/pf3311-cienciadatosgeoespaciales/2021-iii/main/contenido/b/datos/asp-especies-murcielagos.csv")

especies_asp
id nombre_asp cantidad_especies lista_especies
0 areas_silvestres_protegidas.1 Montes Submarinos 0 NaN
1 areas_silvestres_protegidas.2 Cabo Blanco 0 NaN
2 areas_silvestres_protegidas.3 Alberto Manuel Brenes 0 NaN
3 areas_silvestres_protegidas.4 Isla Guayabo 0 NaN
4 areas_silvestres_protegidas.5 Isla Pajaros 0 NaN
... ... ... ... ...
167 areas_silvestres_protegidas.168 Quebrada Rosario 0 NaN
168 areas_silvestres_protegidas.169 Santa Rosa 0 NaN
169 areas_silvestres_protegidas.170 Bahia Junquillal 0 NaN
170 areas_silvestres_protegidas.171 Internacional La Amistad 11 Micronycteris megalotis, Hylonycteris underwoo...
171 areas_silvestres_protegidas.172 Bicentenario de la República - Pájaro Campana 0 NaN

172 rows × 4 columns

import geopandas as gpd

# ASP
asp = gpd.read_file("https://github.com/pf3311-cienciadatosgeoespaciales/2021-iii/raw/main/contenido/b/datos/asp.geojson")

asp
id codigo nombre_asp cat_manejo estatus siglas_cat nombre_ac siglas_ac descripcio a_creacion n_creacion normativa area area_km version geometry
0 areas_silvestres_protegidas.1 A01 Montes Submarinos Area Marina de Manejo Estatal AMM Marina Cocos ACMC Area Marina de Manejo 2011 DE_36452 None 9.592623e+09 9.592623e+07 2019-11-19-001 POLYGON ((-87.00000 6.13333, -86.43333 5.73333...
1 areas_silvestres_protegidas.2 A02 Cabo Blanco Area Marina de Manejo Estatal AMM Area de Conservacion Tempisque ACT Area Marina de Manejo 1963 Ley_10 None 8.247806e+08 8.247806e+06 2019-11-19-001 POLYGON ((-85.14336 9.59649, -85.14332 9.59643...
2 areas_silvestres_protegidas.3 B01 Alberto Manuel Brenes Reserva Biologica Estatal RB Area de Conservacion Central ACC Area terrestre protegida 1993 Ley_7354 None 7.800440e+07 7.800440e+05 2019-11-19-001 POLYGON ((-84.63388 10.18202, -84.64167 10.177...
3 areas_silvestres_protegidas.4 B03 Isla Guayabo Reserva Biologica Estatal RB Area de Conservacion Tempisque ACT Isla 1973 DE_2858_A None 6.268092e+04 6.268092e+02 2019-11-19-001 POLYGON ((-84.87710 9.91109, -84.87737 9.91086...
4 areas_silvestres_protegidas.5 B04 Isla Pajaros Reserva Biologica Estatal RB Area de Conservacion Pacifico Central ACOPAC Isla 1976 DE_ 5963_A None 3.211583e+04 3.211583e+02 2019-11-19-001 POLYGON ((-84.99674 10.09266, -84.99696 10.092...
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
167 areas_silvestres_protegidas.168 Z31 Quebrada Rosario Zona Protectora Estatal ZP Area de Conservacion Central ACC Area terrestre protegida 1997 DE_ 26297_MINAE None 4.292695e+05 4.292695e+03 2019-11-19-001 POLYGON ((-84.07619 9.70425, -84.07689 9.70374...
168 areas_silvestres_protegidas.169 P10 Santa Rosa Parque Nacional Estatal PN Area de Conservacion Guanacaste ACG Isla 1966 Ley_3694 None 3.230258e+06 3.230258e+04 2019-11-19-001 MULTIPOLYGON (((-85.87565 10.84304, -85.87571 ...
169 areas_silvestres_protegidas.170 V25 Bahia Junquillal Refugio Nacional de Vida Silvestre Estatal RVS Area de Conservacion Guanacaste ACG Isla 1995 DE_ 23867_MIRENEM None 1.836792e+05 1.836792e+03 2021-08-20-001 MULTIPOLYGON (((-85.73360 10.95775, -85.73329 ...
170 areas_silvestres_protegidas.171 P18 Internacional La Amistad Parque Nacional Estatal PN Area de Conservacion La Amistad Pacifico ACLAP Area terrestre protegida 1982 DE_13324_A None 1.982896e+09 1.982896e+07 2019-11-19-001 MULTIPOLYGON (((-82.85282 9.01273, -82.85414 9...
171 areas_silvestres_protegidas.172 B09 Bicentenario de la República - Pájaro Campana Reserva Biologica Estatal RB Area de Conservacion La Amistad Pacifico ACLAP Area terrestre protegida 2021 DE_42615_MINAE None 5.082743e+07 5.082743e+05 2021-08-21-001 POLYGON ((-82.77351 8.94507, -82.81050 8.95856...

172 rows × 16 columns

# Creación del mapa base
m = folium.Map(location=[9.8, -84], tiles='CartoDB positron', zoom_start=8)

folium.Choropleth(
    geo_data=asp,
    data=especies_asp,
    columns=['id', 'cantidad_especies'],
    bins=8,
    key_on='feature.properties.id',
    fill_color='Reds', 
    fill_opacity=0.5, 
    line_opacity=1,
    legend_name='Cantidad de especies de murciélagos',
    smooth_factor=0).add_to(m)

# Despliegue del mapa
m
Make this Notebook Trusted to load map: File -> Trust Notebook