Preparativos previos

Mapdeck (el paquete de R) requiere un “token” de acceso a la API de Mapbox (el servicio de mapas online). Para obtener un token, basta con darse de alta en Mapbox, y seguir las instrucciones en https://www.mapbox.com/help/how-access-tokens-work/#creating-and-managing-access-tokens

Activamos Mapdeck junto a otras librerías que vamos a usar

library(mapdeck)
library(tidyverse)
library(sf)

Y le decimos a Mapdeck cual es nuestro token de acceso a los mapas de Mapbox.

mi_token <- 'blahblahblahsasdasdasdasdasdas'    ## ponga su propio token aquí
set_token(token = mi_token)

Por último, definimos el mapa base que vamos a usar.

Mapbox ofrece muchos para elegir, e incluso un editor para crear un estilo propio:

Por el momento, podemos elegir alguno de los predefinidos: “dark”, “light”, “outdoors”, “streets”, “satellite”, o “satellite-streets”.

Testeamos algunas:

mapdeck(style = mapdeck_style("dark"))
mapdeck(style = mapdeck_style("light"))
mapdeck(style = mapdeck_style("streets"))

El estilo “dark” es una buena opción como mapa base de visualizaciones, ya que el fondo oscuro resaltará los colores de los datos que proyectemos por encima.

También podemos controlar el nivel de zoom inicial, con zoom; y el ángulo de inclinación con pitch. Por ejemplo:

mapdeck(style = mapdeck_style("dark"), 
        #location = c(lon, lat) <<<< primero longitud, despues latitud
        location = c(-58.38, -34.6), 
        zoom = 11,
        pitch = 45)

Visualizando por capas

Con los pasos previos resueltos, podemos cargar nuestros datos y visualizarlos mediante distintas capas. Por el momento, Mapdeck permite utilizar las siguientes:

Tanto Mapdeck como deck.gl (la librería de javascript que provee las funciones de visualización) están en continuo desarrollo, por lo que es probable que aparezcan nuevas capas disponibles con frecuencia.

Los datos de origen pueden ser dataframes tradicionales (con info de latitud y longitud en sendas columnas), o archivos espaciales, leídos vía sf.

Líneas

viajes_taxi <- read.csv("https://query.data.world/s/5s2wwvtmse2y2s66jpkxblurzumpnr",
                        dec = ",", 
                        stringsAsFactors = FALSE)

Carguemos un dataset de viajes en taxi en Buenos Aires. Contiene el identificador del taxista, el momento de inicio y fin del viaje, duración del viaje en segundos, coordenadas de origen, coordenadas de destino y la cantidad de pasajeros.

head(viajes_taxi)
##   id_viaje_r id_taxista_r            fecha_inicio               fecha_fin
## 1          1          499 2017-05-01 00:12:48.000 2017-05-01 00:31:09.000
## 2          2          715 2017-05-01 00:17:21.000 2017-05-01 00:28:36.000
## 3          3          429 2017-05-01 00:16:03.000 2017-05-01 00:36:33.000
## 4          4          164 2017-05-01 00:34:39.000 2017-05-01 00:54:57.000
## 5          5          499 2017-05-01 00:32:02.000 2017-05-01 00:48:37.000
## 6          6          695 2017-05-01 00:45:37.000 2017-05-01 00:59:00.000
##   duracion origen_viaje_x origen_viaje_y destino_viaje_x destino_viaje_y
## 1     1101      -58.38730      -34.59432       -58.43145       -34.57819
## 2      675      -58.41399      -34.58276       -58.43849       -34.58742
## 3     1230      -58.42991      -34.59942       -58.48317       -34.56460
## 4     1218      -58.44784      -34.63374       -58.43939       -34.59365
## 5      995      -58.43316      -34.57962       -58.40372       -34.59986
## 6      803      -58.41368      -34.58750       -58.44471       -34.58994
##   cantidad_pasajeros
## 1                  3
## 2                  1
## 3                  1
## 4                  2
## 5                  2
## 6                  1

Podemos visualizar la información trazando arcos, líneas curvas que conectan origen y destino de los viajes.

Al crear una visualización con Mapdeck, siempre es necesario dar un nombre a cada capa, con el parámetro “layer_id”. Puede tener el nombre que queramos (a continuación usaremos “lineas_taxis”), pero siempre debe tener uno. Esto es necesario por el funcionamiento interno de deck.gl, que requiere que cada capa visualizada tenga un identificador.

mapdeck(style = mapdeck_style("dark"), pitch = 45) %>%
    add_arc(data = viajes_taxi,
            layer_id = "lineas_taxis",
            origin = c("origen_viaje_x", "origen_viaje_y"),
            destination = c("destino_viaje_x", "destino_viaje_y"), 
            stroke_from = "duracion",
            stroke_from_opacity = 100,
            stroke_to = "duracion", 
            stroke_to_opacity = 100,
            stroke_width = "cantidad_pasajeros")

Si en lugar de arcos preferimos trazar líneas rectas, podemos usar add_line() en lugar de add_arc()

Trayectos (paths)

Practiquemos con un archivo espacial que contiene rutas entre estaciones de bicicletas públicas. El dataset contiene las rutas estimadas para los 100 viajes más populares (cada viaje tiene como origen y destino estaciones distintas de la red de bicicletas públicas).

recorridos_bici <- st_read("https://bitsandbricks.github.io/data/100_recorridos_BA_bici.geojson")
## Reading layer `100_recorridos_BA_bici' from data source `https://bitsandbricks.github.io/data/100_recorridos_BA_bici.geojson' using driver `GeoJSON'
## Simple feature collection with 100 features and 5 fields
## geometry type:  LINESTRING
## dimension:      XY
## bbox:           xmin: -58.44249 ymin: -34.62843 xmax: -58.35621 ymax: -34.56658
## epsg (SRID):    4326
## proj4string:    +proj=longlat +datum=WGS84 +no_defs
head(recorridos_bici)
## Simple feature collection with 6 features and 5 fields
## geometry type:  LINESTRING
## dimension:      XY
## bbox:           xmin: -58.42635 ymin: -34.59587 xmax: -58.37324 ymax: -34.57185
## epsg (SRID):    4326
## proj4string:    +proj=longlat +datum=WGS84 +no_defs
##   ORIGEN_ESTACION DESTINO_ESTACION  duration distance total
## 1               1                2 15.518333   5.4225   333
## 2               1                9  5.631667   1.8977    81
## 3               1               14  9.663333   4.1159    62
## 4               1               44  6.095000   2.7773   146
## 5               1               69 10.173333   3.0146    67
## 6               2                1  6.736667   2.2984   311
##                         geometry
## 1 LINESTRING (-58.39256 -34.5...
## 2 LINESTRING (-58.39256 -34.5...
## 3 LINESTRING (-58.39256 -34.5...
## 4 LINESTRING (-58.39256 -34.5...
## 5 LINESTRING (-58.39256 -34.5...
## 6 LINESTRING (-58.37493 -34.5...
mapdeck(style = mapdeck_style("dark"),
        location = c(-58.38, -34.6), zoom = 10) %>%
  add_path(data = recorridos_bici, 
           tooltip = "PEPE",
           stroke_colour = "total",
           layer_id = "path_bicis", 
           palette = viridis::plasma)

Mapas de puntos (scatter)

Mostrando los más de 10.000 alojamientos ofrecidos por AirBNB en Buenos Aires, a principios de 2018.

airbnbaires <- read_csv("https://query.data.world/s/o3oj2566jeun7bzeudzkto26yofff3")
head(airbnbaires)
## # A tibble: 6 x 26
##    room_id host_id room_type country city  neighborhood address    reviews
##      <int>   <int> <chr>     <chr>   <chr> <chr>        <chr>        <int>
## 1  7556928  3.96e⁷ Private … <NA>    <NA>  <NA>         Buenos Ai…       1
## 2   769573  4.06e⁶ Private … <NA>    <NA>  <NA>         Buenos Ai…       0
## 3  9032306  2.90e⁷ Private … <NA>    <NA>  <NA>         Buenos Ai…       0
## 4 16828729  5.45e⁷ Private … <NA>    <NA>  <NA>         Buenos Ai…       5
## 5  2671579  1.37e⁷ Private … <NA>    <NA>  <NA>         Lanús Est…       0
## 6 16097606  1.02e⁸ Private … <NA>    <NA>  <NA>         Buenos Ai…       0
## # ... with 18 more variables: overall_satisfaction <dbl>,
## #   accommodates <int>, bedrooms <int>, bathrooms <dbl>, price <int>,
## #   deleted <int>, minstay <chr>, last_modified <dttm>, latitude <dbl>,
## #   longitude <dbl>, survey_id <int>, location <chr>,
## #   coworker_hosted <chr>, extra_host_languages <chr>, name <chr>,
## #   property_type <chr>, currency <chr>, rate_type <chr>
# Antes de mapear, eliminamos registros con el campo "price" vacío; de lo contrario
# mapdeck genera un error.

airbnbaires <- airbnbaires %>% 
    filter(!is.na(price))

## Y tambien quitamos outliers, como habitaciones a más de 10.000 pesos la noche

airbnbaires <- airbnbaires %>% 
    filter(price < 3000)

mapdeck(style = mapdeck_style("light"), # Para variar
        location = c(-58.38, -34.6), zoom = 10) %>%
    add_scatterplot(data = airbnbaires,
                     lat = "latitude",
                     lon = "longitude",
                     radius = "bedrooms",
                     fill_colour = "price", 
                     palette = viridisLite::plasma,
                     layer_id = "scatter_airbnb")

Mapas de calor (screen grid)

Siguiendo con AirBNB: Concentración de oferta

mapdeck(style = mapdeck_style('streets'), pitch = 45,
        location = c(-58.38, -34.6), zoom = 12 ) %>%
    add_screengrid(data = airbnbaires,
                   lat = "latitude", 
                   lon = "longitude", 
                   layer_id = "screengrid_airbnb",
                   cell_size = 10,
                   opacity = 0.7)

Y más!

Otras capas y trucos en la documentación oficial de Mapdeck:

https://cran.r-project.org/web/packages/Mapdeck/vignettes/Mapdeck.html