A fully-commented walk-through of an R script that builds a publication-quality map of northwest Washington, ready for reuse or adaptation.
1 · Load the libraries
library(sf)
library(ggplot2)
library(ggmap)
library(ggspatial)
library(dplyr)
library(rnaturalearth)
library(rnaturalearthdata)
library(scales) # for alpha()
Why?
* sf
, rnaturalearth
, and dplyr
handle vector data and simple-feature operations.
* ggplot2
and ggspatial
layer data, add scale-bars & north arrows.
* ggmap
retrieves tiled basemaps.
* scales::alpha()
lets us tweak fill transparency later.
2 · Authenticate with Stadia Maps
register_stadiamaps(key = "7da33b85-7352-45de-8189-217884e7376a")
Registers your Stadia Maps API key so ggmap
can download high-resolution tiles.
Replace the key with an environment variable for production work.
3 · Define the map extent
nw_wash_bbox <- c(left = -124.5, bottom = 47.0, right = -122.0, top = 49.0)
A named numeric vector that sets the bounding box for northwest Washington.
Top edge fixed at 49.0 °N to match international border.
4 · Read the basin polygons
basins_sf <- st_read("/Users/zacharybengtsson/Desktop/puget-sound-basins")
Loads the Puget-Sound basin shapefile into an sf object.
5 · Remove basins we don’t need
basins_sf <- basins_sf %>%
filter(!regn_nm %in% c("Grays Harbor", "Willapa Bay"))
Drops Grays Harbor and Willapa Bay for a cleaner map.
6 · Define key locations
locations <- data.frame(
Name = c("South Sound", "Central Sound", "North Sound"),
Latitude = c(47.398583, 47.591472, 48.481944),
Longitude = c(-122.819722, -122.672722, -122.574583)
)
Defines labels and coordinates for regional markers.
7 · Convert to spatial features
locations_sf <- st_as_sf(locations,
coords = c("Longitude", "Latitude"),
crs = 4326)
Creates spatial points using WGS84 (EPSG:4326).
8 · Download a basemap
basemap <- get_stadiamap(bbox = nw_wash_bbox,
zoom = 8,
maptype = "stamen_terrain_background")
Fetches a terrain-style background from Stadia Maps.
9 · Create the map
map_plot <- ggmap(basemap) +
geom_sf(data = basins_sf, aes(fill = regn_nm), inherit.aes = FALSE,
color = "black", linewidth = 0.5, alpha = 0.6) +
geom_sf(data = locations_sf, inherit.aes = FALSE,
color = "black", fill = "white", shape = 21, size = 2, stroke = 1.5) +
geom_label(data = locations, aes(x = Longitude, y = Latitude, label = Name),
hjust = 1, vjust = -1, size = 4, color = "black", fontface = "bold",
fill = "white", alpha = 0.8, inherit.aes = FALSE) +
annotation_scale(location = "bl", width_hint = 0.3, style = "ticks") +
annotation_north_arrow(location = "tl", which_north = "true",
pad_x = unit(0.2, "in"), pad_y = unit(0.2, "in"),
height = unit(0.8, "cm"), width = unit(0.8, "cm"),
style = north_arrow_orienteering(
line_width = 0.5,
line_col = "black",
fill = c("black", "black"),
text_col = "black",
text_size = 6)) +
ggtitle("Sound Locations and Basins in Northwest Washington") +
theme_minimal() +
theme(
legend.position = c(0.2, 0.24),
legend.background = element_rect(fill = alpha("white", 0.8), color = "black"),
legend.title = element_blank(),
legend.text = element_text(size = 7),
legend.key.size = unit(0.3, "cm"),
legend.spacing.y = unit(0.15, "cm")
)
10 · Export the map
ggsave("nw_washington_final_map.png", plot = map_plot,
width = 8, height = 6, dpi = 300)
Saves a high-resolution PNG of the final figure.