Travis-CI Build Status Coverage Status

Introduction

rmapzen is a client for the Mapzen API. For more information, see https://mapzen.com/documentation/. The project is available on github.

Isochrones

The isochrone service allows you to “[compute] areas that are reachable within specified time intervals from a location, and returns the reachable regions as contours of polygons or lines that you can display on a map”. Below is an example of finding places within driving distance of UC Berkeley, and plotting them using the leaflet package.

ucb <- mz_geocode("UC Berkeley")
isos <- mz_isochrone(
    ucb,
    costing_model = mz_costing$auto(),
    contours = mz_contours(c(10, 20, 30))
)

library(leaflet)
leaflet(as_sp(isos)) %>%
    addProviderTiles("CartoDB.DarkMatter") %>%
    addPolygons(color = ~paste0("#", color), weight = 1) %>%
    addLegend(colors = ~paste0("#", color), 
              labels = ~paste(contour, "minutes"),
              title = "Drive times from <br/> UC Berkeley Campus")

Vector tile service

rmapzen provides an interface to Mapzen’s vector tiles service. Tile requests can be specified using the x, y, zoom coordinates of the tile service, as well as with a lat/long bounding box. For instance, continuing the previous example:

# mz_bbox is a generic that returns the bounding box of an object
ucb_tiles <- mz_vector_tiles(mz_bbox(isos))

# vector tiles return all layers (roads, water, buildings, etc) in a list
roads <- as_sp(ucb_tiles$roads)
## NOTE: keeping only 617 wkbLineString of 617 features
roads <- subset(roads, kind != "ferry")

# some layers contain multiple geometry types (points, lines, polygons)
# but Spatial*DataFrames can only contain a single type
water <- as_sp(ucb_tiles$water, geometry_type = "polygon")
## NOTE: keeping only 121 wkbPolygon of 1324 features
water <- subset(water, kind == "ocean")

# make a quick static map that includes roads and oceans as reference
library(ggplot2)
water_df <- fortify(water)
## Regions defined for each Polygons
roads_df <- fortify(roads) 

ggplot(roads_df, aes(x = long, y = lat, group = group)) +
    coord_quickmap() +
    theme_void() +

    # add ocean
    geom_polygon(data = water_df, colour = NA, fill = "lightblue") +
    
    # add the road network
    geom_path(size = .2, colour = "gray30") +
    
    # add the isochrones
    geom_polygon(data = as.data.frame(isos),
                 aes(x = lon, y = lat, group = contour),
                 colour = NA, fill = "black", alpha = .3)

Tidiness/Interoperability

As some of the above examples illustrate, any object returned by a Mapzen service can be converted to the appropriate Spatial* object using the generic function as_sp, for easy interoperability with other packages. You can also convert most objects directly to data frames, allowing for use within tidy pipelines:

library(dplyr)
as.data.frame(hard_rock) %>%
    select(name, confidence, region, locality, neighbourhood)
## # A tibble: 10 × 5
##                  name confidence          region       locality
##                 <chr>      <dbl>           <chr>          <chr>
## 1      Hard Rock Café      0.902       Stockholm      Stockholm
## 2      Hard Rock Cafe      0.962 Västra Götaland       Göteborg
## 3    Rock'n Roll Café      0.662           Skåne           <NA>
## 4        Carolas Cafe      0.661           Skåne       Furulund
## 5          Cafe Charm      0.661  Västernorrland      Sundsvall
## 6          Cafe capri      0.661       Stockholm Upplands Väsby
## 7           Cafeteria      0.661       Jönköping           <NA>
## 8  CaféHarpaviljongen      0.661       Stockholm      Stockholm
## 9       Cafe Columbia      0.661    Östergötland           Kisa
## 10         Cafékoppen      0.661       Stockholm      Stockholm
## # ... with 1 more variables: neighbourhood <chr>

Mapzen list methods

Currently, the following methods are available to pull out commonly used pieces of a response:

  • mz_coordinates (only available for search results)
  • mz_bbox
mz_coordinates(hard_rock)
## # A tibble: 10 × 2
##         lon      lat
##       <dbl>    <dbl>
## 1  18.05484 59.34408
## 2  11.97425 57.70123
## 3  13.83493 55.93419
## 4  13.09754 55.77635
## 5  17.30462 62.38921
## 6  17.94834 59.39728
## 7  14.13232 57.58279
## 8  18.08074 59.34991
## 9  15.63464 57.98744
## 10 17.96348 59.28589
mz_bbox(ucb_tiles)
## # A tibble: 1 × 4
##     min_lon min_lat   max_lon max_lat
## *     <dbl>   <dbl>     <dbl>   <dbl>
## 1 -123.0469 37.1603 -121.6406 38.2727

A more detailed example

Say you have an afternoon meeting at the TransAmerica center in San Francisco, and would like to visit a local museum afterwards. Here’s how to make a map of museums within walking distance:

# first geocode the TransAmerica Center
trans_america <- mz_geocode("TransAmerica Center, San Francisco CA")

# then identify the area that is within 15 minutes walking distance
walkable <- mz_isochrone(
    trans_america,
    costing_model = mz_costing$pedestrian(),
    contours = mz_contours(15))

# now search for museums, but limit the search to areas within "walkable"
museums <- mz_search(
    "Museum", 
    boundary.rect = mz_bbox(walkable), 
    layers = mz_layers$venue, 
    size = 15
)

# use the leaflet package to draw the map
leaflet(as_sp(walkable)) %>%
    addProviderTiles("CartoDB.DarkMatter") %>%
    addPolygons(color = "#ffffff", weight = 1) %>%
    addMarkers(
        data = trans_america, 
        lat = ~geocode_latitude, 
        lng = ~geocode_longitude,
        popup = "TransAmerica Center") %>%
    addCircleMarkers(
        data = as_sp(museums), 
        weight = 1,
        radius = 7,
        opacity = 1,
        popup = ~name,
        color = "#ff0000")

Rate limits

Mapzen’s per-second published rate limits are automatically observed, using the ratelimitr package. The package does not manage daily limits for you, but you can check usage statistics at any time using the function mz_check_usage.

mz_check_usage()
## for the search endpoint:
##   updated on: Thu, 22 Dec 2016 02:34:58 GMT
##   remaining queries today: 29990
##   remaining queries this second: 5
## for the matrix endpoint:
##   updated on: Thu, 22 Dec 2016 02:34:57 GMT
##   remaining queries today: 4990
##   remaining queries this second: 1

These statistics are taken from the headers in the various responses from Mapzen and stored only for the length of the R session. If an endpoint has “No data,” that means you have yet to use that endpoint during the current R session, or that all uses of the endpoint have hit Mapzen’s cache servers and so have not been counted against usage limits.

Convenience features

Several of the search functions take, optionally, the arguments layers, sources, and boundary.country (the latter requires ISO-3166 codes). If you’re using an IDE with auto-complete, the objects mz_layers, mz_sources, and mz_countries should make it easier to get the correct codes.

Easy lookup for ISO-3166 codes

Easy lookup for ISO-3166 codes

Similarly, argument constructors are available for easier specifications of isochrone and search requests.

  • mz_costing
  • mz_costing_options
  • mz_location
  • mz_contours
  • mz_date_time

Installation

This is a very young package, things may break or change. To install:

devtools::install_github("tarakc02/rmapzen")

You’ll also need to acquire an API key, and then set the MAPZEN_KEY environment variable:

Sys.setenv(MAPZEN_KEY = "mapzen-xxxxxx")