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.

Instalación

folium puede instalarse tanto mediante Conda como mediante pip.

# Instalación mediante Conda
conda install -c conda-forge folium

# Instalación mediante pip
pip install folium

Carga

import folium

# Versión
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)
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
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 (zoom)
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

Por defecto, Folium utiliza OpenStreetMap como mapa base. Pueden elegirse otros mapas base mediante el parámetro 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

El siguiente es un ejemplo que utiliza la opción como mapa 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

Controles

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

# Control de escala
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

# 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://github.com/pf3311-cienciadatosgeoespaciales/2021-iii/raw/main/contenido/b/datos/redvial.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/pf3311-cienciadatosgeoespaciales/2021-iii/main/contenido/b/datos/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 3337559907 50c9509d-22c7-4a22-a47d-8c48425ef4a7 https://www.inaturalist.org/observations/90794984 Animalia Chordata Mammalia Carnivora Felidae Puma Puma concolor ... Marvin López M. 2021-08-11T17:02:57 CC_BY_NC_4_0 Marvin López M. Marvin López M. NaN NaN 2021-09-23T21:26:16.096Z StillImage COORDINATE_ROUNDED
1 3333401669 50c9509d-22c7-4a22-a47d-8c48425ef4a7 https://www.inaturalist.org/observations/88270427 Animalia Chordata Mammalia Carnivora Felidae Puma Puma concolor ... Tiziano Luka Pesci Rubilar 2021-07-23T17:52:04 CC_BY_NC_4_0 Rebeca Quirós Rebeca Quirós NaN NaN 2021-09-23T21:15:51.507Z NaN COORDINATE_ROUNDED
2 3325502794 50c9509d-22c7-4a22-a47d-8c48425ef4a7 https://www.inaturalist.org/observations/85490861 Animalia Chordata Mammalia Carnivora Felidae Leopardus Leopardus pardalis ... Sofía Pastor Parajeles 2021-07-03T16:59:46 CC_BY_NC_4_0 Sofía Pastor Parajeles Sofía Pastor Parajeles NaN NaN 2021-09-23T20:59:21.345Z StillImage COORDINATE_ROUNDED
3 3314547422 50c9509d-22c7-4a22-a47d-8c48425ef4a7 https://www.inaturalist.org/observations/84224884 Animalia Chordata Mammalia Carnivora Felidae Leopardus Leopardus pardalis ... Sofía Pastor Parajeles 2021-06-23T20:39:47 CC_BY_NC_4_0 Sofía Pastor Parajeles Sofía Pastor Parajeles NaN NaN 2021-09-23T21:25:26.648Z StillImage NaN
4 3307298689 50c9509d-22c7-4a22-a47d-8c48425ef4a7 https://www.inaturalist.org/observations/82810053 Animalia Chordata Mammalia Carnivora Felidae Leopardus Leopardus wiedii ... David 2021-06-13T09:10:50 CC_BY_NC_4_0 David David NaN NaN 2021-09-23T21:25:57.478Z 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

# UGM de San Carlos
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