There are a number of workflows within R for making maps based on geospatial data. Here, we focus almost exclusively on mapping within the ggplot2 package ecosystem. But, it is certainly worth the effort to learn about the other options including tmap, mapview, and leaflet.
Choosing a Projection
It’s important that your spatial coordinates be projected. This is an important step when presenting your data as a map because the choice of projection can lead to unintentional perception bias and cause confusion. Just as importantly, geographic data that is represented in latitude and longitude coordinates cannot be used for animal movement modeling. Ideally, you will already have a good understanding of your study area and will have determined your target CRS. In this situation, you can use the sf::st_transform() function to transform your coordinates into this new projection.
If you are unsure of what CRS might be a good choice for your data, the crsuggest package can provide some insight. We’ll use this package to find a sensible projection for our Alaska bearded seal data. To help narrow the options, we can specify that we want to keep the corresponding geographic coordinate system as WGS 84 by passing the 4326 EPSG code to the gcs argument. We can also specify that we want our units to be in meters.
# A tibble: 10 × 4
crs_code crs_name crs_gcs crs_units
<chr> <chr> <dbl> <chr>
1 6124 WGS 84 / EPSG Arctic zone 4-12 4326 m
2 32602 WGS 84 / UTM zone 2N 4326 m
3 32601 WGS 84 / UTM zone 1N 4326 m
4 32603 WGS 84 / UTM zone 3N 4326 m
5 32604 WGS 84 / UTM zone 4N 4326 m
6 32605 WGS 84 / UTM zone 5N 4326 m
7 32606 WGS 84 / UTM zone 6N 4326 m
8 32607 WGS 84 / UTM zone 7N 4326 m
9 5926 WGS 84 / EPSG Arctic Regional zone B1 4326 m
10 5931 WGS 84 / EPSG Arctic Regional zone C1 4326 m
The first CRS suggested is the WGS 84 / EPSG Arctic zone 4-12. So, let’s go ahead and transform our data and see what this projection looks like on a map with our data. As mentioned above, we’ll use the sf::st_transform() function to do the transformation. To give ourselves some context, we’ll load simple world basemap data from the rnaturalearth package.
This looks pretty good and, now, we can proceed with making a more complete set of maps for our observations. The focus is still more about understanding the nature and distribution of our data than making perfect maps. But, it is reasonable to expect these products might be useful within future publications or presentations.
Map Observations with ggplot2
There are three methods for visualizing our observation data:
points on a map, colored by deploy_id
lines on a map, colored by deploy_id
grid of point density
Points on a Map
For this, we can start with the figure we made above. But, we’ll want to be more deliberate about grouping, color choices, and labels. For color choices, we’re going to choose palettes from the colorspace package. Also, we’ll take the opportunity to reduce the length of our deploy_id values.
library(colorspace)library(stringr)filt_locs <- filt_locs %>% dplyr::mutate(deploy_id = stringr::str_sub(deploy_id, 1,11))map <-ggplot() +geom_sf(data = world) +geom_sf(data = filt_locs, aes(color = deploy_id),size =0.35, shape =19) +coord_sf(xlim = sf::st_bbox(filt_locs)[c(1,3)],ylim = sf::st_bbox(filt_locs)[c(2,4)]) +scale_color_discrete_qualitative(palette ="Dark 3",name ="deployment") +labs(title ="Observed Locations of 6 Bearded Seals in NW Alaska",subtitle =paste0("some data were censored based on a","speed, distance, and angle filter")) +theme_minimal()map
This is pretty good, but it would be nice if we could interact with the data and zoom in on particular regions. The mapview package provides an easy means for creating interactive maps of your spatial data. The one caveat to mapview is that it is based on the Web Mercator projection (a la Google Maps, etc) and there are some extra steps required if your tracks cross the dateline at 180 (which ours do … yay! fun!)
What we need to do is transform our data back to geographic and, then, convert the coordinates from -180:180 to 0:360. We will use a custom written function to handle this for us. The st_to_360() function is not needed for data sets that do not cross the 180 meridian.
We will use the ESRI Ocean Basemap for our background layer and the same qualitative color palette we used above. The mapview package is based on the web mapping library, leaflet. Because of that, these interactive maps are only available when rendering to HTML or other HTML capable viewers.