Learn how to create maps using the ggplot2
package.
Basic understanding of ggplot2
is necessary. Here are some resources:
Click on the three horizontally stacked lines at the bottom left corner of the slide, then you will see table of contents, and you can jump to the section you want
Hit letter “o” on your keyboard and you will have a panel view of all the slides
sf
using the ggplot2
packageCreating maps differs from creating non-spatial figures in some ways. However, the underlying principle and syntax under ggplot2
to create maps and non-spatial figures are very similar.
Indeed, you will find map making very intuitive and rather easy if you already have some knowledge of how ggplot2
works even if you have not created maps using ggplot2
. The only major difference between them is the choice of geom_*()
types.
To create a map from sf
s, we use geom_sf()
.
Check how each of them looks like using plot()
:
Instruction
We can use geom_sf()
to create maps from sf
objects
geom_sf()
automatically detects the geometry type of spatial objects stored in an sf
object and draw maps accordingly
Syntax
Try to create a map using one of wells_ne_sf
, ne_counties
, and railroads_ne
.
ggplot2
.ggplot2
figures.We use corn_acres_ne
for demonstration. This is a county-level corn harvested acres data observed annually from 2020 through 2023.
Notice that a single county has multiple rows (one row for one year) with the identical geometry
Here are some of the aesthetic variables for points:
color
: color of the pointsfill
: available for some shapes (but likely useless)shape
: shape of the pointssize
: size of the points (rarely useful)color
: dependent on gw_extracted
(the amount of groundwater extraction)size
: constant across the points (bigger than the default)color
: constant across the points (blue)size
: dependent on gw_extracted
shape
: constant at 2 across the points (square)color
: constant across the points (blue)fill
: constant across the points (red)size
: constant at 1.5 across the pointsshape
: constant at 22 across the points (square)Here are some of the aesthetic variables for polygons:
color
: color of the borders of the polygonslinewidth
: width of the borders of the polygonsfill
: color of the inside of the polygonsshape
: not availablesize
: not availablecolor
: constant at “red” across the polygonsfill
: constant at “darkgreen” across the polygonslinewidth
: constant at 0.4 across the polygonscolor
: depends on name
fill
: constant at “darkgreen” across the polygonscolor
: constant at “red” across the polygonsfill
: depends on “countyfp”Here are some of the aesthetic variables for lines:
color
: color of the lineslinewidth
: width of the linescolor
: constant at “blue” across the lineslinewidth
: constant at 0.5 across the linesIt is often the case that you want to create a map using more than one spatial objects.
For example, you want to have county boundary (ne_counties
), railroads (railroads_ne
), and wells (wells_ne_sf
) all in one map.
You can create layers with geom_sf()
by setting different sf
objects as the datasets individually, and then simply add them so they appear in a single map.
Remember that when you specify data in ggplot()
, all subsequent geom_*()
functions will use this data unless otherwise specified.
Instruction
+
add the end of line 2, run, and see what happensne_couties
in line 1.geom_sf()
s that are added later are superimposed on top of the existing layers
Wells are hidden beneath the county layer:
Instruction
Hide the railroads beneath the county layer.
ggplot()
uses the CRS of the sf
to draw a map by default.
Currently, ne_counties
is unprojected:
Let’s project it to WGS 84, UTM zone 14.
Now, the map is drawn based on the new CRS of 32614
Notice that the major grid lines are no longer straight in figure at the bottom unlike the one at the top
X-Y labels are still in longitude and latitude (we will see how we change this)
You can use coord_sf()
to alter the CRS on the map on the go, but not the CRS of the sf
object itself.
In order to have X
and Y
values in the same units as that of the CRS in use on the map, you need to add datum =
in coord_sf()
.
When there are multiple geom_sf()
layers, the CRS of the first layers is automatically applied for all the layers , reconciling the difference in CRS automatically.
coord_sf()
applies to all the layers.coord_sf(32614)
at the endtheme_void()
is a veery suitable pre-made theme for map that can get rid of many unnecessary components from default maps.
The ggspatial
package lets you put a north arrow and scale bar on a map using annotation_scale()
and annotation_north_arrow()
location
: determines where the scale bar is
t
(top) or b
(bottom)l
(left) or r
(right).width_hint
: determines the length of the scale bar relative to the plotTry yourself
Play with location
and width_hint
and see what happens.
Use pad_x
and pad_y
options to fine-tune the location of the scale bar.
A positive number means that the scale bar will be placed further away from closest border of the plot.
pad_x
: since the second letter of location
is l
, the scale bar move an inch from the left border of the map
pad_y
: since the first letter of location
is b
, the scale bar move 0.3 inches from the bottom border of the map
Try yourself
Play with pad_x
and pad_y
and see what happens.
annotation_north_arrow()
to add north arrowannotation_scale()
style
option to pick a different type of north arrow symbolInset map (like one below) provides a better sense of the geographic extent and the location of the area of interest relative to the larger geographic extent that the readers are more familiar with.
Create a map like this using ne_counties
with the ggmapinset
package.
Note
Visit the ggmapinset
website for more examples and other functionalities beyond what is presented here, including multiple insets.
The first step of making an inset map is to create the base map layer, a part of which is going to be expanded as an inset.
We want to create a map of all the counties in Nebraska with only the three counties (Perkins, Chase, and Dundy) colored red.
Let’s first create an sf
consisting of the three counties first:
We now create the base map. You use geom_sf()
to create base map layers.
We now configure (specify) the inset using configure_inset()
. Here is the list of parameters you want to provide:
centre
: the geographic coordinates of the small circle from which you expandtranslation
: how much you shift in x and y from the center to display the enlarged circleradius
: radius of the small circle at the originscale
: how much to enlargeunits
: length unitgeom_sf_inset()
and/or geom_sf_text_inset()
to create layers to present as an inset.geom_inset_frame()
to add the inset frame (small circle, big circle, and the lines connecting them)coord_sf_inset(inset = inset_config)
to reflect the configuration you set up earlier.Try yourself
By default, geom_sf_inset()
creates two copies of the map layer: one for the base map and the other for the inset map.
map_base
option in geom_sf_inset()
determines whether you create the copy for the base map or not.
In the code below, map_base
is not specified, meaning that geom_sf_inset(data = three_counties, fill = "black")
will be applied for both the base and inset maps.
Try yourself
Comment out line 2 and comment in line 3 to see what happens.
We will use the gpplot2
and tidyterra
package to create maps using raster data.
The tidyterra
package provides geom_spatraster()
that works specifically for SpatRaster
object from the terra
package.
There are other options like the tmap
package. But, we do not talk about it in this course.
It works very much like map creation with sf
. We just use SpatRaster
object and use geom_spatraster()
in place of geom_sf
.
Note
Notice that geom_spatraster()
automatically based the fill color of the cells on the attribute values without you specifying so.
By default, the cells with NA values are colored grey. You can set the color for such cells using the na.value
option inside scale_*()
function. For example, the following code makes the cells with NA values transparent (invisible).
How does geom_spatraster()
behave with a multi-layer SpatRaster
?
As the warning message suggests, both layers are plotted by default. You can specify which layer to use with aes(fill = layer_name)
like below.
Note
When you want to create maps for individual attributes at the same time, you can add facet_wrap(~lyr)
.
sf
and SpatRaster
It is very easy to achieve this. You just use geom_sf()
for sf
and geom_spatraster()
for SpatRaster
. You just add them as layers just like any figures you create with ggplot2
.