Here's one (shoddy) way of doing this. I'm still a ggplot amateur... I had trouble drawing lines in cowplot between the two ggplot objects, so I assigned a new coordinate system for the resulting plot and manually defined the start and endpoints for lines. If anyone has suggestions for how to improve this, particularly for assigning the leader line coordinates programmatically, I'm all ears.
Inspiration from https://r-spatial.org/r/2018/10/25/ggplot2-sf-3.html and https://geocompr.github.io/post/2019/ggplot2-inset-maps/
library(sf)
library(spData)
library(ggplot2)
library(cowplot)
library(rcartocolor)
data("us_states", package = "spData")
north_carolina = read_sf(system.file("shape/nc.shp", package = "sf"))
us_states_2163 = st_transform(us_states, crs = 2163)
north_carolina_2163 = st_transform(north_carolina, crs = 2163)
north_carolina_2163_bb = st_as_sfc(st_bbox(north_carolina_2163))
mainbox <- st_bbox(north_carolina_2163)
# inset panel
inset = ggplot() +
geom_sf(data = us_states_2163, fill = "white") +
geom_sf(data = north_carolina_2163_bb, fill = NA, color = "yellow", size = 1.2) +
theme_void()
# main panel
main = ggplot() +
geom_sf(data = north_carolina_2163, aes(fill = BIR74)) +
scale_fill_carto_c(palette = "Mint") +
geom_sf(data = north_carolina_2163_bb, fill = NA, color = "yellow", size = 1.2) +
theme_void() +
theme(legend.position = "none")
# map
gg_inset_map1 = cowplot::ggdraw() +
coord_equal(xlim = c(0, 20), ylim = c(0, 20), expand = FALSE) +
annotation_custom(ggplotGrob(inset), xmin = 0, xmax = 10, ymin = 10, ymax = 20) +
annotation_custom(ggplotGrob(main), xmin = 0, xmax = 20, ymin = 0, ymax = 10) +
geom_segment(aes(x = 8.9, xend = 19, y = 14.4, yend = 9.2), color = "yellow", size = 1.2) +
geom_segment(aes(x = 7.5, xend = 1, y = 14.4, yend = 9.2), color = "yellow", size = 1.2)
E: I ran into this question and answer and thought it was relevant here. This is one approach to using the data within the grob to define the location of the lines. However, as the author of the answer points out, this is a "fiddly...one off solution." The answer I submitted is similar in that regard... and a lot less work than sifting through grob attributes...