Skip to content

R for Journalists

Unlock the power of R

  • What Is R?
  • R for Rob
  • GitHub
  • Twitter
  • Etsy
  • Home
  • 2020
  • December
  • 15
  • How to access Open Street Map in R

How to access Open Street Map in R

Posted on December 15, 2020May 4, 2022 By Rob
Geospatial data, Landmark Atlas, Learn

Author’s note: if you like this post, you might like Landmark Atlas. This is my new blog where I tell stories about Britain’s history, culture and geography through maps.


What is Open Street Map?

Open Street Map (OSM) is a world map put together by volunteers. Its data is open, meaning that with appropriate credit you can use OSM data for your own work.

It has topographical features such as rivers and forests as well as man-made features such as roads and buildings.

Here is an embedded OSM map centred on central London (it may need zooming in):


View Larger Map

What are the strengths of OSM?

International

OSM covers the entire world (in varying degrees of detail). It’s unlikely that national statistics agencies for different countries will have much, if any, geospatial data that doesn’t pertain directly to them.

Open data

OSM allows you to reuse their data, including for commercial purposes, provided you credit them appropriately. This is usually as simple as putting:

© OpenStreetMap contributors

Coverage and accuracy

The map itself is usually comprehensive, meaning it doesn’t leave out any major features. It is also very accurate when you compare it to other sources of map data available online.

How do you access Open Street Map in R?

You can obtain access to OSM data in R via the osmdata package.

To get started, load the osmdata package and let’s begin drawing a map of bars in a section of central London.

We have to work with OSM’s Overpass query. The first thing to do is to specify the location in the world that we are interested in mapping using the opq() function. There are two ways to do this.

  1. Specify a named location
  2. Specify the bounding box for Open Street Map to draw. You do this with two latitude and longitude coordinates which will form the limits of your box.

The first option is the simpler one. The second one is more complex but offers more flexibility by essentially saying to Open Street Map: ‘Give me everything within this area’.

I recommend the second option if you are interested in drawing a large or densely-populated area. If you request ‘London’ OSM will give you the entire city, which may time out the server request or at any rate provide you with a lot of data that you won’t need.

All this code is on GitHub.

#first option (not recommended in this case)
library(osmdata)
library(tidyverse)
library(sf)

town <- 'London' 
location <- town %>% opq()

#second option (recommended)
coords <- matrix(c(-0.1,-0.07,51.5,51.52), byrow = TRUE, nrow = 2, ncol = 2, dimnames = list(c('x','y'),c('min','max'))) 
location <- coords %>% opq()

Retrieving OSM data

Open Street Map has two attributes to identify things on a map: features and tags.

A feature is a type of object that can be mapped such as buildings, highways and railways. Features contain various tags that go into more detail about what the feature is. For example the natural feature contains the likes of wood, coastline and beach.

Building a query

water <- location %>%
   add_osm_feature(key = "natural", 
                   value = c("water")) %>%
   osmdata_sf()

Here is a sample query. Note that we are using the location that we defined earlier and adding the OSM feature ‘natural’ with the ‘water’ tag. Finally the osmdata_sf() function actually requests the data from the server in simple feature (sf) format, which we have been using so far in this series.

You’ll notice a c() in front of water. I put this there by default because sometimes I want to search for more than one tag e.g. value = c("water","coastline")

Examining the result

This query returns a list of different types of geospatial data:

  • points
  • lines
  • polygons
  • multipolygons

Which one is suitable to plot depends on the feature you are interested in. For individual features such as cafes or statues points may be appropriate. For roads it will likely be lines. For lakes it may be polygons or even multipolygons.

In this case it’s the multipolygons that have the best, most useable plot of the River Thames:

ggplot() + geom_sf(data = water$osm_multipolygons, fill = 'light blue') + theme_minimal()

The code below builds up a map of pubs in central London.

#build different types of streets
main_st <- data.frame(type = c("motorway","trunk","primary","motorway_junction","trunk_link","primary_link","motorway_link"))
 st <- data.frame(type = available_tags('highway'))
 st <- subset(st, !type %in% main_st$type)
 path <- data.frame(type = c("footway","path","steps","cycleway"))
 st <- subset(st, !type %in% path$type)
 st <- as.character(st$type)
 main_st <- as.character(main_st$type)
 path <- as.character(path$type)

#query OSM
 main_streets <- location %>%
   add_osm_feature(key = "highway", 
                   value = main_st) %>%
   osmdata_sf()
 streets <- location %>%
   add_osm_feature(key = "highway", 
                   value = st) %>%
   osmdata_sf()
 water <- location %>%
   add_osm_feature(key = "natural", 
                   value = c("water")) %>%
   osmdata_sf()
 rail <- location %>%
   add_osm_feature(key = "railway", 
                   value = c("rail")) %>%
   osmdata_sf()
 parks <- location %>%
   add_osm_feature(key = "leisure", 
                   value = c("park","nature_reserve","recreation_ground","golf_course","pitch","garden")) %>%
   osmdata_sf()
 buildings <- location %>%
   add_osm_feature(key = "amenity", 
                   value = "pub") %>%
   osmdata_sf()
 
#plot map
ggplot() + geom_sf(data = water$osm_multipolygons, fill = 'light blue') + theme_minimal()
 ggplot() + 
   geom_sf(data = main_streets$osm_lines, color = '#ff9999', size = 2) + 
   geom_sf(data = streets$osm_lines, size = 1.5, color = '#eedede') +
   geom_sf(data = water$osm_polygons, fill = '#c6e1e3') +
   geom_sf(data = water$osm_multipolygons, fill = '#c6e1e3') +
   geom_sf(data = rail$osm_lines, color = '#596060', size = 1) +
   geom_sf(data = parks$osm_polygons, fill = '#94ba8e') +
   geom_sf(data = buildings$osm_points, color = '#40493f', fill = '#40493f', size = 2) +
   coord_sf(xlim = c(coords[1], coords[1,2]), 
                                             ylim = c(coords[2], coords[2,2]),
                                             expand = FALSE) + theme_minimal()

The pubs are the dark blobs on the map.

A few things to note about the code:

  • There are lots of different options in the highway feature so I made vectors called main_st, st and path (not pictured) to divide them up.
  • The coord_sf() function allows you to specify the area to plot. This is useful because sometimes an OSM object will stretch out beyond the confines of your bounding box, like the River Thames in our earlier example. This is what the same code looks like without coord_sf():

Not much good.

  • The plot uses a healthy mix of points, lines, polygons and multipolygons
  • The colour values are hex codes. There are numerous websites devoted to helping you pick the right one – a certain amount of trial and error is needed to get ones you are happy with.

Conclusion

That is my beginner’s overview to using Open Street Map. For more, please study the list of features and see what you can discover.

As I said in my introductory post, I started my mapping journey with Open Street Map and then moved to Ordnance Survey data. I’ll show you how to work with OS data in another post. I will also write another one comparing the pros and cons of the two sources.

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook

Related

Tags: geospatial mapping Open Street Map

Post navigation

❮ Previous Post: Five more useful spatial functions from the sf package
Next Post: Introducing Landmark Atlas: my R mapping project on Etsy ❯

Recent Posts

  • I’ve moved my blog over to Substack
  • How to plot a large rural area using Ordnance Survey data in R
  • Check the COVID-19 vaccination progress in your area
  • Let R tell you what to watch on Netflix
  • Sentiment analysis of Nineteen-Eighty-Four: how gloomy is George Orwell’s dystopian novel?

Archives

  • April 2022
  • April 2021
  • March 2021
  • February 2021
  • January 2021
  • December 2020
  • February 2020
  • December 2019
  • November 2019
  • October 2019
  • April 2018
  • March 2018
  • January 2018
  • December 2017
  • November 2017
  • October 2017
  • September 2017
  • August 2017
  • July 2017
  • May 2017
  • April 2017
  • March 2017
  • February 2017
  • January 2017
  • December 2016
  • November 2016
  • October 2016
  • September 2016

Categories

  • Geospatial data
  • Landmark Atlas
  • Learn
  • See
  • Seen Elsewhere
  • Site
  • Uncategorized

Copyright © 2025 R for Journalists.

Theme: Oceanly by ScriptsTown

 

Loading Comments...