KSU GIS Day Demo: Make a map in R

In celebration of the Kent State University Department of Geography’s GIS Day, I’ve created a hands-on demo of how to make a map in R using ggplot2 and posted it here for those who couldn’t make the demo.

This is a very basic example and does not go into great detail of R or spatial data in R (we don’t have that kind of time!). But if you already know a little something about R and spatial data, this exercise will get you up and running and hopefully serve as a template for your future work.

**Prior to this exercise, create a new RStudio Project in a new working directory, name of your choice. Then in Finder or WindowsExplorer, create two sub directories: “SourceData” and “Figures”. Place all data into the “SourceData” directory.
**

The data can be accessed on github. Special thanks to MapIt! and Jessica Reese for KSU campus data.

You will need the following packages for this demo: raster, ggplot2, sf, gridExtra

If they are not installed on your machine, do so now:

install.packages(c("raster", "ggplot2", "sf", "gridExtra"))

Once installed, they will need to be loaded:

library(raster)
library(ggplot2)
library(sf)
library(gridExtra)

Map 1 – KSU Campus Buildings

First we will load the required shapefiles:

KSU_Campus <- st_read("SourceData/KSU_Boundary.shp")
KSU_Buildings <- st_read("SourceData/KSU_Buildings.shp")

Note: we will not go into details of projections here, but spatial objects used in the same plot must have the same projection. This set of files have the same projection.

Next we will make the map using ggplot:

Map1<-ggplot() +
  #load campus boundary first
  geom_sf(data = KSU_Campus, size = 0.25, color = "black", fill = "gray80") + 
  #load buildings second - ggplot adds each layer in order, so we want buildings on top
  geom_sf(data = KSU_Buildings, size = 0.5, color = "darkblue", fill = "yellow") +
  coord_sf()+
  #add labels
  labs(title = "Kent State University Campus",
       subtitle = "Building Footprints - 2019", 
       caption = "Data Sources: KSU Data (Map It!); OH Data (Ohio DOT)")+
  theme_linedraw() #this will remove the default gray background from the map
Map1 #plot map

We can save it to the Figures directory using ggsave():

ggsave("Figures/KSU_Map.jpg", Map1, width=8, height=4, dpi=300) #save map

Map 2 – Kent Vicinity Map

Let’s create a second map so we know where in Ohio Kent is located.

First we’ll load some additional shapefiles, then create the map:

OH_County <- st_read("SourceData/OH_Counties.shp")
OH_Kent <- st_read("SourceData/Kent_OH_Boundary.shp")

#Next we will make the map using ggplot:

Map2<-ggplot() +
  #load county boundaries first
  geom_sf(data = OH_County, size = 0.25, color = "black", fill = "gray80") + 
  #load Kent boundary second - ggplot adds each layer in order
  geom_sf(data = OH_Kent, size = 0.25, color = "black", fill = "red") +
  #here is a different way to add a title
  ggtitle("Location Map") + 
  #let's hide the axis ticks and labels since we aren't worried about those details at this scale
  theme(axis.ticks = element_blank(), axis.text.x = element_blank(), axis.text.y=element_blank())+
  theme_linedraw() #this will remove the default gray background from the map
Map2

Not bad, but if we show the town of Kent as a polygon it probably won’t scale well. Let’s convert the Kent polygon to a centroid, then we’ll show it on the map as a point.

OH_Kent_Centroid <- st_geometry(st_centroid(OH_Kent))

Now we’re ready to make another map using the new centroid:

inset.map<-ggplot() +
  #load county boundaries first
  geom_sf(data = OH_County, size = 0.25, color = "black", fill = "gray80") + 
  #load Kent centroid; we'll display as a square (shape = 15)
  geom_sf(data = OH_Kent_Centroid, size = 1, color = "red", shape= 15) +
  ggtitle("Kent Location Map") + 
  theme(axis.ticks = element_blank(), axis.text.x = element_blank(), 
        axis.text.y=element_blank(),
        panel.border = element_rect(colour = "black", fill=NA, size=1))+
  theme_linedraw() #this will remove the default gray background from the map
inset.map

This should be much better for scaling the map in the next step.

Map 3 – Composite Map

Now let’s put the two maps together into a composite map. Since we already wrote the two maps to objects, we can simply call them here and arrange using the gridExtra package.

# We'll have two columns, specify the order and the width of each map
composite_map<-grid.arrange(Map1, inset.map, ncol=2, widths=c(7,3))
composite_map
#save the map
ggsave("Figures/Composite_map.jpg", composite_map, width=8, dpi=300)

Now that’s a publication quality map that didn’t take all that much code to create. Hopefully you can use this template to create future maps. Go forth and be spatial!