# Instálalo en el caso de que no lo tengas aún
install.packages("leaflet")
4 - Mapas interactivos con leaflet
¿Qué vamos a hacer?
Durante el capítulo anterior vimos una introducción a los gráficos de mapas con ggplot2. En este, profundizaremos en la visualización de datos geoespaciales, y utilizaremos una herramienta especializada en ello: leaflet
.
leaflet
es una librería de visualización de mapas creada originalmente para javascript, pero existe una librería en R para poder crear mapas directamente desde este lenguaje.
Los objetivos de esta sesión son:
- Entender los conceptos básicos de los datos geoespaciales.
- Interactuar con mapas con tiles (imágenes de fondo) y geometrías (puntos, polígonos, …).
- Representar gráficamente datos geoespaciales.
¿Gráficos estáticos o interactivos?
Además, leaflet
es la primera herramienta de varias que veremos en esta asignatura que crea gráficos interactivos. Por el contrario, ggplot
crea gráficos estáticos. Los pros, contras, y algunos ejemplos de herramientas de ambos casos son:
Gráficos estáticos:
Pros:
- Más sencillo de utilizar
- Más exportable: al producir imágenes, se pueden incrustar en cualquier tipo de documento, como PDF, Word, HTML, …
- Auto-contenidos, no necesitan dependencias externas para ser visualizados.
Contras:
- Menos ricos, no hay interacción
Ejemplos de herramientas
- ggplot, rmarkdown (exportando a PDF, Word, …).
Gráficos interactivos:
Pros:
- La interactividad permite ampliar información a demanda en un solo gráfico (suelen permitir hacer zoom, sacar tooltips que muestran más datos, etc.).
Contras:
- Solo son exportables a HTML.
- Suelen necesitar dependencias externas para visualizarse: ciertas librerías de javascript externas, recursos CSS. En general, deben visualizarse dentro de un navegador web.
Ejemplos de herramientas
- rmarkdown (exportando a HTML), leaflet, plotly, flexdashboard, shiny.
La elección de crear gráficos estáticos o interactivos depende del caso de uso ante el que nos encontremos. Si estamos haciendo un análisis exploratorio de un dataset, casi siempre nos valdrá con gráficos estáticos. También para realizar informes que deben compartirse por PDF. En cambio, si estamos diseñando un cuadro de mando completo, en un entorno donde los usuarios están acostumbrados a utilizar un explorador web, utilizaremos gráficos interactivos.
1. Introducción a los datos geoespaciales
Sistemas de referencia espaciales
Los sistemas de referencia espaciales sirven para establecer una referencia a la hora de definir la localización de objetos y la relación entre estos.
Existen dos categorías de SREs:
- Geográficos: usan coordenadas esféricas
- Proyectados: usan coordenadas en un plano
A la hora de almacenar información geográfica en la base de datos, debemos especificar las coordenadas y el sistema de referencia. En general, utilizaremos uno de los más comunes: WGS-84 (EPSG:4326). Sobre este sistema:
- Es geográfico (no proyectado)
- Usa longitud, latitud
Objetos espaciales
Vamos a trabajar con los siguientes tipos de objetos:
- Puntos
- Líneas
- Polígonos
- Multi-polígonos
2. Mapas base y controles
Para poder lanzar los ejemplos, necesitarás tener instalada la librería leaflet
.
Vamos a pintar un primer mapa.
library(leaflet)
library(dplyr)
# leaflet() inicializa un mapa con controles, pero vacío
# addTiles() proporciona las imágenes de fondo
leaflet() %>%
addTiles()
Fíjate en cómo puedes interactuar con el mapa: utiliza el zoom, desplázate por diferentes regiones y fíjate cómo se van actualizando solas las imágenes de fondo (los tiles).
Es habitual centrar el mapa en un punto y darle un zoom adecuado dependiendo de lo que queramos visualizar. Lo podemos hacer con setView
. Consulta la documentación de esta función para conocer todas las opciones.
leaflet() %>%
addTiles() %>%
setView(lng = -3.69, lat = 40.43, zoom = 12)
Podemos personalizar las imágenes de fondo ajustando las tiles utilizando addProviderTiles
en lugar de addTiles
. Algunas opciones:
CartoDB.Positron
: muy limpios y claros, útiles para poner marcadores o colorear zonas.CartoDB.PositronNoLabels
: como la anterior, pero eliminando las etiqutas.CartoDB.DarkMatter
yCartoDB.DarkMatterNoLabels
: la versión dark de las anteriores, más adecuado si se integra en un cuadro de mando con un estilo oscuro generalizado.Stamen.Terrain
: con más descripción del terreneo, útil para zonas rurales o de montaña.
Puedes consultar la lista completa aquí.
leaflet() %>%
addProviderTiles("Stamen.Terrain") %>%
setView(lng = -3.69, lat = 40.43, zoom = 12)
Visita la lista completa y prueba más opciones sobre el mapa.
3. Marcadores
Los marcadores son los puntos que ponemos sobre el mapa, expresados como una latitud y longitud, y que solemos representar con forma de pins o círculos.
La fuente de datos puede ser variada:
- Un dataframe geolocalizado, como los que devuelve
sf::read_sf
. - Matrices numéricas de dos columnas (longitud, latitud).
- Un dataframe con columnas de latitud y longitud.
- Vectores independientes de lat / lon.
Podemos añadir uno o varios marcadores con addMarkers
.
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
setView(lng = -3.69, lat = 40.43, zoom = 12) %>%
addMarkers(lng = -3.6845, lat = 40.4158, label = "Parque El Retiro")
Pasa el ratón por encima del punto para comprobar que sale el nombre del marcador. El evento de mostrar algo mientras se pasa el ratón por encima se denomina
hover
.
Al igual que con ggplot, con leaflet vamos definiendo las diferentes capas y opciones de nuestro mapa. Ten cuidado y no te confundas, que con ggplot las capas se añadían con
+
y en leaflet es con%>%
.
También podemos añadir marcadores desde un dataframe. Ya sabíamos leer geojson con sf::read_sf
.
library(sf)
# Leemos el geojson con las líneas de metro
<- read_sf("dat/paradas_metro_madrid.geojson")
paradas_metro head(paradas_metro)
Simple feature collection with 6 features and 7 fields
Geometry type: POINT
Dimension: XY
Bounding box: xmin: -3.704666 ymin: 40.39819 xmax: -3.666807 ymax: 40.48013
Geodetic CRS: WGS 84
# A tibble: 6 × 8
cartodb_id place id name line lat lng geometry
<int> <int> <int> <chr> <chr> <dbl> <dbl> <POINT [°]>
1 1 1 1 Pinar de C… L1 40.5 -3.67 (-3.666807 40.48013)
2 2 2 2 Bambú L1 40.5 -3.68 (-3.676377 40.47681)
3 6 6 6 Tetuán L1 40.5 -3.70 (-3.698258 40.46055)
4 9 9 9 Cuatro Cam… L1 40.4 -3.70 (-3.703978 40.44697)
5 16 16 16 Tirso de M… L1 40.4 -3.70 (-3.704666 40.41234)
6 22 22 22 Puente de … L1 40.4 -3.67 (-3.669062 40.39819)
# Nos quedamos con una sola línea, por ejemplo, la circular (L6)
<- paradas_metro %>%
paradas_circular filter(line == "L6")
nrow(paradas_circular)
[1] 28
Para mapear los marcadores de un dataframe, pasamos este como argumento de leaflet()
. Y luego mapeamos los atributos de los marcadores (posición y etiqueta) a columnas del dataframe. Estas columnas van siempre precedidas del símbolo ~
. Esto es muy parecido a lo que hacíamos en ggplot
mediante el uso de aes(...)
.
leaflet(data = paradas_circular) %>%
addProviderTiles("CartoDB.Positron") %>%
setView(lng = -3.69, lat = 40.43, zoom = 12) %>%
addMarkers(lng = ~lng, lat = ~lat, label = ~name)
También podemos utilizar marcadores circulares, que suelen ser más fácilmente personalizables (tamaño, color, opacidad, borde, …):
leaflet(data = paradas_circular) %>%
addProviderTiles("CartoDB.Positron") %>%
setView(lng = -3.69, lat = 40.43, zoom = 12) %>%
addCircleMarkers(lng = ~lng, lat = ~lat, label = ~name)
Consulta la documentación de ?addCircleMarkers
para ver todas las opciones. Un ejemplo con personalización:
leaflet(data = paradas_circular) %>%
addProviderTiles("CartoDB.Positron") %>%
setView(lng = -3.69, lat = 40.43, zoom = 12) %>%
addCircleMarkers(lng = ~lng, lat = ~lat, label = ~name,
radius = 8,
color = "gray",
stroke = FALSE,
fillOpacity = 0.5
)
4. Líneas y polígonos
De forma parecida a como añadimos marcadores, podemos también representar líneas y polígonos en los mapas de leaflet
.
# Leemos el geojson con la definición de las líneas de metro
<- read_sf("dat/lineas_metro.geojson")
lineas_metro head(lineas_metro)
Simple feature collection with 6 features and 5 fields
Geometry type: LINESTRING
Dimension: XY
Bounding box: xmin: -3.7687 ymin: 40.3398 xmax: -3.5873 ymax: 40.4804
Geodetic CRS: WGS 84
# A tibble: 6 × 6
OBJECTID Texto Linea Fecha Fuente geometry
<chr> <chr> <chr> <chr> <chr> <LINESTRING [°]>
1 1 L1: Pinar de Chamartín … L1 mar_… Conso… (-3.5916 40.3598, -3.591…
2 2 L2: La Elipa - Cuatro C… L2 mar_… Conso… (-3.601 40.4228, -3.601 …
3 3 L3: Villaverde Alto - M… L3 mar_… Conso… (-3.7135 40.3412, -3.713…
4 4 L4: Argüelles - Pinar d… L4 mar_… Conso… (-3.7164 40.4309, -3.716…
5 5 L5: Alameda de Osuna - … L5 mar_… Conso… (-3.7617 40.403, -3.763 …
6 6 L6: Circular L6 mar_… Conso… (-3.7271 40.4138, -3.728…
Y las podemos representar con addPolylines
.
leaflet(data = lineas_metro) %>%
addProviderTiles("CartoDB.Positron") %>%
setView(lng = -3.69, lat = 40.43, zoom = 12) %>%
addPolylines(label = ~Texto)
Igual que hemos hecho con líneas, podemos hacerlo con polígonos:
# Leemos el geojson con los barrios de Madrid
<- read_sf("dat/neighbourhoods.geojson")
barrios head(barrios)
Simple feature collection with 6 features and 2 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -3.722863 ymin: 40.40507 xmax: -3.690364 ymax: 40.43066
Geodetic CRS: WGS 84
# A tibble: 6 × 3
neighbourhood neighbourhood_group geometry
<chr> <chr> <MULTIPOLYGON [°]>
1 Palacio Centro (((-3.70584 40.4203, -3.706248 40.42018, -3…
2 Embajadores Centro (((-3.703837 40.41432, -3.70277 40.41392, -…
3 Cortes Centro (((-3.697959 40.41929, -3.696453 40.41875, …
4 Justicia Centro (((-3.695463 40.41898, -3.696453 40.41875, …
5 Universidad Centro (((-3.701075 40.42134, -3.701547 40.42011, …
6 Sol Centro (((-3.704747 40.42027, -3.701501 40.42002, …
leaflet(data = barrios) %>%
addProviderTiles("CartoDB.Positron") %>%
setView(lng = -3.69, lat = 40.43, zoom = 12) %>%
addPolygons(label = ~neighbourhood)
3. Coropletas
Colores
Los mapas de coropletas (choropleths) son mapas con regiones coloreadas en base al atributo que queremos representar. Ya sabemos cómo dibujar esas regiones, así que nos vamos a centrar ahora en cómo rellenarlas de color.
Recordarás que con ggplot
era muy fácil mapear columnas a colores. Cuando lo hacíamos con columnas continuas, ggplot utilizaba por defecto una escala secuencial; y cuando lo hacíamos con columnas categóricas, utilizaba una escala cualitativa (discreta).
Con leaflet
no es tan autómatico: necesitamos definir la escala y cómo se mapean los valores a ella.
Escalas secuenciales
Para aquellas columnas que sean continuas, tenemos dos opciones:
- Utilizar una escala continua, es decir, un gradiente de colores, con
colorNumeric
- Discretizar ese gradiente en N colores, mediante
colorBin
ocolorQuantile
.
Consulta la documentación de las tres funciones.
Podemos probar con los datos de las elecciones de 2019 en España.
# Leemos los polígonos de un geojson que contiene las provincias españolas simplificadas
<- read_sf("dat/spain_provinces.geojson")
provincias
# Leemos elecciones_2019_votos.csv con el número de votos por provincia y partido
<- read.csv("dat/elecciones_2019_provincias.csv")
elecciones
# Calculamos el ratio de participación
<- elecciones %>%
participacion mutate(ratio_participacion = round((votos_validos + votos_nulos) / censo_electoral, 3)) %>%
select(ccaa_nombre, provincia_cod_ine, ratio_participacion)
# Añadimos al mapa el ratio de participación
<- provincias %>%
tmp inner_join(participacion, by = c("codigo" = "provincia_cod_ine"))
head(tmp)
Simple feature collection with 6 features and 5 fields
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: -1.8386 ymin: 3.6739 xmax: 0.7771 ymax: 4.2623
Geodetic CRS: WGS 84
# A tibble: 6 × 6
OBJECTID codigo nombre geometry ccaa_…¹ ratio…²
<int> <int> <chr> <POLYGON [°]> <chr> <dbl>
1 1 20 Guipúzcoa ((0.3515 4.0509, 0.2355 4.1197, 0.… País V… 0.658
2 2 15 Coruña (A) ((-1.601 3.7516, -1.6469 3.7784, -… Galicia 0.57
3 3 48 Vizcaya ((0.053 4.0646, -0.01 4.1035, -0.0… País V… 0.668
4 4 31 Navarra ((0.6115 3.6739, 0.5459 3.7058, 0.… Comuni… 0.659
5 5 39 Cantabria ((-0.1907 3.9288, -0.3244 4.0103, … Cantab… 0.657
6 6 33 Asturias ((-1.0583 3.8709, -1.0583 3.9308, … Princi… 0.581
# … with abbreviated variable names ¹ccaa_nombre, ²ratio_participacion
Los datos de participación son numéricos, por lo que su escala será secuencial.
Primero, veamos cómo lo mapearíamos a una escala continua con colorNumeric
.
# Blues es el nombre de la paleta en colorbrewer2 (https://colorbrewer2.org/)
<- colorNumeric(
pal_numeric palette = "Blues",
domain = tmp$ratio_participacion
)
Prueba a cambiar la paleta de colores por otra de tu elección
# Aquí no tiene sentido centrar la vista en una latitud longitud real
# ni poner los tiles de fondo porque nuestro geojson está simplificado
# y no está situado en las coordenadas "reales"
<- leaflet(data = tmp) %>%
map_numeric addPolygons(color = ~pal_numeric(ratio_participacion),
label = ~nombre,
stroke = FALSE,
fillOpacity = 1
)
map_numeric
Las provincias pueden tomar cualquier valor entre el mínimo (blanco) y el máximo (azul muy intenso), correspondiente con su nivel de participación.
La alternativa sería utilizar una escala discretizada. Con colorBin
dividiremos el espectro de posibles colores en el número de bins que decidamos.
<- colorBin(
pal_bin palette = "Blues",
domain = tmp$ratio_participacion,
bins = 4
)
<- leaflet(data = tmp) %>%
map_bin addPolygons(color = ~pal_bin(ratio_participacion),
label = ~nombre,
stroke = FALSE,
fillOpacity = 1
)
map_bin
Y colorQuantile
es similar a colorBin
, pero utiliza cuantiles para hacer los cortes.
<- colorQuantile(
pal_quantile palette = "Blues",
domain = tmp$ratio_participacion,
n = 4
)
<- leaflet(data = tmp) %>%
map_quantile addPolygons(color = ~pal_quantile(ratio_participacion),
label = ~nombre,
stroke = FALSE,
fillOpacity = 1
)
map_quantile
Fíjate en cómo cambia de colorBin a colorQuantile. El corte mediante bins, por defecto, corta el rango de colores en trozos de igual longitud. En cambio, por cuantiles (como hemos dicho 4, será por cuartiles), corta el rango para que haya el mismo número de observaciones en cada trozo (con la excepción de que tuviéramos valores repetidos, que provocaría trozos con más o menos observaciones).
Escalas cualitativas
Para crear escalas cualitativas (discretas), utilizamos colorFactor
.
Vamos a ilustrarlo con un ejemplo muy simple, coloreando las provincias por comunidad autónoma.
<- colorFactor(
pal_factor palette = "Set1",
domain = tmp$ccaa_nombre
)
<- leaflet(data = tmp) %>%
map_factor addPolygons(color = ~pal_factor(ccaa_nombre),
label = ~nombre,
stroke = FALSE,
fillOpacity = 1
)
map_factor
4. Leyendas y capas
Leyendas
Mirando los mapas de coropletas que acabamos de generar, hay una cosa que automáticamente echamos en falta: leyendas. Son necesarias para entender el mapeo de colores.
Las leyendas las podemos añadir utilizando addLegend
y ajustando sus parámetros según nuestra necesidad.
# Consulta la documentación sobre los parámetros que estamos ajustando aquí
%>%
map_numeric addLegend(
position = "bottomright",
pal = pal_numeric,
values = ~ratio_participacion,
title = "Ratio de participación"
)
Podemos sobrescribir el aspecto de los valores de la leyenda con labFormat
.
%>%
map_bin addLegend(
position = "bottomright",
pal = pal_bin,
values = ~ratio_participacion,
title = "Ratio de participación",
labFormat = labelFormat(suffix = "%", transform = function(x) 100 * x),
)
Nota: haz lo mismo con map_quantile (quitando el parámetro labFormat), la escala que hemos discretizado por cuantiles. Fíjate en cómo queda la leyenda. Los porcentajes indican dónde cae el 25% de los valores más bajos, el 25% siguiente, … y así. En este caso, como la participación es un ratio, puede ser muy confuso mostrar esa leyenda a los usuarios: podrían pensar que hay regiones con una participación de menos del 25%.
Capas
Cada addMarkers
, addPolygons
, … que utilizamos añade una capa sobre nuestro mapa. Podemos añadir controles para superponerlas o elegir mostrar solo una de las activas.
Por ejemplo, podemos ver el ratio de votos a una serie de partidos.
# Leemos los datos de votos
<- read.csv("dat/elecciones_2019_votos.csv")
votos
# Nos quedamos solo con algunos partidos y calculamos el % de voto
# TODO: si te interesa, puedes juntar coaliciones (p.e. contar
# los votos de encomupodem como podemos)
<- votos %>%
votos_partidos filter(partido %in% c("psoe", "pp", "vox", "podemos")) %>%
inner_join(elecciones) %>%
mutate(ratio_votos = round(votos / votos_validos, 3)) %>%
select(provincia_cod_ine, partido, ratio_votos)
head(votos_partidos)
provincia_cod_ine partido ratio_votos
1 4 psoe 0.295
2 11 psoe 0.306
3 14 psoe 0.330
4 18 psoe 0.332
5 21 psoe 0.366
6 23 psoe 0.388
# La función pivot_wider pertenece al paquete tidyr
# Si lo lo tienes instalado, hazlo
install.packages("tidyr")
library(tidyr)
# Los pasamos a formato ancho para tener una fila por provincia y
# una columna con el ratio de votos por cada partido, y mapearlas
# en capas diferentes
<- votos_partidos %>%
votos_partidos_ancho pivot_wider(names_from = partido, values_from = ratio_votos)
# Lo incorporamos al objeto con la información de los polígonos
# Cuidado: si hacemos el join al revés (left = votos y right = provincias)
# perdemos el tipo de dato de objeto espacial y luego leaflet no sabe
# pintarlo
<- provincias %>%
mapa_votos inner_join(votos_partidos_ancho, by = c("codigo" = "provincia_cod_ine"))
head(mapa_votos)
Simple feature collection with 6 features and 7 fields
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: -1.8386 ymin: 3.6739 xmax: 0.7771 ymax: 4.2623
Geodetic CRS: WGS 84
# A tibble: 6 × 8
OBJECTID codigo nombre geometry psoe pp vox podemos
<int> <int> <chr> <POLYGON [°]> <dbl> <dbl> <dbl> <dbl>
1 1 20 Guipúzcoa ((0.3515 4.0509, 0.2355 … 0.181 0.062 0.019 0.15
2 2 15 Coruña (… ((-1.601 3.7516, -1.6469… 0.3 0.305 0.082 NA
3 3 48 Vizcaya ((0.053 4.0646, -0.01 4.… 0.191 0.088 0.024 0.154
4 4 31 Navarra ((0.6115 3.6739, 0.5459 … 0.25 NA 0.058 0.166
5 5 39 Cantabria ((-0.1907 3.9288, -0.324… 0.232 0.259 0.149 0.087
6 6 33 Asturias ((-1.0583 3.8709, -1.058… 0.333 0.232 0.159 0.16
Ahora que ya tenemos el dataset preparado, podemos representarlo. Con el parámetro group
de cada capa y addLayersControl
añadimos el control para elegir qué capa mostrar. Consulta la documentación de esta función para ver todas las posibilidades.
# Creo una paleta por partido
<- colorBin(
pal_votos_psoe palette = "Reds",
domain = mapa_votos$psoe,
bins = 5
)
<- colorBin(
pal_votos_pp palette = "Blues",
domain = mapa_votos$pp,
bins = 5
)
<- colorBin(
pal_votos_vox palette = "Greens",
domain = mapa_votos$vox,
bins = 5
)
<- colorBin(
pal_votos_podemos palette = "Purples",
domain = mapa_votos$vox,
bins = 5
)
# Pinto el mapa, con una capa por ratio de votos a ese partido
leaflet(data = mapa_votos) %>%
# Capa del PSOE
addPolygons(color = ~pal_votos_psoe(psoe),
label = ~nombre,
stroke = FALSE,
fillOpacity = 1,
group = "PSOE"
%>%
) # Capa del PP
addPolygons(color = ~pal_votos_pp(pp),
label = ~nombre,
stroke = FALSE,
fillOpacity = 1,
group = "PP"
%>%
) # Capa de VOX
addPolygons(color = ~pal_votos_vox(vox),
label = ~nombre,
stroke = FALSE,
fillOpacity = 1,
group = "VOX"
%>%
) # Capa de Podemos
addPolygons(color = ~pal_votos_podemos(podemos),
label = ~nombre,
stroke = FALSE,
fillOpacity = 1,
group = "Podemos"
%>%
) # Control de capas
addLayersControl(
baseGroups = c("PSOE", "PP", "VOX", "Podemos"),
options = layersControlOptions(collapsed = FALSE)
)
En casos como este tenemos bastante información por región: de cada provincia, tenemos el % de voto a 4 partidos diferentes. Es útil que añadamos un resumen de esta información al tooltip o popup.
La diferencia entre tooltip y popup es que el primero se muestra al pasar por encima y no admite texto formateado con HTML, y el segundo se muestra al hacer click y sí permite HTML.
Vamos a ver un caso con popups y texto formateado con HTML:
# Queremos que al hacer click, salga el nombre de la provincia y
# el % de voto a cada uno de los partidos. Las etiquetas html que usamos, sirven para:
# - strong: poner en negrita
# - br: salto de línea
# - ul: lista de elementos
# - li: cada uno de los elementos de ul
<- mapa_votos %>%
mapa_votos mutate(
# Reemplazo los NAs por 0
# Son casos en los que estos partidos fueron en coalición
psoe = replace_na(psoe, 0),
pp = replace_na(pp, 0),
vox = replace_na(vox, 0),
podemos = replace_na(podemos, 0),
# Creamos el popup
popup = paste0("<strong>", nombre, "</strong><br/><ul>",
"<li>PSOE: ", psoe * 100, "%</li>",
"<li>PP: ", pp * 100, "%</li>",
"<li>VOX: ", vox * 100, "%</li>",
"<li>Podemos: ", podemos * 100, "%</li></ul>")
)
head(mapa_votos)
Simple feature collection with 6 features and 8 fields
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: -1.8386 ymin: 3.6739 xmax: 0.7771 ymax: 4.2623
Geodetic CRS: WGS 84
# A tibble: 6 × 9
OBJECTID codigo nombre geometry psoe pp vox podemos
<int> <int> <chr> <POLYGON [°]> <dbl> <dbl> <dbl> <dbl>
1 1 20 Guipúzcoa ((0.3515 4.0509, 0.2355 … 0.181 0.062 0.019 0.15
2 2 15 Coruña (A) ((-1.601 3.7516, -1.6469… 0.3 0.305 0.082 0
3 3 48 Vizcaya ((0.053 4.0646, -0.01 4.… 0.191 0.088 0.024 0.154
4 4 31 Navarra ((0.6115 3.6739, 0.5459 … 0.25 0 0.058 0.166
5 5 39 Cantabria ((-0.1907 3.9288, -0.324… 0.232 0.259 0.149 0.087
6 6 33 Asturias ((-1.0583 3.8709, -1.058… 0.333 0.232 0.159 0.16
# … with 1 more variable: popup <chr>
Ahora puedo añadir el popup a cada una de las capas.
# Pinto el mapa, con una capa por ratio de votos a ese partido
leaflet(data = mapa_votos) %>%
# Capa del PSOE
addPolygons(color = ~pal_votos_psoe(psoe),
popup = ~popup,
stroke = FALSE,
fillOpacity = 1,
group = "PSOE"
%>%
) # Capa del PP
addPolygons(color = ~pal_votos_pp(pp),
popup = ~popup,
stroke = FALSE,
fillOpacity = 1,
group = "PP"
%>%
) # Capa de VOX
addPolygons(color = ~pal_votos_vox(vox),
popup = ~popup,
stroke = FALSE,
fillOpacity = 1,
group = "VOX"
%>%
) # Capa de Podemos
addPolygons(color = ~pal_votos_podemos(podemos),
popup = ~popup,
stroke = FALSE,
fillOpacity = 1,
group = "Podemos"
%>%
) # Control de capas
addLayersControl(
baseGroups = c("PSOE", "PP", "VOX", "Podemos"),
options = layersControlOptions(collapsed = FALSE)
)
Si haces click sobre una de las provincias, deberías ver un popup como este:
Profundiza
Para saber más sobre los conceptos que hemos visto, puedes consultar alguna de estas referencias:
- Documentación web de leaflet: imprescindible, profundiza sobre todas las posibilidades que tiene la librería, ilustrado con ejemplos.
- Chuleta de leaflet: sintetiza las funciones más habituales para leaflet Muy útil para tener a mano a la hora de utilizar la librería.
- Tiles de leaflet: detalla cómo utilizar los tiles, cómo funcionar algunos de ellos y un listado con todos los disponibles.
Conclusiones
Nos podemos quedar con las siguientes ideas como resumen de este tema:
- Las herramientas de gráficos interactivas nos dan más posibilidades para comunicar información, con elementos donde hacer zoom, clickar para ampliar información, intercambiar capas, etc.
- Leaflet es la herramienta interactiva de visualización de mapas por excelencia.
- Los tiles son las imágenes de fondo del mapa y son personalizables dependiendo de si queremos destacar las calles, el terreno u otros elementos geográficos.
- Podemos representar marcadores, líneas y polígonos como capas de leaflet
- Para mapear propiedades del mapa a columnas del dataframe, utilizamos el prefijo
~mi_columna
.
Actividades
Actividad 1
Pinta el metro de Madrid, con:
- Las paradas
- Las líneas de metro, cada una con un color diferente.
Nota: No vale crear una capa por línea diferente de metro, todas las líneas deben ir en la misma.
Bonus: personaliza los colores con el suyo oficial (línea 2 en rojo, línea 7 en naranja, …)
Actividad 2
Reproduce un mapa con el % de voto a cada uno de los 4 principales partidos por Comunidad Autónoma, en lugar de por provincia.
Necesitarás, además de los datos que ya hemos ido usando en este capítulo, los siguientes:
dat/provincias_ccaas.csv
: con el detalle de qué provincia pertenece a cada comunidad autónoma (mediante sus códigos INE).dat/spain_ccaas.geojson
: con el geojson de las comunidades autónomas simplificado
Actividad 3
Lee dat/listings.csv
. Contiene un listado de alojamientos anunciados en AirBnB en Madrid.
Coge aleatoriamente una muestra de 500 alojamientos y píntalos sobre un mapa de Madrid. Cada marcador debe tener un color diferente dependiendiendo del tipo (room_type
).
Actividad 4 (bonus)
Los datos sobre los alojamientos de AirBnB están descargados de aquí. Cada ciudad, tiene:
listings.csv
: con un resumen de los datos más relevantes por cada alojamiento.neighbourhoods.geojson
: con el geojson de los barrios.
Y además, un panel donde se visualizan alguno de esos datos en un mapa (de leaflet!) y gráficas e indicadores a la derecha. P.e. este es el de Madrid.
Reproduce con leaflet (mapas) y ggplot (gráficas) los gráficos que se pintan en el panel, sobre una ciudad de tu elección.