The goal of mapboxer is to make it easy to create interactive maps using Mapbox GL JS within R. Visualizations can be used at the R console, embedded in R Markdown documents or Shiny apps.
This guide covers the basic usage.
Map: The map is the main component of your visualization to which you then add other components like layers, controls or sources. Maps are created with mapboxer()
.
Sources: Sources state which type of data should be displayed on the map. R objects can be converted to Mapbox sources with as_mapbox_source()
. With add_source()
or as first parameter of mapboxer()
sources can be added to the map so that they can be used accross layers.
Layers: A layer’s style define how a source is displayed on the map. Furthermore, you can apply filters to the data of a source. With add_layer()
you can add any type of layer to the map but in most cases it is easier to use one of the shortcuts like add_circle_layer()
.
Controls: Controls are used to interact with the map. Besides the standard controls like NavigationControl
included in Mapbox GL JS, mapboxer provides additional controls. For example, add_filter_control()
can be used to filter your data on the fly without having to set up a Shiny app.
Expressions: Expressions are pretty powerful. Among other things, they can be used for data-driven-styling or to filter your data.
Shiny Bindings: With renderMapboxer()
and mapboxerOutput()
you can integrate your visualizations in Shiny apps. Furthermore, you can use mapboxer_proxy()
and update_mapboxer()
to update an already rendered widget. Observe the input$<widget_id>_onclick
event to get the properties for a clicked feature.
# Load the library
library(mapboxer)
# Create a source
motor_vehicle_collisions_nyc %>%
dplyr::mutate(color = ifelse(injured > 0, "red", "yellow")) %>%
as_mapbox_source(lng = "lng", lat = "lat") %>%
# Setup a map with the default source above
mapboxer(
center = c(-73.9165, 40.7114),
zoom = 10
) %>%
# Add a navigation control
add_navigation_control() %>%
# Add a layer styling the data of the default source
add_circle_layer(
circle_color = c("get", "color"),
circle_radius = 3,
# Use a mustache template to add popups to the layer
popup = "Number of persons injured: {{injured}}"
)
With mapboxer()
you create a map object. This is the main component of your vizualization. To add components like layers or controls or to modify your map you use the add_*
and set_*
functions. The options to configure your map are set via the ...
parameter that allows you to pass on any option described in the Map API Reference:
mapboxer(
style = basemaps$Carto$dark_matter,
center = c(-73.9165, 40.7114),
zoom = 9,
minZoom = 8
)
With the optional source
parameter you can add a default source to the map that will be used by the layers if no source is provided. Therefore, it is easy to integrate mapboxer()
into your workflow:
motor_vehicle_collisions_nyc %>%
dplyr::filter(killed > 0) %>%
as_mapbox_source() %>%
mapboxer(
center = c(-73.9165, 40.7114),
zoom = 9
) %>%
add_circle_layer(circle_color = "red")
As you can see above mapboxer is designed to use the widely used piping style provided by magrittr.
The style
parameter passed to mapboxer()
sets the style of the basemap. By default mapboxer uses a Carto vector style. It is also possible to use raster tiles or a background color as basemap. Therefore, you can use the helpers basemap_raster_style()
or basemap_background_style()
:
mapboxer(style = basemap_raster_style())
To use styles from Mapbox it is recommened that your store your API token in an environment variable called MAPBOX_API_TOKEN
. If not set globally you can store it as follows:
Sys.setenv(MAPBOX_API_TOKEN = "<yourSuperSecretToken>")
mapboxer(style = basemaps$Mapbox$satellite_v9)
Sources state which data the map should display. To show the data on the map you need to bind a source to a layer which contains the styling details like color or width. This makes it possible to style the same source in different ways. The easiest way to create a source from an R data object is to use as_mapbox_source()
. Supported structures are sf-objects and data frames that contain longitudes and latitudes:
mvc_sf <- motor_vehicle_collisions_nyc %>%
sf::st_as_sf(coords = c("lng", "lat"), crs = 4326)
mvc_source_from_sf <- mvc_sf %>%
as_mapbox_source()
mvc_source_from_df <- motor_vehicle_collisions_nyc %>%
as_mapbox_source(lng = "lng", lat = "lat")
With the ...
parameter you can pass additional options to the source:
mvc_cluster <- motor_vehicle_collisions_nyc %>%
as_mapbox_source(
lat = "lat",
lng = "lng",
cluster = TRUE,
clusterMaxZoom = 14,
clusterRadius = 50
)
See the Sources API Reference for available options for the used source type. Sources are either passed to the add_*_layer
functions or as first parameter to mapboxer()
setting it as default source. With add_source()
you can add a source to the map that you refer to in the layer definition by its ID.
Layers style the data of the source to which they refer. Optionally you can filter features. Each layer must have a unique ID. If you use the generic function add_layer()
, the type of the layer is specified by the type
property. See the Layers API Reference for available types. In most cases it is convenient to use one of the add_*_layer()
functions:
mapboxer(
center = c(-73.9165, 40.7114),
zoom = 9
) %>%
add_circle_layer(
source = as_mapbox_source(motor_vehicle_collisions_nyc),
circle_color = "red",
circle_radius = 5
)
Usually popups are added to a layer with the popup
parameter of the add_*_layer()
functions. Optionally you can also use add_popups()
. The popup text (HTML) is specified by a mustache template in which the tags refer to the properties of the layer’s data object. If your data contains the properties name
and population
, it could look like this:
popup_template <- "Name: {{name}}</br>Population: {{population}}"
With add_tooltips()
you can add tooltips to a layer in the same way.
Controls are used to interact with the user. They are displayed as overlays on top of the map. Options of the standard controls described in the Markers and Controls API Reference are provided with the ...
parameter. The position is set with the pos
parameter, one of top-left
, top-right
, bottom-right
, bottom-left
:
mapboxer() %>%
add_navigation_control(
pos = "top-left",
# Option passed to the 'NavigationControl'
showCompass = FALSE
) %>%
add_scale_control(
pos = "bottom-left",
# Option passed to the 'ScaleControl'
unit = "nautical"
) %>%
add_text_control(
pos = "top-right",
text = "mapboxer"
)
The value of any layout property, paint property (data-driven-styling) or filter may be specified as an expression. Expressions in Mapbox GL JS use a Lisp-like syntax represented as JSON arrays:
[expression_name, argument_0, argument_1, ...]
Therefore, in R you must use the list
structure:
list(expression_name, argument_0, argument_1, ...)
If all elements are of the same type you can also use a vector:
expr_get_property <- c("get", "<data-property>")`
A simple expression is to use a data property to style your data:
map <- motor_vehicle_collisions_nyc %>%
dplyr::mutate(
color = ifelse(injured > 0, "red", "yellow")
) %>%
as_mapbox_source() %>%
mapboxer(
center = c(-73.9165, 40.7114),
zoom = 9
)
map %>%
add_circle_layer(
# Expression to get the color from the data's color property
circle_color = c("get", "color")
)
You can get the same result for the circle_color
without modifying the data but using expressions only:
map %>%
add_circle_layer(
circle_color = list(
"case",
# 'red' if 'injured > 0'
list(">", c("get", "injured"), 0), "red",
# Defaults to 'yellow'
"yellow"
)
)
A filter could look like this:
map %>%
add_circle_layer(
circle_color = c("get", "color"),
# Expression to display only data where 'injured > 1'
filter = list(">", "injured", 1)
)
See also add_filter_control()
to modify filter expressions on the fly to update your map without the need of a Shiny app, Get started with expressions for a tutorial and the Expressions Style Specification for details.
Use mapboxerOutput()
and renderMapboxer()
to integrate mapboxer in a Shiny app:
library(shiny)
library(mapboxer)
view <- fluidPage(
h1("mapboxer"),
mapboxerOutput("map")
)
backend <- function(input, output) {
output$map <- renderMapboxer({
mapboxer(center = c(9.5, 51.3), zoom = 10) %>%
add_navigation_control() %>%
add_marker(lng = 9.5, lat = 51.3, popup = "mapboxer")
})
}
if (interactive()) shinyApp(view, backend)
With mapboxer_proxy()
and update_mapboxer()
you can update your already rendered map:
LAYER_ID <- "crashes"
START_VALUE <- 4
view <- basicPage(
sliderInput("slider", "Number of persons injured:",
min = 0, max = 7, step = 1, value = START_VALUE),
mapboxerOutput("map")
)
backend <- function(input, output) {
output$map <- renderMapboxer({
mapboxer(
center = c(-73.9165, 40.7114),
zoom = 9
) %>%
add_circle_layer(
source = as_mapbox_source(motor_vehicle_collisions_nyc),
circle_color = "red",
popup = "{{injured}}",
filter = list("==", "injured", START_VALUE),
id = LAYER_ID
)
})
observeEvent(input$slider, {
mapboxer_proxy("map") %>%
set_filter(LAYER_ID, list("==", "injured", input$slider)) %>%
update_mapboxer()
})
}
if (interactive()) shinyApp(view, backend)
Observe the input$<widget_id>_onclick
event to get the properties for a clicked feature.