| Title: | Inset Plots for Spatial Data Visualization |
|---|---|
| Description: | Tools for easily and flexibly creating 'ggplot2' maps with inset maps. One crucial feature of maps is that they have fixed coordinate ratios, i.e., they cannot be distorted, which makes it difficult to manually place inset maps. This package provides functions to automatically position inset maps based on user-defined parameters, making it extremely easy to create maps with inset maps with minimal code. |
| Authors: | Chao Kong [aut, cre, cph] (ORCID: <https://orcid.org/0000-0002-6404-6142>) |
| Maintainer: | Chao Kong <[email protected]> |
| License: | GPL (>= 2) |
| Version: | 1.4.0 |
| Built: | 2026-06-02 10:39:53 UTC |
| Source: | https://github.com/fncokg/insetplot |
insetplot lets you create ggplot2 maps with inset maps easily and flexibly. It handles spatial configuration, aspect ratios, and plot composition automatically.
Build a configuration with config_insetmap and inset_spec by specifying necessary parameters (position and size).
Pass your ggplot object to with_inset to generate the composed figure.
Save the final plot with ggsave_inset to maintain correct aspect ratio.
inset_spec: Define bbox, position (loc or loc_left/loc_bottom),
and size (prefer scale_factor; or provide one of width/height).
config_insetmap: Create and store the configuration.
with_inset: Crop each subplot, compose subplots and calculate sizes and positions automatically.
ggsave_inset: Save with the correct aspect ratio derived from with_inset,
with optional ratio_scale for fine-tuning.
library(sf)
library(ggplot2)
library(insetplot)
nc <- st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE)
# Approach 1: shared base plot for all subplots
config_insetmap(
bbox = st_bbox(nc),
specs = list(
inset_spec(main = TRUE),
inset_spec(
xmin = -84, xmax = -75, ymin = 33, ymax = 37,
loc = "left bottom", scale_factor = 0.5
)
)
)
base_map <- ggplot(nc, aes(fill = AREA)) +
geom_sf() +
scale_fill_viridis_c() +
guides(fill = "none") +
theme_void()
p <- with_inset(base_map)
# Approach 2: provide custom plots in each spec
config_insetmap(
bbox = st_bbox(nc),
specs = list(
inset_spec(main = TRUE, plot = base_map),
inset_spec(
xmin = -84, xmax = -75, ymin = 33, ymax = 37,
loc = "left bottom", scale_factor = 0.5,
plot = base_map + ggtitle("Detail")
)
)
)
p <- with_inset() # plot argument is optional here
# Save with the correct aspect ratio
ggsave_inset("map.png", p, width = 10)
Maintainer: Chao Kong [email protected] (ORCID) [copyright holder]
inset_spec, config_insetmap,
with_inset, ggsave_inset, map_border,
last_insetcfg
Create and store an inset configuration used by with_inset(). The
configuration contains subplot specifications, aspect ratio of the main plot,
CRS settings, and border appearance for insets.
config_insetmap( specs, to_crs = sf::st_crs("EPSG:4326"), from_crs = sf::st_crs("EPSG:4326"), bbox = NULL, lims_method = "cross", border_args = list() )config_insetmap( specs, to_crs = sf::st_crs("EPSG:4326"), from_crs = sf::st_crs("EPSG:4326"), bbox = NULL, lims_method = "cross", border_args = list() )
specs |
A non-empty list of |
to_crs |
Coordinate reference system to transform to, passed to
|
from_crs |
Coordinate reference system of bboxes in |
bbox |
An optional bounding box (compatible with |
lims_method |
Method to calculate limits from bbox. See also |
border_args |
A list of named arguments passed to |
An object of class insetcfg. Also stored as the last configuration, retrievable via last_insetcfg().
inset_spec(), with_inset(), last_insetcfg()
library(sf) nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) config_insetmap( bbox = sf::st_bbox(nc), specs = list( inset_spec(main = TRUE), inset_spec( xmin = -84, xmax = -75, ymin = 33, ymax = 37, loc = "left bottom", scale_factor = 0.5 ) ) )library(sf) nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) config_insetmap( bbox = sf::st_bbox(nc), specs = list( inset_spec(main = TRUE), inset_spec( xmin = -84, xmax = -75, ymin = 33, ymax = 37, loc = "left bottom", scale_factor = 0.5 ) ) )
Computes spatial range and aspect ratio metrics from a bounding box.
get_bbox_features(bbox)get_bbox_features(bbox)
bbox |
A named numeric vector with elements |
A list with elements:
x_range |
Width (xmax - xmin) of the bounding box |
y_range |
Height (ymax - ymin) of the bounding box |
xy_ratio |
Aspect ratio (x_range / y_range) |
# Create a sample bounding box bbox <- c(xmin = -84, xmax = -75, ymin = 33, ymax = 37) # Extract width, height, and aspect ratio features <- get_bbox_features(bbox) features # Access individual components features$x_range features$y_range features$xy_ratio# Create a sample bounding box bbox <- c(xmin = -84, xmax = -75, ymin = 33, ymax = 37) # Extract width, height, and aspect ratio features <- get_bbox_features(bbox) features # Access individual components features$x_range features$y_range features$xy_ratio
Calculates the overall bounding box that encompasses all provided spatial shapes.
get_widest_bbox(shapes)get_widest_bbox(shapes)
shapes |
A list of sf objects. |
A named numeric vector with elements: ymin, xmin, xmax, ymax
representing the union of all input bounding boxes.
library(sf) # Load sample data nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) # Get the bounding box of the entire dataset bbox <- get_widest_bbox(list(nc)) bboxlibrary(sf) # Load sample data nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) # Get the bounding box of the entire dataset bbox <- get_widest_bbox(list(nc)) bbox
A wrapper around ggplot2::ggsave() that automatically calculates the output
dimensions based on the full ratio defined in the inset configuration.
This ensures the saved image maintains the correct aspect ratio for proper
rendering of all subplots.
ggsave_inset( filename, plot = last_plot(), device = NULL, path = NULL, scale = 1, width = NA, height = NA, ..., ratio_scale = 1, .cfg = last_insetcfg() )ggsave_inset( filename, plot = last_plot(), device = NULL, path = NULL, scale = 1, width = NA, height = NA, ..., ratio_scale = 1, .cfg = last_insetcfg() )
filename |
Filename to save the plot to. Passed directly to |
plot |
The plot to save. Default |
device |
Device to save to (e.g., "png", "pdf"). Default NULL (inferred from filename). |
path |
Directory path for saving. Default NULL (current directory). |
scale |
Scaling factor. Default 1. |
width, height
|
Width and height in inches. You only need to provide one; the other will be calculated automatically. Default NA. |
... |
Additional arguments passed to |
ratio_scale |
Optional scaling factor to adjust the aspect ratio. Default 1.0. Use when there are extra elements (e.g., titles, legends) that affect the overall image dimensions. For example, set to 1.1 for extra width when a legend is present on the left/right side. |
.cfg |
An inset configuration (class |
All parameters are the same as ggplot2::ggsave(), except that you only need to
provide either width or height, and the other dimension will be calculated
automatically to match the aspect ratio defined in the inset configuration.
The function automatically calculates width and height based on .cfg$main_ratio
to maintain aspect ratio consistency. If both width and height are provided,
a warning is issued as the output aspect ratio may not match the configuration.
NULL (invisibly). Saves the plot to disk.
library(sf) library(ggplot2) nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) config_insetmap( bbox = st_bbox(nc), specs = list( inset_spec(main = TRUE), inset_spec( xmin = -84, xmax = -75, ymin = 33, ymax = 37, loc = "left bottom", width = 0.3 ) ) ) base <- ggplot(nc, aes(fill = AREA)) + geom_sf() + scale_fill_viridis_c() + guides(fill = "none") + theme_void() with_inset(base) # Save with automatically calculated height ggsave_inset(paste0(tempdir(), "/inset_map.png"), width = 10)library(sf) library(ggplot2) nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) config_insetmap( bbox = st_bbox(nc), specs = list( inset_spec(main = TRUE), inset_spec( xmin = -84, xmax = -75, ymin = 33, ymax = 37, loc = "left bottom", width = 0.3 ) ) ) base <- ggplot(nc, aes(fill = AREA)) + geom_sf() + scale_fill_viridis_c() + guides(fill = "none") + theme_void() with_inset(base) # Save with automatically calculated height ggsave_inset(paste0(tempdir(), "/inset_map.png"), width = 10)
Define the spatial extent and positioning for each subplot (main or inset).
inset_spec( xmin = NA, xmax = NA, ymin = NA, ymax = NA, loc = "right bottom", loc_left = NA, loc_bottom = NA, width = NA, height = NA, scale_factor = NA, main = FALSE, plot = NULL )inset_spec( xmin = NA, xmax = NA, ymin = NA, ymax = NA, loc = "right bottom", loc_left = NA, loc_bottom = NA, width = NA, height = NA, scale_factor = NA, main = FALSE, plot = NULL )
xmin, xmax, ymin, ymax
|
Numeric bbox coordinates for the subplot in the coordinate system of the data, normally longitude/latitude. Any may be NA and will be inferred from the overall extent if possible. |
loc |
A convenience string like "left bottom", "center top", etc. to specify
the position of the inset on the full canvas. Horizontal position must be one of
"left", "center", or "right"; vertical position must be one of "bottom", "center", or "top".
Ignored when |
loc_left, loc_bottom
|
Numbers in [0, 1] for the bottom-left position of the inset on the full canvas. |
width, height
|
Numeric values in (0, 1] for the size of the inset.
It is recommended to provide only one of these; the other dimension will be
inferred to maintain the aspect ratio of the spatial extent. It is also
recommended to use |
scale_factor |
Numeric value in (0, Inf) indicating the scale of the inset
relative to the main plot. If not NA, the inset's width/height are
automatically derived from the spatial ranges relative to the main plot
multiplied by this factor. For example, the scale of the main plot is 1:10,000,
the inset's dimensions will be 1:20,000 if |
main |
Logical. TRUE marks this spec as the main plot (exactly one). Default FALSE. |
plot |
Optional ggplot object to use for this spec instead of the base
plot passed to |
A list with elements bbox, loc_left, loc_bottom, width,
height, scale_factor, main, plot, hpos, and vpos. You do not
normally need to interact with this object directly; it is used internally.
specs <- list( # Create a main plot specification inset_spec(main = TRUE), # Create an inset plot specification with explicit dimensions inset_spec( xmin = -120, xmax = -100, ymin = 30, ymax = 50, loc = "right bottom", width = 0.3 ), # Create an inset with scale factor inset_spec( xmin = -120, xmax = -100, ymin = 30, ymax = 50, loc = "left bottom", scale_factor = 0.5 ) )specs <- list( # Create a main plot specification inset_spec(main = TRUE), # Create an inset plot specification with explicit dimensions inset_spec( xmin = -120, xmax = -100, ymin = 30, ymax = 50, loc = "right bottom", width = 0.3 ), # Create an inset with scale factor inset_spec( xmin = -120, xmax = -100, ymin = 30, ymax = 50, loc = "left bottom", scale_factor = 0.5 ) )
Retrieves the most recently created inset configuration object.
This is used internally by with_inset() when no configuration is explicitly provided.
last_insetcfg()last_insetcfg()
An inset configuration object of class insetcfg, or NULL if no
configuration has been set.
library(sf) # Load some spatial data nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) # Configure inset map config_insetmap( bbox = sf::st_bbox(nc), specs = list( inset_spec(main = TRUE), inset_spec( xmin = -84, xmax = -75, ymin = 33, ymax = 37, loc = "left bottom", width = 0.3 ) ) ) # Retrieve the configuration cfg <- last_insetcfg()library(sf) # Load some spatial data nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) # Configure inset map config_insetmap( bbox = sf::st_bbox(nc), specs = list( inset_spec(main = TRUE), inset_spec( xmin = -84, xmax = -75, ymin = 33, ymax = 37, loc = "left bottom", width = 0.3 ) ) ) # Retrieve the configuration cfg <- last_insetcfg()
Returns a small theme that draws a rectangular border around the plot area. Handy for visually separating inset plots from the main plot.
map_border(color = "black", linewidth = 1, fill = "white", ...)map_border(color = "black", linewidth = 1, fill = "white", ...)
color |
Border color. Default "black". |
linewidth |
Border line width. Default 1. |
fill |
Background fill color. Default "white". |
... |
Passed to |
A ggplot2 theme object to add to a ggplot with +.
library(ggplot2) ggplot(mtcars, aes(mpg, wt)) + geom_point() + map_border(color = "red", linewidth = 2)library(ggplot2) ggplot(mtcars, aes(mpg, wt)) + geom_point() + map_border(color = "red", linewidth = 2)
Build a combined plot using an inset configuration created by config_insetmap().
For each plot specification in the configuration, the function either uses the
provided spec$plot or the supplied plot parameter and adds spatial coordinates
via ggplot2::coord_sf() with the given bounding box. Non-main subplots receive
a border from map_border(). Insets are composed using patchwork::inset_element().
with_inset( plot = NULL, .cfg = last_insetcfg(), .as_is = FALSE, .return_details = FALSE )with_inset( plot = NULL, .cfg = last_insetcfg(), .as_is = FALSE, .return_details = FALSE )
plot |
Optional. Either:
NOTE: you SHOULD NOT pass |
.cfg |
An inset configuration (class "insetcfg") created by
|
.as_is |
Logical. If TRUE, return |
.return_details |
Logical. If FALSE (default), returns a combined plot with the main plot and inset layers. If TRUE, returns a list. See 'Value' section for details. |
If .return_details = FALSE, a ggplot object containing the main plot plus inset layers. If TRUE, a list with elements:
full |
The combined plot |
subplots |
Individual ggplot objects for each subplot |
subplot_layouts |
A |
main_ratio |
Width-to-height ratio of the main plot's data extent |
library(sf) library(ggplot2) nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) config_insetmap( bbox = st_bbox(nc), specs = list( inset_spec(main = TRUE), inset_spec( xmin = -82, xmax = -80.5, ymin = 35.5, ymax = 36, loc = "left bottom", scale_factor = 2 ) ) ) # Supply base plot for all subplots base <- ggplot(nc, aes(fill = AREA)) + geom_sf() + scale_fill_viridis_c() + guides(fill = "none") + theme_void() with_inset(base) # Or supply custom plots in each inset_spec, then call with_inset() without plot config_insetmap( bbox = st_bbox(nc), specs = list( inset_spec(main = TRUE, plot = base), inset_spec( xmin = -82, xmax = -80.5, ymin = 35.5, ymax = 36, loc = "left bottom", scale_factor = 2, plot = base # Each spec has its own plot ) ) ) with_inset() # plot parameter is optional nowlibrary(sf) library(ggplot2) nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) config_insetmap( bbox = st_bbox(nc), specs = list( inset_spec(main = TRUE), inset_spec( xmin = -82, xmax = -80.5, ymin = 35.5, ymax = 36, loc = "left bottom", scale_factor = 2 ) ) ) # Supply base plot for all subplots base <- ggplot(nc, aes(fill = AREA)) + geom_sf() + scale_fill_viridis_c() + guides(fill = "none") + theme_void() with_inset(base) # Or supply custom plots in each inset_spec, then call with_inset() without plot config_insetmap( bbox = st_bbox(nc), specs = list( inset_spec(main = TRUE, plot = base), inset_spec( xmin = -82, xmax = -80.5, ymin = 35.5, ymax = 36, loc = "left bottom", scale_factor = 2, plot = base # Each spec has its own plot ) ) ) with_inset() # plot parameter is optional now