The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Looking for a home

Say you are moving to a new city and want to live near the amenities that are important to you. In this tutorial, we find the blocks that are within a 10-minute walk of a supermarket, a 5-minute walk of a restaurant, and a 20-minute walk of a frequent-transit stop. Then, we narrow those blocks to the overlap of two commutes. The example city is Somerville, Massachusetts.

Running this tutorial uses about 2,600 tokens.

Set up

Build a client, then read the pieces you need from the free catalog instead of memorising codes.

library(closecity)
library(sf)
close <- closecity::close_client(api_key = "ck_live_your_key")   # use your own key here
# The catalog lists every category with its numeric id. Pull the ids you need.
amenity_types <- close$destination_types()
ids <- setNames(amenity_types$dest_type_id, amenity_types$label)

supermarket_dest_id <- ids[["grocery_stores"]]
restaurant_dest_id <- ids[["restaurants"]]
freq_transit_stop_dest_id <- ids[["frequent_transit"]]

# Turn the city name into a GEOID and pull its boundary for context.
city <- close$places(q = "Somerville")[1, ]
city_boundary <- close$place_boundary(geoid = city$geoid)

See what is around

Look at the raw ingredients first: every supermarket, restaurant, and frequent-transit stop within Somerville, from $place_pois(). The city boundary, not a guessed radius, is the edge. Give each category a colour and map them together.

supermarkets <- close$place_pois(geoid = city$geoid, type = supermarket_dest_id)
restaurants <- close$place_pois(geoid = city$geoid, type = restaurant_dest_id)
stops <- close$place_pois(geoid = city$geoid, type = freq_transit_stop_dest_id)

supermarkets$kind <- "Supermarket"
restaurants$kind <- "Restaurant"
stops$kind <- "Transit stop"
around <- rbind(supermarkets, restaurants, stops)

palette <- c(Supermarket = "#058040", Restaurant = "#c6cbe0", `Transit stop` = "#f36e21")
closecity::close_map(
  x = around,
  color = palette[around$kind],
  label = "kind",
  boundary = city_boundary
)

Find the blocks that qualify

Somerville is a census place, so one call by place GEOID pulls the per-block walk times for every block in the city. $place_blocks() reads every page and returns one sf row per (block, category); block boundaries come from tigris, downloaded once and cached. (To search an arbitrary area instead, use $blocks_query() with a centre and radius or a polygon. We do that with a radius in the other tutorials only to keep their token cost low; a place GEOID pulls the whole city.)

blocks <- close$place_blocks(
  geoid = city$geoid,
  mode = "walk",
  type = c(supermarket_dest_id, restaurant_dest_id, freq_transit_stop_dest_id)
)

Reshape to one row per block, with a walk-time column for each amenity, so a block carries all three times at once (and the hover on the map shows them). Then flag the blocks that pass every rule.

city_blocks <- blocks[!duplicated(blocks$geoid), "geoid"]
time_to <- function(type_id) {
  sub <- blocks[blocks$dest_type_id == type_id, ]
  setNames(sub$travel_time, sub$geoid)[city_blocks$geoid]
}
city_blocks$supermarket_min <- time_to(supermarket_dest_id)
city_blocks$restaurant_min <- time_to(restaurant_dest_id)
city_blocks$transit_min <- time_to(freq_transit_stop_dest_id)

city_blocks$qualifies <- (city_blocks$supermarket_min <= 10 &
                          city_blocks$restaurant_min <= 5 &
                          city_blocks$transit_min <= 20)
city_blocks$qualifies[is.na(city_blocks$qualifies)] <- FALSE

Show every block in the city, highlight the ones that qualify, and hover any block to read its walk time to each amenity.

closecity::close_map(
  x = city_blocks,
  highlight = "qualifies",
  color = "#f36e21",
  boundary = city_boundary
)

Narrow to a shared commute

Suppose two of you work in different places. A transit isochrone from each workplace shows how far each commute reaches; drawn together, half-transparent, you can see both at once.

work_a <- close$isochrone(
  lon = -71.0865,
  lat = 42.3625,
  mode = "transit",
  direction = "from",
  minutes = 20,
  format = "geojson"
)
work_b <- close$isochrone(
  lon = -71.0589,
  lat = 42.3555,
  mode = "transit",
  direction = "from",
  minutes = 20,
  format = "geojson"
)

closecity::close_map(
  x = work_a,
  color = "#058040",
  opacity = 0.5,
  background = work_b,
  background_color = "#f36e21",
  background_opacity = 0.5
)

Keep the qualifying blocks that also sit inside both commutes. The final map shows those winning blocks, with the shortlist (inside both commutes) highlighted, over the two commute walksheds.

both_commutes <- sf::st_intersection(sf::st_union(work_a), sf::st_union(work_b))
winners <- city_blocks[city_blocks$qualifies, ]
winners$shortlist <- sf::st_intersects(winners, both_commutes, sparse = FALSE)[, 1]

closecity::close_map(
  x = winners,
  highlight = "shortlist",
  color = "#1f78b4",
  boundary = city_boundary,
  background = list(work_a, work_b),
  background_color = c("#058040", "#f36e21"),
  background_fill = FALSE
)

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.