Title: | Create a Magnified Inset of Part of a "Ggplot" Object |
---|---|
Description: | Creates a magnified inset of a ggplot, with projection lines and borders around the target area and inset, plus optional shadow. Rectangular, elliptical or arbitrary regions can be magnified. Works with facets and maps. Geoms can optionally be recomputed within the inset area. |
Authors: | David Hugh-Jones [aut, cre] |
Maintainer: | David Hugh-Jones <[email protected]> |
License: | MIT + file LICENSE |
Version: | 0.4.1 |
Built: | 2024-08-23 05:19:09 UTC |
Source: | https://github.com/hughjonesd/ggmagnify |
geom_magnify()
creates a magnified inset of part of a ggplot. Optional
borders are drawn around the target and inset, along with projection lines
from one to the other. from
gives the location of the target area,
and to
gives the location of the inset. Usually, these are specified as
c(xmin, xmax, ymin, ymax)
.
geom_magnify( mapping = NULL, data = NULL, stat = StatMagnify, position = "identity", ..., shape = c("rect", "ellipse", "outline"), expand = 0.1, aspect = c("free", "fixed"), axes = "", proj = c("facing", "corresponding", "single"), shadow = FALSE, corners = 0, colour = "black", linetype = 1, target.linetype = linetype, inset.linetype = linetype, proj.linetype = 2, alpha = 1, linewidth = 0.4, proj.fill = NULL, plot = NULL, shadow.args = list(sigma = 5, colour = "grey40", x_offset = 5, y_offset = 5), recompute = FALSE, scale.inset = 1, proj.combine = TRUE, na.rm = FALSE, inherit.aes = TRUE ) geom_magnify_tile( mapping = NULL, data = NULL, stat = StatMagnifyTile, position = "identity", ..., shape = c("rect", "ellipse", "outline"), expand = 0.1, aspect = c("free", "fixed"), axes = "", proj = "facing", shadow = FALSE, corners = 0, colour = "black", linetype = 1, target.linetype = linetype, inset.linetype = linetype, proj.linetype = 2, alpha = 1, linewidth = 0.4, proj.fill = NULL, plot = NULL, shadow.args = list(sigma = 5, colour = "grey40", x_offset = 5, y_offset = 5), recompute = FALSE, scale.inset = 1, proj.combine = TRUE, na.rm = FALSE, inherit.aes = FALSE )
geom_magnify( mapping = NULL, data = NULL, stat = StatMagnify, position = "identity", ..., shape = c("rect", "ellipse", "outline"), expand = 0.1, aspect = c("free", "fixed"), axes = "", proj = c("facing", "corresponding", "single"), shadow = FALSE, corners = 0, colour = "black", linetype = 1, target.linetype = linetype, inset.linetype = linetype, proj.linetype = 2, alpha = 1, linewidth = 0.4, proj.fill = NULL, plot = NULL, shadow.args = list(sigma = 5, colour = "grey40", x_offset = 5, y_offset = 5), recompute = FALSE, scale.inset = 1, proj.combine = TRUE, na.rm = FALSE, inherit.aes = TRUE ) geom_magnify_tile( mapping = NULL, data = NULL, stat = StatMagnifyTile, position = "identity", ..., shape = c("rect", "ellipse", "outline"), expand = 0.1, aspect = c("free", "fixed"), axes = "", proj = "facing", shadow = FALSE, corners = 0, colour = "black", linetype = 1, target.linetype = linetype, inset.linetype = linetype, proj.linetype = 2, alpha = 1, linewidth = 0.4, proj.fill = NULL, plot = NULL, shadow.args = list(sigma = 5, colour = "grey40", x_offset = 5, y_offset = 5), recompute = FALSE, scale.inset = 1, proj.combine = TRUE, na.rm = FALSE, inherit.aes = FALSE )
mapping , data , stat , position , ... , na.rm
|
See e.g. |
shape |
Shape of the area to be magnified. |
expand |
Number. Expand the target area and inset proportionally by this amount. |
aspect |
String. |
axes |
String. Which axes to plot in the inset? |
proj |
String. What style of projection lines to draw? |
shadow |
Logical. Draw a shadow behind the inset plot? Requires the "ggfx" package. |
corners |
Numeric between 0 and 1. Radius of rounded corners for the
target area and inset. Only used if |
linetype , colour , alpha , linewidth
|
Linetype, colour, alpha and linewidth for borders and projection lines. |
target.linetype , inset.linetype , proj.linetype
|
Linetypes
for specific components. Set to |
proj.fill |
Colour to fill between the projection lines. |
plot |
Ggplot object to plot in the inset. If |
shadow.args |
List. Arguments to |
recompute |
Logical. If |
scale.inset |
Length 1 or 2 numeric. Normally, exactly the target area is shown on the inset. Sometimes you may wish to rescale the plot in the inset. Use 2 numbers to scale width and height separately. |
proj.combine |
Logical. How to draw projection lines when more than
one polygon/map area is magnified? |
inherit.aes |
If |
geom_magnify understand the following aesthetics (required aesthetics are in bold):
from
to
from
and to
can be vectors of length 4, like list(xmin, xmax, ymin, ymax)
.
These specify the bottom left and top right corners of the target area to
magnify, and the area for the magnified inset. The lists can optionally be
named: list(xmin = 1, xmax = 2, ymin = 3, ymax = 4)
.
Note: very early versions of ggmagnify used a
different order of coordinates: list(xmin, ymin, xmax, ymax)
.
Alternatively, from
can be:
A data frame of points with two columns for x
and y
, or a grid::grob()
object. Points within the grob region (a polygon spanned by the data frame)
will be magnified. Points should be
on the same scale as the data, with default.units = "native"
in the grob.
shape
will be ignored.
A logical vector. Points in the data where from
is TRUE
will be
surrounded by a rectangle, ellipse or outline.
Normally you'll set from
and to
in the call to geom_magnify()
. You can
specify them as aesthetics, e.g. if you want different areas per facet. If
so, you may need to wrap them in a list()
to make sure they are length one
per row of data. Only the first row per panel is used. (To magnify multiple
areas in one panel, use multiple calls to geom_magnify()
.)
If shape = "ellipse"
an elliptical area is magnified. This may not include
all points within the target area given by from
.
If shape = "outline"
then a convex hull will be drawn around points in
the target area. This only works if you are using geom_point()
or some other
geom with aesthetics x
and y
. If you are plotting a map, then
"outline"
magnifies exactly the map features selected by from
.
proj = "corresponding"
or "facing"
draws projection lines from the
corners of the target to the corners of the inset.
"corresponding"
always projects each corner of the target to the same
corner of the inset.
"facing"
sometimes draws lines between facing corners, when this looks
cleaner.
For non-rectangular insets, "facing"
and "corresponding"
are the same.
"single"
draws a single line from the midpoint of facing sides.
To draw no lines, set proj.linetype = 0
.
geom_magnify()
uses masks. This requires R version 4.1.0 or higher, and
a graphics device that supports masking. If you are using knitr, you may have
luck with the ragg_png
device. If your device doesn't support masks,
only shape = "rect"
will work, and the plot inset will not be clipped
to the panel area.
R graphics devices are not very predictable. My current recommendations
are: ragg_png
for knitr; cairo_pdf
for PDF output; RStudio AGG
backend for interactive output. Your mileage may vary.
geom_magnify()
uses dark magic to deal with faceting. It may break with
older, or newer, versions of ggplot2. If you don't need faceting, and want
your code to be robust to upgrades, set options(ggmagnify.safe_mode = TRUE)
to use slightly less magic.
By design, geom_magnify()
replots the original plot using new limits. It
does not directly copy the target area pixels. The advantage is that you can
e.g. add axes, plot points at an appropriate size, zoom in on data that's
invisible in the main plot, or recompute derived graphics. If you want an
exact pixel-by-pixel copy, use a different tool.
geom_magnify()
may break with discrete scales. This is a limitation in
ggplot2 for now.
Find a bug? Report it at https://github.com/hughjonesd/ggmagnify/issues/.
geom_magnify_tile()
geom_magnify_tile()
is a version of geom_magnify()
which uses different
aesthetics. Set x
, width
, y
, height
and to_x
, to_width
to_y
,
to_height
to specify the target and inset location.
library(ggplot2) ggp <- ggplot(iris, aes(Sepal.Width, Sepal.Length, colour = Species)) + geom_point() + xlim(c(2, 6)) from <- list(2.5, 3.5, 6, 7) to <- list(4, 6, 5, 7) # Basic magnification ggp + geom_magnify(from = from, to = to) # Convex hull of points ggp + geom_magnify(aes(from = Species == "setosa"), to = c(3, 5, 6, 8), shape = "outline") # Order matters # `geom_magnify()` stores the plot when it is added to it: ggp + scale_color_brewer() + geom_magnify(from = from, to = to) # This will print the inset without the new scale: ggp + geom_magnify(from = from, to = to) + scale_color_brewer() # For more examples see https://github.com/hughjonesd/ggmagnify
library(ggplot2) ggp <- ggplot(iris, aes(Sepal.Width, Sepal.Length, colour = Species)) + geom_point() + xlim(c(2, 6)) from <- list(2.5, 3.5, 6, 7) to <- list(4, 6, 5, 7) # Basic magnification ggp + geom_magnify(from = from, to = to) # Convex hull of points ggp + geom_magnify(aes(from = Species == "setosa"), to = c(3, 5, 6, 8), shape = "outline") # Order matters # `geom_magnify()` stores the plot when it is added to it: ggp + scale_color_brewer() + geom_magnify(from = from, to = to) # This will print the inset without the new scale: ggp + geom_magnify(from = from, to = to) + scale_color_brewer() # For more examples see https://github.com/hughjonesd/ggmagnify
Create a grob from a subset of sf data
grob_where(where, sf, crs = NULL)
grob_where(where, sf, crs = NULL)
where |
Logical condition to be evaluated in |
sf |
An object of class sf. |
crs |
Optional coordinate reference system. |
A grid::grob()
which you can pass to from
.
library(ggplot2) if (requireNamespace("sf", quietly = TRUE) && requireNamespace("maps", quietly = TRUE)) { usa <- sf::st_as_sf(maps::map("state", fill=TRUE, plot = FALSE)) texas <- grob_where(ID == "texas", usa, crs = sf::st_crs(4326)) ggplot(usa) + coord_sf(crs = sf::st_crs(4326)) + geom_sf() + geom_magnify(from = texas, to = c(-90, -70, 25, 35), colour = "red", aspect = "fixed", expand = 0) }
library(ggplot2) if (requireNamespace("sf", quietly = TRUE) && requireNamespace("maps", quietly = TRUE)) { usa <- sf::st_as_sf(maps::map("state", fill=TRUE, plot = FALSE)) texas <- grob_where(ID == "texas", usa, crs = sf::st_crs(4326)) ggplot(usa) + coord_sf(crs = sf::st_crs(4326)) + geom_sf() + geom_magnify(from = texas, to = c(-90, -70, 25, 35), colour = "red", aspect = "fixed", expand = 0) }
Default elements to blank in the ggmagnify inset
inset_blanks(..., axes)
inset_blanks(..., axes)
... |
Character vector of extra elements to blank. |
axes |
String. Which axes to plot in the inset? |
A character vector.
Use inset_theme()
to add a suitable theme to a manually-created inset
plot.
inset_theme( blank = inset_blanks(axes = axes), axes, margin = if (axes == "") 0 else 8 )
inset_theme( blank = inset_blanks(axes = axes), axes, margin = if (axes == "") 0 else 8 )
blank |
Character vector of theme elements to blank. See |
axes |
String. Which axes to plot in the inset? |
margin |
Margin around the plot. See |
A ggplot theme object
library(ggplot2) ggp <- ggplot(iris, aes(Sepal.Width, Sepal.Length, colour = Species)) + geom_point() + xlim(c(2, 6)) from <- list(2.5, 3.5, 6, 7) to <- list(4, 6, 5, 7) inset <- ggp + geom_density2d() + inset_theme(axes = "") ggp + geom_magnify(from = from, to = to, plot = inset)
library(ggplot2) ggp <- ggplot(iris, aes(Sepal.Width, Sepal.Length, colour = Species)) + geom_point() + xlim(c(2, 6)) from <- list(2.5, 3.5, 6, 7) to <- list(4, 6, 5, 7) inset <- ggp + geom_density2d() + inset_theme(axes = "") ggp + geom_magnify(from = from, to = to, plot = inset)
Helper functions to find rectangles or convex hulls of data
rect_around(x, y, data = NULL, expand = 0) hull_around(x, y, data = NULL, expand = 0)
rect_around(x, y, data = NULL, expand = 0) hull_around(x, y, data = NULL, expand = 0)
x , y
|
Unquoted names or expressions |
data |
A data frame |
expand |
Amount to expand the data around its midpoint. Default is 10 per cent. |
rect_around()
returns a list with names xmin
, xmax
, ymin
,
and ymax
. hull_around()
returns a data frame with columns x
and y
.
library(ggplot2) to <- c(2, 4.5, 6, 8) setosas <- iris[iris$Species == "setosa", ] rect_around(Sepal.Width, Sepal.Length, data = setosas) hull_around(Sepal.Width, Sepal.Length, data = setosas)
library(ggplot2) to <- c(2, 4.5, 6, 8) setosas <- iris[iris$Species == "setosa", ] rect_around(Sepal.Width, Sepal.Length, data = setosas) hull_around(Sepal.Width, Sepal.Length, data = setosas)