Cropping {ggmap} rasters with {terra} to make beautiful maps
Combining the feautres of {ggmap}, {osmdata}, {terra} and {tidyterra}
Maps
[ggmap}
{osmdata}
{terra}
{tidyterra}
Raster
Author
Aditya Dahiya
Published
March 10, 2025
Loading Libraries
Code
# Data wrangling & visualizationlibrary(tidyverse) # Data manipulation & visualization# Spatial data handlinglibrary(sf) # Import, export, and manipulate vector datalibrary(terra) # Import, export, and manipulate raster data# ggplot2 extensionslibrary(tidyterra) # Helper functions for using terra with ggplot2# Getting raster tileslibrary(ggmap) # Getting map raster tileslibrary(osmdata) # Get Open Street Maps# Final plot toolslibrary(scales) # Nice Scales for ggplot2library(fontawesome) # Icons display in ggplot2library(ggtext) # Markdown text in ggplot2library(showtext) # Display fonts in ggplot2library(patchwork) # Composing Plotsbts =12# Base Text Sizesysfonts::font_add_google("Roboto Condensed", "body_font")sysfonts::font_add_google("Oswald", "title_font")sysfonts::font_add_google("Saira Extra Condensed", "caption_font")showtext::showtext_auto()# A base Colourbg_col <-"white"seecolor::print_color(bg_col)# Colour for highlighted texttext_hil <-"grey30"seecolor::print_color(text_hil)# Colour for the texttext_col <-"grey20"seecolor::print_color(text_col)theme_set(theme_minimal(base_size = bts,base_family ="body_font" ) +theme(text =element_text(colour ="grey30",lineheight =0.3,margin =margin(0,0,0,0, "pt") ),plot.title =element_text(hjust =0.5 ),plot.subtitle =element_text(hjust =0.5 ) ))# Caption stuff for the plotsysfonts::font_add(family ="Font Awesome 6 Brands",regular = here::here("docs", "Font Awesome 6 Brands-Regular-400.otf"))github <-""github_username <-"aditya-dahiya"xtwitter <-""xtwitter_username <-"@adityadahiyaias"social_caption_1 <- glue::glue("<span style='font-family:\"Font Awesome 6 Brands\";'>{github};</span> <span style='color: {text_hil}'>{github_username} </span>")social_caption_2 <- glue::glue("<span style='font-family:\"Font Awesome 6 Brands\";'>{xtwitter};</span> <span style='color: {text_hil}'>{xtwitter_username}</span>")plot_caption <-paste0("**Data**: StadiaMaps & Open Street Maps"," | **Code:** ", social_caption_1, " | **Graphics:** ", social_caption_2 )rm(github, github_username, xtwitter, xtwitter_username, social_caption_1, social_caption_2)
Getting, cropping, masking and plotting raster maps
This code leverages multiple R packages to create a detailed map of London Boroughs, integrating rasterized map tiles with spatial vector data. The {sf} package is used to obtain and manipulate the bounding box of London Boroughs, while {spData} provides the spatial dataset. The {ggmap} package is used to fetch base map tiles from Stamen Maps via get_stadiamap(), and {terra} functions like rast(), crop(), and mask() are applied to process and refine these tiles. The map visualization is built using {ggplot2}, with additional enhancements from {ggrepel} for labeling borough names, {paletteer} for colour scaling, and {ggthemes} for theming. The final visualization overlays London Boroughs on the map tiles, applying transparency and borders for clarity, and saves the output using {here}.
Code
# Obtain the bounding box of London Boroughslondon_bbox <- sf::st_bbox(spData::lnd)# A bounding box in the format c(lowerleftlon, lowerleftlat, upperrightlon, upperrightlat)london_bbox <-c(left = london_bbox$xmin,right = london_bbox$xmax,bottom = london_bbox$ymin,top = london_bbox$ymax)names(london_bbox) <-c("left", "right", "bottom", "top")# Getting London Boroughs Datadf <- spData::lnd |>st_transform("EPSG:4326")# Register stadia maps API key# register_stadiamaps("Your-Key-Here")# Getting the map tiles# london_base1 <- get_stadiamap(# bbox = london_bbox,# zoom = 11,# maptype = "stamen_toner_lines"# )london_base2 <-get_stadiamap(bbox = london_bbox,zoom =11,maptype ="stamen_toner_background")# Convert {ggmap} object into a SpatRasterlondon_base3 <- london_base2 |>rast() |>crop(df) |>mask(df)# Starting with base map tilesg <-ggplot() +# Plotting the cropped raster mapgeom_spatraster_rgb(data = london_base3,maxcell =Inf,alpha =0.7 ) +# Plotting the London boroughsgeom_sf(data = df,aes(fill = NAME),alpha =0.1,linewidth =0.8,colour =alpha("white", 0.5) ) + paletteer::scale_fill_paletteer_d("palettesForR::Tango") +# Plotting overall border of London Citygeom_sf(data = df |>st_geometry() |>st_union(),colour = text_col,linewidth =0.3,fill =NA ) +# Plotting names of London Boroughs on top of the geom_sf ggrepel::geom_label_repel(data = df,aes(label = NAME, geometry = geometry, size = HECTARES),fill =alpha("white", 0.5),colour = text_col,family ="caption_font",fontface ="bold",label.size =unit(0, "pt"),stat ="sf_coordinates" ) +scale_size_continuous(range =c(5, 20)) +coord_sf(expand =FALSE) +# Labelslabs(title ="Boroughs of London",subtitle =str_wrap("Overlaying a {ggmap}'s Stamen Map (rasterized and cropped with {terra} functions, plotted with {tidyterra}) with an {sf} object of london boroughs (from {spData}), and writing names of Boroughs with {ggrepel}'s geom_label_repel() and stat = \"sf_coordinates\"", 90),caption = plot_caption ) +# Some theme elements ggthemes::theme_map(base_size = bts,base_family ="body_font" ) +theme(legend.position ="none",plot.title =element_text(size =4* bts,margin =margin(30,0,10,0, "pt"),hjust =0.5 ),plot.subtitle =element_text(margin =margin(0,0,0,0, "pt"),lineheight =0.3,size = bts *1.4,hjust =0.5 ),plot.caption =element_textbox(margin =margin(0,0,20,0, "pt"),hjust =0.5,halign =0.5,family ="caption_font" ),plot.margin =margin(0,-10,0,-10, "pt") )ggsave(filename = here::here("geocomputation", "images", "ggmap_terra_1.png"),plot = g,height =3000,width =3000,units ="px",bg ="white")
Figure 1: A raster tile maps of Stamen Toner Background for London area, plotted at the base. London Boroughs’ borders plotted on top of it, along with names of the boroughs.
This code showcases the creation of a detailed administrative map of Vladivostok using a powerful combination of R spatial packages. The workflow begins by retrieving administrative boundary data via the osmdata package, then processes these geometries using sf for spatial operations. The map incorporates a stylish dark basemap from Stadia Maps, accessed through ggmap, which is then carefully cropped and masked to the city boundaries using terra functions. The visualization layer, built with ggplot2, combines the raster basemap with vector boundaries and elegantly positioned labels using ggrepel. The code demonstrates a sophisticated integration of multiple spatial data processing techniques—from acquisition to transformation to visualization—resulting in a professional-quality map that highlights Vladivostok’s administrative regions with both Russian and English labels. The approach illustrates modern R spatial data visualization practices, combining the strengths of multiple packages to handle different aspects of the geospatial workflow.
Figure 2: This visualization highlights the administrative districts of Vladivostok, Russia, with both Russian and English labels to enhance accessibility. The dark basemap creates a striking contrast with the white boundary lines, emphasizing the city’s complex geography where land meets the Sea of Japan. Each district is clearly delineated, revealing how Vladivostok’s urban structure has been shaped by its mountainous peninsula location and its historical importance as Russia’s major Pacific port.
Stylized Maps with {ggmap} and {osmdata}
This code extracts the boundary of the City of London from the spData package and processes it using sf functions. It defines a bounding box for the area and retrieves a watercolor-style basemap from get_stadiamap(). Using osmdata, historical sites within the City of London—such as castles, memorials, and ruins—are queried from OpenStreetMap. The extracted data is filtered, transformed, and plotted with ggplot2, overlaying the historical landmarks on the base map. Labels are added using ggrepel to improve readability. The final visualization is saved using ggsave().
Figure 3: Map of historical sites in the City of London, overlaid on a watercolor-style basemap. The visualization highlights key landmarks such as castles, monuments, and memorials, with point sizes indicating their type and significance.