I’ve adapted an old homework problem set from a data management class I took during my M.S. degree for this blog post. The homework was to make a map showing your hometown in R! I thought this would be a fun way to introduce you to some of R’s mapping capabilities. I encourage you to change my code in the appropriate places to map your own hometown.

Hopefully by the end of this you will have the skills you need to create your own maps in R worthy of publication! Let’s give it a whirl. I will give examples using two different packages mainly used for creating maps- maps and ggmap. Other packages exist for creating maps in R as well but I am most familiar with maps and ggmap so I will stick with those for this post.

Let’s load up the packages we will use today.

#For mapping capabilities and spatial layers
require(maps)
require(ggmap)

#For map extras like scale bars and north arrows
require(GISTools)
require(ggsn)

#For %>%
require(dplyr)

maps

I am going to walk through how to create nice looking maps in R using two different packages. Let’s get started with the maps package, which has a similar syntax structure as R’s base plotting capabilities.

I will start by calling the map() function and asking for the latitude and longitude boundaries I want. Thankfully these packages come loaded with a lot of spatial layers already. The maps package comes loaded with a world, usa, state, and county database for spatial layers. If you have your own shape files you would like to add, R is capable of handling that too.

map("state", xlim = c(-125, -116.5), ylim = c(45, 49.9)) #note that you can also just call specific regions e.g. map("state", "washington")

Next, I can add my own data to the map. For example, I’m going to add a point to encircle the part of the state where I grew up.

map("state", xlim = c(-125, -116.5), ylim = c(45, 49.9))
points(-122.4982, 47.7987, col = "red", pch = 1, lwd = 2, cex = 1.5)

Now let’s add some fancy features like a north arrow, a scale bar, and map axes. These features are all part of the GISTools package and come in handy for making your maps look real nice.

map("state", xlim = c(-125, -116.5), ylim = c(45, 49.9))
points(-122.4982, 47.7987, col = "red", pch = 1, lwd = 2, cex = 1.5)
north.arrow(xb = -123.9, yb = 49, len=0.13, lab="N") 
maps::map.scale(x = -124.8, y = 45.6, ratio = F, relwidth=0.25)
map.axes(cex.axis=0.8)

We can take it one step further and add an inset map. This step is a bit tricky to do with maps. In general, it requires that you reset the plot boundaries using par(usr = ) and add a small map in the bottom corner. It will take some trial and error to get the dimensions just right.

map("state", xlim = c(-125, -116.5), ylim = c(45, 49.9))
points(-122.4982, 47.7987, col = "red", pch = 1, lwd = 2, cex = 1.5)
north.arrow(xb = -123.9, yb = 49, len=0.13, lab="N") 
maps::map.scale(x = -124.8, y = 45.6, ratio = F, relwidth=0.25)
map.axes(cex.axis=0.8)

par(usr=c(-216, -63, 22, 144))
rect(xleft = -128, ybottom = 22, xright = -63, ytop = 51, col = "white")

map("usa", add = T)
map("state", region = "washington", fill = T, add = T)
points(-122.4982, 47.7987, col = "white", pch = 16, cex  = 0.5)

ggmap

Creating maps using ggmap and ggplot2 does require more code, but you gain a lot in terms of flexibility and customization.

Let’s use these packages to re-create the same plot we just made above. We will start with creating the inset part of our map.

inset <- map_data("state") %>%
  ggplot() +
  geom_polygon(aes(x=long, y=lat, group = group), fill = 'cornsilk', color = "black") +
  geom_rect(xmin = -125, xmax = -116.5, ymin = 45, ymax = 49.9, fill = NA, colour = "black", size = 1.5) +
  theme_bw() +
  theme(axis.title = element_blank(), 
          axis.text  = element_blank(),
          axis.ticks = element_blank())
inset

Next I’ll create the main part of my plot.

states <- map_data("state")
wa <- subset(states, region == 'washington')

main <- wa %>%
  ggplot() +
  geom_polygon(aes(x=long, y=lat, group = group), fill = 'cornsilk', color = "black") +
  geom_point(aes(-122.4982,47.7987), color="red", size = 4, pch = 16) +
  xlab("Longitude") +
  ylab("Latitude") +
  theme_bw()

Now I will add the main plot and the inset together using inset().

#First I want to get the x and y limits of my main map to decide where to put the inset
layer_scales(main)$y$get_limits()
## [1] 45.53296 49.00508
layer_scales(main)$x$get_limits()
## [1] -124.6813 -116.9235
final_map <- main +
  inset(ggplotGrob(inset), xmin = -119.5, xmax = -116.9235, ymin = 45.53296, ymax = 46.5)
final_map

Now to add the scalebar and north arrow as finishing touches.

final_map + 
  north(wa, location = "topleft", scale = 0.15, symbol = 12) + #try northSymbols() to see all available north arrows
  scalebar(wa, location = "bottomleft", dist = 100, height = 0.03, transform = TRUE, model = "WGS84", dist_unit = "km") 

There really is no limit to what you can accomplish with R as long as you are willing to get over the learning curve. In addition to great mapping capabilities, you can also perform complex spatial analyses if you have spatial data.

Hopefully this post has provided you with the code scaffolding you will need to start creating nice looking maps of your own study sites in R.