Title: | Grammar Extensions to 'ggplot2' |
---|---|
Description: | Extensions to 'ggplot2' respecting the grammar of graphics paradigm. Geometries: geom_table(), geom_plot() and geom_grob() add insets to plots using native data coordinates, while geom_table_npc(), geom_plot_npc() and geom_grob_npc() do the same using "npc" coordinates through new aesthetics "npcx" and "npcy". Statistics: select observations based on 2D density. Positions: radial nudging away from a center point and nudging away from a line or curve; combined stacking and nudging; combined dodging and nudging. |
Authors: | Pedro J. Aphalo [aut, cre] |
Maintainer: | Pedro J. Aphalo <[email protected]> |
License: | GPL (>= 2) |
Version: | 0.5.8-1 |
Built: | 2024-08-29 06:39:21 UTC |
Source: | https://github.com/aphalo/ggpp |
Extensions to 'ggplot2' respecting the grammar of graphics paradigm. Geometries: geom_table(), geom_plot() and geom_grob() add insets to plots using native data coordinates, while geom_table_npc(), geom_plot_npc() and geom_grob_npc() do the same using "npc" coordinates through new aesthetics "npcx" and "npcy". Statistics: select observations based on 2D density. Positions: radial nudging away from a center point and nudging away from a line or curve; combined stacking and nudging; combined dodging and nudging.
Package 'ggpp' provides functions that extend the grammar of graphics as implemented in 'ggplot2'. It attempts to stay true to the original grammar and to respect the naming conventions used in 'ggplot2'.
Extensions provided:
Geoms adding support for plot, table and grob insets within the gramamr. Geoms using a parallel pseudo-scale based on native plot coordinates (npc) to allow annotations consistent with the grammar and so supporting facets and grouping. Geoms for annotations on the edges of the plotting area. Geom for easily drawing lines separating the quadrants of a plot.
Stats for filtering-out/filtering-in observations in regions of a panel or group where the density of observations is high. Statistics simultaneously computing summaries, optionally using different functions, along x and y. Stat computing quadrant counts.
Position functions implementing multi-directional nudging based on the data.
Scales. Pseudo-scales supporting npc coordinates for x and y.
Specializations of the ggplot()
generic accepting time series
objects of classes ts
and xts
as data argument.
We thank Kamil Slowikowski not only for
contributing ideas and code examples to this package but also for adding
new features to his package 'ggrepel' that allow new use cases for
stat_dens2d_labels()
, position_nudge_center()
,
position_nudge_line()
and position_nudge_to()
from this
package. This package includes code copied and/or modified from
that in package 'ggplot2'.
Maintainer: Pedro J. Aphalo [email protected] (ORCID)
Other contributors:
Kamil Slowikowski (ORCID) [contributor]
Michał Krassowski (ORCID) [contributor]
Daniel Sabanés Bové [contributor]
Stella Banjo [contributor]
Package 'ggplot2' documentation is available at
https://ggplot2.tidyverse.org/
Package 'ggplot2' source code at
https://github.com/tidyverse/ggplot2
Useful links:
Report bugs at https://github.com/aphalo/ggpp/issues
A revised version of annotate()
from package 'ggplot2' adding support
for npcx
and npcy
position aesthetics, allowing use of the
geometries defined in the current package such as geom_text_npc()
. It
also has a parameter label
that directly accepts data frames, ggplots
and grobs as arguments in addition to objects of atomic classes like
character. When package 'ggpmisc' is loaded this definition of
annotate()
overrides that in package 'ggplot2'.
annotate( geom, x = NULL, y = NULL, xmin = NULL, xmax = NULL, ymin = NULL, ymax = NULL, xend = NULL, yend = NULL, npcx = NULL, npcy = NULL, label = NULL, ..., na.rm = FALSE )
annotate( geom, x = NULL, y = NULL, xmin = NULL, xmax = NULL, ymin = NULL, ymax = NULL, xend = NULL, yend = NULL, npcx = NULL, npcy = NULL, label = NULL, ..., na.rm = FALSE )
geom |
character Name of geom to use for annotation. |
x , y , xmin , ymin , xmax , ymax , xend , yend , npcx , npcy
|
numeric Positioning aesthetics - you must specify at least one of these. |
label |
character, data.frame, ggplot or grob. |
... |
Other named arguments passed on to |
na.rm |
logical If |
Note that all position aesthetics are scaled (i.e., they will expand the limits of the plot so they are visible), but all other aesthetics are set. This means that layers created with this function will never affect the legend.
A plot layer instance.
To use the original definition of annotate()
after loading
package 'ggpmisc', use ggplot2::annotate()
.
p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point() # Works as ggplot2::annotate() p + annotate("text", x = 5, y = 32, label = "Some text") p + annotate("label", x = c(2, 5), y = c(15, 32), label = c("A", "B")) p + annotate("table", x = 5, y = 30, label = data.frame(A = 1:2, B = letters[1:2])) p + annotate("plot", x = 5.5, y = 34, label = p + theme_bw(9)) p + annotate("rect", xmin = 3, xmax = 4.2, ymin = 12, ymax = 21, alpha = .2) p + annotate("segment", x = 2.5, xend = 4, y = 15, yend = 25, colour = "blue") p + annotate("pointrange", x = 3.5, y = 20, ymin = 12, ymax = 28, colour = "red", size = 1.5) # But ggpmisc::annotate() also works with npcx and npcy pseudo-aesthetics p + annotate("label_npc", npcx = c(0.1, 0.9), npcy = c(0.1, 0.9), label = c("A", "B")) p + annotate("label_npc", npcx = 0.9, npcy = c(0.1, 0.9), label = c("A", "B")) p + annotate("text_npc", npcx = 0.9, npcy = 0.9, label = "Some text") p + annotate("text_npc", npcx = "right", npcy = "top", label = "Some text") p + annotate("table_npc", npcx = 0.9, npcy = 0.9, label = data.frame(A = 1:2, B = letters[1:2])) p + annotate("plot_npc", npcx = 1, npcy = 1, label = p + theme_bw(9)) p + annotate("plot_npc", npcx = c(0, 1), npcy = c(0, 1), label = list(p + theme_bw(9), p + theme_grey(9)), vp.width = 0.3, vp.height = 0.4)
p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point() # Works as ggplot2::annotate() p + annotate("text", x = 5, y = 32, label = "Some text") p + annotate("label", x = c(2, 5), y = c(15, 32), label = c("A", "B")) p + annotate("table", x = 5, y = 30, label = data.frame(A = 1:2, B = letters[1:2])) p + annotate("plot", x = 5.5, y = 34, label = p + theme_bw(9)) p + annotate("rect", xmin = 3, xmax = 4.2, ymin = 12, ymax = 21, alpha = .2) p + annotate("segment", x = 2.5, xend = 4, y = 15, yend = 25, colour = "blue") p + annotate("pointrange", x = 3.5, y = 20, ymin = 12, ymax = 28, colour = "red", size = 1.5) # But ggpmisc::annotate() also works with npcx and npcy pseudo-aesthetics p + annotate("label_npc", npcx = c(0.1, 0.9), npcy = c(0.1, 0.9), label = c("A", "B")) p + annotate("label_npc", npcx = 0.9, npcy = c(0.1, 0.9), label = c("A", "B")) p + annotate("text_npc", npcx = 0.9, npcy = 0.9, label = "Some text") p + annotate("text_npc", npcx = "right", npcy = "top", label = "Some text") p + annotate("table_npc", npcx = 0.9, npcy = 0.9, label = data.frame(A = 1:2, B = letters[1:2])) p + annotate("plot_npc", npcx = 1, npcy = 1, label = p + theme_bw(9)) p + annotate("plot_npc", npcx = c(0, 1), npcy = c(0, 1), label = list(p + theme_bw(9), p + theme_grey(9)), vp.width = 0.3, vp.height = 0.4)
A dataset containing the measurements on 350 birch seedlings.
birch.df birch_dw.df
birch.df birch_dw.df
A data.frame
object with 350 rows and 8 variables.
A data.frame
object with 700 rows and 5 variables.
The data are for seedlings grown in trays with cells or containers of two different volumes. For each of these types of trays, all cells, 1/2 of the cells or 1/4 of the cells contained seedlings. Root-collar diameter (mm), height (cm), dry mass (mg) of stems and roots. Measurements done at the end of the first growing season, after leaf fall.
Aphalo, P. J. and Rikala, R. (2003) Field performance of silver-birch planting-stock grown at different spacing and in containers of different volume. New Forests, 25:93-108. doi:10.1023/A:1022618810937.
Other Plant growth and morphology data:
ivy.df
colnames(birch.df) head(birch.df) colnames(birch_dw.df) head(birch_dw.df)
colnames(birch.df) head(birch.df) colnames(birch_dw.df) head(birch_dw.df)
Translate and/or compute NPC (Normalised Parent Coordinates) for use with
aesthetics x
and y
.
compute_npcx(x, group = 1L, h.step = 0.1, margin.npc = 0.05, each.len = 1) compute_npcy(y, group = 1L, v.step = 0.1, margin.npc = 0.05, each.len = 1) as_npcx(x, ...) as_npcy(y, ...) compute_npc(a, margin.npc = 0.05) as_npc(a, margin.npc = 0.05)
compute_npcx(x, group = 1L, h.step = 0.1, margin.npc = 0.05, each.len = 1) compute_npcy(y, group = 1L, v.step = 0.1, margin.npc = 0.05, each.len = 1) as_npcx(x, ...) as_npcy(y, ...) compute_npc(a, margin.npc = 0.05) as_npc(a, margin.npc = 0.05)
x |
numeric or if character, one of "right", "left", "maximum", "minimum", "centre", "center" or "middle". |
group |
integer vector, ggplot's group id. Used to shift coordinates to avoid overlaps. |
h.step , v.step
|
numeric [0..1] The step size for shifting coordinates in npc units. Usually << 1. |
margin.npc |
numeric [0..1] The margin added towards the nearest plotting area edge when converting character coordinates into npc. Usually << 1. |
each.len |
integer The number of steps per group. |
y |
numeric or if character, one of "top", "bottom", "maximum", "minimum", "centre", "center" or "middle". |
... |
named arguments passed to |
a |
numeric or if character, one of "right", "left", "top", "maximum", "minimum", "bottom", "centre", "center" or "middle". |
Functions compute_npcx
and compute_npcy
convert
character-encoded positions to npc units and shift positions to avoid
overlaps when grouping is active. If numeric, they validate the npc values.
Function compute_npcx
does the translation either for both x
and y
aesthetics, but does not implement a shift for grpups.
Functions as_npcx()
, as_npcy()
and as_npc()
are
wrappers on these functions that return the value as objects of class
"AsIs"
so that in 'ggplot2' >= 3.5.0 they can be used with any layer
function.
These functions use NPC (Normalised Parent Coordinates) instead of data coordinates. They translate named positions into numeric values in [0..1] and they can also shift the position according to the group, e.g., for each increase in the group number displace the position inwards or outwards, by a user-supplied distance. They make it possible to set automatically set default positions for grouped text labels.
Out of bounds numeric values are constrained to [0..1]. Unrecognized
character values are silently converted into NA_integer_
.
A numeric vector with values in the range [0..1] representing npc coordinates.
The as_npc() functions make it easier the use of NPC coordinates with 'ggplot2' >= 3.5.0. The _compute_ functions are used by several layer functions in packages 'ggpp' and 'ggpmisc', are compatible with 'ggplot2' <= 3.4.4 and can be useful to developers of other 'ggplot2' extensions.
compute_npcx("right") compute_npcx(c("left", "right")) compute_npcx(c("minimum", "maximum")) compute_npcx(c("left", "right"), margin.npc = 0) compute_npcy("bottom") compute_npcy("bottom", group = 1L:3L) compute_npcy("bottom", group = 1L:3L, v.step = 0.2) compute_npcy("bottom", group = 2L) compute_npcx(0.5) compute_npcx(1) compute_npcx(-2) as_npc("right") class(as_npc("right")) class(compute_npcx("right"))
compute_npcx("right") compute_npcx(c("left", "right")) compute_npcx(c("minimum", "maximum")) compute_npcx(c("left", "right"), margin.npc = 0) compute_npcy("bottom") compute_npcy("bottom", group = 1L:3L) compute_npcy("bottom", group = 1L:3L, v.step = 0.2) compute_npcy("bottom", group = 2L) compute_npcx(0.5) compute_npcx(1) compute_npcx(-2) as_npc("right") class(as_npc("right")) class(compute_npcx("right"))
Chose between a pair of contrasting dark and light colors based on a weighted mean of RGB channels of a color. This function implements a simple approach to the choice for a color of a plot element to ensure it is visible against a background color.
dark_or_light( colors, threshold = 0.45, dark.color = "black", light.color = "white" )
dark_or_light( colors, threshold = 0.45, dark.color = "black", light.color = "white" )
colors |
A vector of color definitions or color names in the background. |
threshold |
numeric A value of luminance in [0..1] indicating the switch point between dark and light background. |
dark.color , light.color
|
A color definition or color name to return as dark and light colors to contrast light and dark backgrounds respectively. |
The switch between dark and light color is based on a quick and dirty approximation of the luminance of colors computed from RGB values. This easily computed approximation seems to work well enough. The default threshold chosen for a switch between black and white may need to be adjusted for other pairs of colors. Graphic devices can differ in the color spaces they support, but this is unlikely to affect the choice between black and white or other pairs of colors with large differences in luminance.
The current implementation of dark_or_light()
ignores
alpha
, the transparency component, of all its arguments.
dark_or_light("yellow") dark_or_light("darkblue") dark_or_light(c("darkblue", "yellow", "red")) dark_or_light("#FFFFFF") dark_or_light("#FFFFFF", dark.color = "darkblue", light.color = "lightgrey") dark_or_light("#000000", dark.color = "darkblue", light.color = "lightgrey")
dark_or_light("yellow") dark_or_light("darkblue") dark_or_light(c("darkblue", "yellow", "red")) dark_or_light("#FFFFFF") dark_or_light("#FFFFFF", dark.color = "darkblue", light.color = "lightgrey") dark_or_light("#000000", dark.color = "darkblue", light.color = "lightgrey")
geom_grob
and geom_grob_npc
add Grobs as insets to the ggplot
using syntax similar to that of geom_text
,
geom_text_s
and geom_text_npc
.
In most respects they behave as any other ggplot geometry: they add a layer
containing one or more grobs and grouping and faceting works as usual. The
most common use of geom_grob
is to add data labels that are graphical
objects rather than text. geom_grob_npc
is used to add grobs
as annotations to plots, but contrary to layer function annotate()
,
geom_grob_npc
is data driven and respects grouping and facets,
thus plot insets can differ among panels. Of these two geoms only
geom_grob
supports the plotting of segments, as
geom_grob_npc
uses a coordinate system that is unrelated
to data units and data.
geom_grob( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., nudge_x = 0, nudge_y = 0, default.colour = "black", default.color = default.colour, colour.target = "segment", color.target = colour.target, default.alpha = 1, alpha.target = "segment", add.segments = TRUE, box.padding = 0.25, point.padding = 1e-06, segment.linewidth = 0.5, min.segment.length = 0, arrow = NULL, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE ) geom_grob_npc( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE )
geom_grob( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., nudge_x = 0, nudge_y = 0, default.colour = "black", default.color = default.colour, colour.target = "segment", color.target = colour.target, default.alpha = 1, alpha.target = "segment", add.segments = TRUE, box.padding = 0.25, point.padding = 1e-06, segment.linewidth = 0.5, min.segment.length = 0, arrow = NULL, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE ) geom_grob_npc( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific dataset - only needed if you want to override the plot defaults. |
stat |
The statistical transformation to use on the data for this layer, as a string. |
position |
Position adjustment, either as a string, or the result of a call to a position adjustment function. |
... |
other arguments passed on to |
nudge_x , nudge_y
|
Horizontal and vertical adjustments to nudge the
starting position of each text label. The units for |
default.colour , default.color
|
A colour definition to use for elements not targeted by the colour aesthetic. |
colour.target , color.target
|
A vector of character strings; |
default.alpha |
numeric in [0..1] A transparency value to use for elements not targeted by the alpha aesthetic. |
alpha.target |
A vector of character strings; |
add.segments |
logical Display connecting segments or arrows between original positions and displaced ones if both are available. |
box.padding , point.padding
|
numeric By how much each end of the segments should shortened in mm. |
segment.linewidth |
numeric Width of the segments or arrows in mm. |
min.segment.length |
numeric Segments shorter that the minimum length are not rendered, in mm. |
arrow |
specification for arrow heads, as created by
|
na.rm |
If |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
You can modify the size of insets with the vp.width
and
vp.height
aesthetics. These can take a number between 0 (smallest
possible inset) and 1 (whole plotting area width or height). The default
value for for both of these aesthetics is 1/5. Thus, in contrast to
geom_text
, geom_label
,
geom_text_s
and geom_label_s
the size of the
insets remains the same relative to the size of the plotting area
irrespective of the size the plot is rendered at. The aspect ratio of
insets is preserved and size is adjusted until the whole inset fits within
the viewport.
By default geom_grob
uses position_nudge_center
and
justification "position"
, while geom_grob_npc
uses
position_nudge
and justification "inward"
. In
contrast to position_nudge
,
position_nudge_center
and all other position functions
defined in packages 'ggpp' keep the original coordinates thus allowing the
plotting of connecting segments and arrows.
This geom_grob
and geom_grob_npc
require the use tibbles as
argument for data
, as the grobs should be stored as a list of
graphics objects ("grob") to be mapped to the label
aesthetic.
The x
and y
aesthetics determine the position of the whole
inset grob, similarly to that of a text label, justification is interpreted
as indicating the position of the grob with respect to its x and
y coordinates in the data, and angle
is used to rotate the
grob as a whole.
A plot layer instance.
The "width" and "height" of an inset as for a text element are 0, so stacking and dodging inset plots will not work by default, and axis limits are not automatically expanded to include all inset plots. Obviously, insets do have height and width, but they are physical units, not data units. The amount of space they occupy on the main plot is not constant in data units of the base plot: when you modify scale limits, inset plots stay the same size relative to the physical size of the base plot.
You can modify text alignment with the vjust
and
hjust
aesthetics. These can either be a number between 0
(right/bottom) and 1 (top/left) or a character ("left"
,
"middle"
, "right"
, "bottom"
, "center"
,
"top"
). In addition, you can use special alignments for
justification including "position"
, "inward"
and
"outward"
. Inward always aligns text towards the center of the
plotting area, and outward aligns it away from the center of the plotting
area. If tagged with _mean
or _median
(e.g.,
"outward_mean"
) the mean or median of the data in the panel along
the corresponding axis is used as center. If the characters following the
underscore represent a number (e.g., "outward_10.5"
) the reference
point will be this value in data units. Position justification is computed
based on the direction of the displacement of the position of the label so
that each individual text or label is justified outwards from its original
position. The default justification is "position"
.
If no position displacement is applied, or a position function defined in
'ggplot2' is used, these geometries behave similarly to the corresponding
ones from package 'ggplot2' with a default justification of 0.5
and
no segment drawn.
Many layer functions from package 'ggpp' are
designed to work seamlessly with position functions that keep, rather than
discard, the original x
and y
positions in data
when
computing a new displaced position. See position_nudge_keep
,
position_dodge_keep
, position_jitter_keep
,
position_nudge_center
, position_nudge_line
,
position_nudge_to
, position_dodgenudge
,
position_jitternudge
, and position_stacknudge
for examples and details of their use.
The insets are stored nested within the main ggplot object and contain their own copy of the data, and are rendered as grid grobs as normal ggplots at the time the main ggplot is rendered. They can have different themes.
Use annotate
as redefined in 'ggpp' when adding insets
as annotations (automatically available unless 'ggpp' is not attached).
annotate
cannot be used with the npcx
and
npcy
pseudo-aesthetics.
The idea of implementing a geom_custom()
for grobs has
been discussed as an issue at
https://github.com/tidyverse/ggplot2/issues/1399.
grid-package
, geom_text
,
and other documentation of package 'ggplot2'.
library(tibble) df <- tibble(x = 2, y = 15, grob = list(grid::circleGrob(r = 0.2))) # without nudging no segments are drawn ggplot(data = mtcars, aes(wt, mpg)) + geom_point(aes(colour = factor(cyl))) + geom_grob(data = df, aes(x, y, label = grob)) # with nudging segments are drawn ggplot(data = mtcars, aes(wt, mpg)) + geom_point(aes(colour = factor(cyl))) + geom_grob(data = df, aes(x, y, label = grob), nudge_x = 0.5, colour = "red", hjust = 0.5, vjust = 0.5) ggplot(data = mtcars, aes(wt, mpg)) + geom_point(aes(colour = factor(cyl))) + geom_grob(data = df, aes(x, y, label = grob), nudge_x = 0.5, colour = "red", colour.target = "none", hjust = 0.5, vjust = 0.5) # with nudging plotting of segments can be disabled ggplot(data = mtcars, aes(wt, mpg)) + geom_point(aes(colour = factor(cyl))) + geom_grob(data = df, aes(x, y, label = grob), add.segments = FALSE, nudge_x = 0.5, hjust = 0.5, vjust = 0.5)
library(tibble) df <- tibble(x = 2, y = 15, grob = list(grid::circleGrob(r = 0.2))) # without nudging no segments are drawn ggplot(data = mtcars, aes(wt, mpg)) + geom_point(aes(colour = factor(cyl))) + geom_grob(data = df, aes(x, y, label = grob)) # with nudging segments are drawn ggplot(data = mtcars, aes(wt, mpg)) + geom_point(aes(colour = factor(cyl))) + geom_grob(data = df, aes(x, y, label = grob), nudge_x = 0.5, colour = "red", hjust = 0.5, vjust = 0.5) ggplot(data = mtcars, aes(wt, mpg)) + geom_point(aes(colour = factor(cyl))) + geom_grob(data = df, aes(x, y, label = grob), nudge_x = 0.5, colour = "red", colour.target = "none", hjust = 0.5, vjust = 0.5) # with nudging plotting of segments can be disabled ggplot(data = mtcars, aes(wt, mpg)) + geom_point(aes(colour = factor(cyl))) + geom_grob(data = df, aes(x, y, label = grob), add.segments = FALSE, nudge_x = 0.5, hjust = 0.5, vjust = 0.5)
geom_text_npc()
adds text directly to the plot.
geom_label_npc()
draws a rectangle behind the text, making it easier
to read. The difference is that x
and y
mappings are expected
to be given in npc
graphic units, using pseudo-aesthetics. Their
intended use is to add annotations to a plot.
geom_label_npc( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., parse = FALSE, nudge_x = 0, nudge_y = 0, label.padding = grid::unit(0.25, "lines"), label.r = grid::unit(0.15, "lines"), label.size = 0.25, size.unit = "mm", na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE ) geom_text_npc( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., parse = FALSE, nudge_x = 0, nudge_y = 0, check_overlap = FALSE, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE )
geom_label_npc( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., parse = FALSE, nudge_x = 0, nudge_y = 0, label.padding = grid::unit(0.25, "lines"), label.r = grid::unit(0.15, "lines"), label.size = 0.25, size.unit = "mm", na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE ) geom_text_npc( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., parse = FALSE, nudge_x = 0, nudge_y = 0, check_overlap = FALSE, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific data set - only needed if you want to override the plot defaults. |
stat |
The statistical transformation to use on the data for this layer, as a string. |
position |
Position adjustment, either as a string, or the result of a call to a position adjustment function. |
... |
other arguments passed on to |
parse |
If TRUE, the labels will be parsed into expressions and
displayed as described in |
nudge_x , nudge_y
|
Horizontal and vertical adjustment to nudge labels by. Useful for offsetting text from points, particularly on discrete scales. |
label.padding |
Amount of padding around label. Defaults to 0.25 lines. |
label.r |
Radius of rounded corners. Defaults to 0.15 lines. |
label.size |
Size of label border, in mm. |
size.unit |
How the 'size' aesthetic is interpreted: as millimetres ('"mm"', default), points ('"pt"'), centimetres ('"cm"'), inches ('"in"'), or picas ('"pc"'). |
na.rm |
If |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
check_overlap |
If 'TRUE', text that overlaps previous text in the same layer will not be plotted. |
These geoms are identical to 'ggplot2'
geom_text
and geom_label
except that they interpret npcx
and npcy
positions in
npc
units. They translate npcx
and npcy
coordinates
using a pseudo-aesthetic with a fixed scale, the translation is done
separately for each plot panel. All aesthetics other than x and
y and grouping work as in normal geoms. These include
linetype
and angle
in geom_label_npc()
.
With textual positions and groups a shift is added to successive labels to avoid overlaps. The shift is based on grouping, however unused levels are not dropped. In plots with faceting, if not all groups appear in each panel, there will be blank spaces in between labels. To solve this pass numeric values for the npc coordinates of each label instead of character strings.
You can modify text alignment with the vjust
and
hjust
aesthetics. These can either be a number between 0
(right/bottom) and 1 (top/left) or a character ("left"
,
"middle"
, "right"
, "bottom"
, "center"
,
"top"
). In addition, you can use special alignments for
justification including "position"
, "inward"
and
"outward"
. Inward always aligns text towards the center of the
plotting area, and outward aligns it away from the center of the plotting
area. If tagged with _mean
or _median
(e.g.,
"outward_mean"
) the mean or median of the data in the panel along
the corresponding axis is used as center. If the characters following the
underscore represent a number (e.g., "outward_10.5"
) the reference
point will be this value in data units. Position justification is computed
based on the direction of the displacement of the position of the label so
that each individual text or label is justified outwards from its original
position. The default justification is "position"
.
If no position displacement is applied, or a position function defined in
'ggplot2' is used, these geometries behave similarly to the corresponding
ones from package 'ggplot2' with a default justification of 0.5
and
no segment drawn.
Note that when you change the scale
limits for x and/or y of a plot, text labels stay the same
size, as determined by the size
aesthetic, given in millimetres. The
actual size as seen in the plotted output is decided during the rendering
of the plot to a graphics device. Limits are expanded only to include the
anchor point of the labels because the "width" and "height" of a text
element are 0 (as seen by ggplot2). Text labels do have height and width,
but in grid units, not data units.
geom_text
and
geom_label
for additional details.
df <- data.frame( x = c(0, 0, 1, 1, 0.5), x.chr = c("left", "left", "right", "right", "center"), y = c(0, 1, 0, 1, 0.5), y.chr = c("bottom", "top", "bottom", "top", "middle"), text = c("bottom-left", "top-left", "bottom-right", "top-right", "center-middle") ) ggplot(df) + geom_text_npc(aes(npcx = x, npcy = y, label = text)) ggplot(df) + geom_text_npc(aes(npcx = x.chr, npcy = y.chr, label = text)) ggplot(df) + geom_text_npc(aes(npcx = x.chr, npcy = y.chr, label = text), angle = 90) ggplot(data = mtcars, mapping = aes(wt, mpg)) + geom_point() + geom_text_npc(data = df, aes(npcx = x, npcy = y, label = text)) ggplot(data = mtcars, mapping = aes(wt, mpg)) + geom_point() + geom_text_npc(data = df, aes(npcx = x, npcy = y, label = text)) + expand_limits(y = 40, x = 6) ggplot(data = mtcars) + geom_point(mapping = aes(wt, mpg)) + geom_label_npc(data = df, aes(npcx = x, npcy = y, label = text)) ggplot(data = mtcars) + geom_point(mapping = aes(wt, mpg)) + geom_label_npc(data = df, aes(npcx = x.chr, npcy = y.chr, label = text), angle = 90) # ignored by ggplot2 < 3.5.0
df <- data.frame( x = c(0, 0, 1, 1, 0.5), x.chr = c("left", "left", "right", "right", "center"), y = c(0, 1, 0, 1, 0.5), y.chr = c("bottom", "top", "bottom", "top", "middle"), text = c("bottom-left", "top-left", "bottom-right", "top-right", "center-middle") ) ggplot(df) + geom_text_npc(aes(npcx = x, npcy = y, label = text)) ggplot(df) + geom_text_npc(aes(npcx = x.chr, npcy = y.chr, label = text)) ggplot(df) + geom_text_npc(aes(npcx = x.chr, npcy = y.chr, label = text), angle = 90) ggplot(data = mtcars, mapping = aes(wt, mpg)) + geom_point() + geom_text_npc(data = df, aes(npcx = x, npcy = y, label = text)) ggplot(data = mtcars, mapping = aes(wt, mpg)) + geom_point() + geom_text_npc(data = df, aes(npcx = x, npcy = y, label = text)) + expand_limits(y = 40, x = 6) ggplot(data = mtcars) + geom_point(mapping = aes(wt, mpg)) + geom_label_npc(data = df, aes(npcx = x, npcy = y, label = text)) ggplot(data = mtcars) + geom_point(mapping = aes(wt, mpg)) + geom_label_npc(data = df, aes(npcx = x.chr, npcy = y.chr, label = text), angle = 90) # ignored by ggplot2 < 3.5.0
Add a plot layer with a text label and a segment connecting two
values along the x
aesthetic. These are usually two levels of a
factor mapped to the x
aesthetic when used to report significance or
highlighting pairwise comparisons.
geom_label_pairwise( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., parse = FALSE, nudge_x = 0, nudge_y = 0, default.colour = "black", default.color = default.colour, colour.target = "all", color.target = colour.target, default.alpha = NA, alpha.target = "segment", label.padding = grid::unit(0.25, "lines"), label.r = grid::unit(0.15, "lines"), segment.linewidth = 0.5, arrow = NULL, size.unit = "mm", na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE ) geom_text_pairwise( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., parse = FALSE, nudge_x = 0, nudge_y = 0, default.colour = "black", default.color = default.colour, colour.target = "all", color.target = colour.target, default.alpha = NA, alpha.target = "all", segment.linewidth = 0.5, arrow = NULL, check_overlap = FALSE, size.unit = "mm", na.rm = FALSE, show.legend = NA, inherit.aes = FALSE )
geom_label_pairwise( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., parse = FALSE, nudge_x = 0, nudge_y = 0, default.colour = "black", default.color = default.colour, colour.target = "all", color.target = colour.target, default.alpha = NA, alpha.target = "segment", label.padding = grid::unit(0.25, "lines"), label.r = grid::unit(0.15, "lines"), segment.linewidth = 0.5, arrow = NULL, size.unit = "mm", na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE ) geom_text_pairwise( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., parse = FALSE, nudge_x = 0, nudge_y = 0, default.colour = "black", default.color = default.colour, colour.target = "all", color.target = colour.target, default.alpha = NA, alpha.target = "all", segment.linewidth = 0.5, arrow = NULL, check_overlap = FALSE, size.unit = "mm", na.rm = FALSE, show.legend = NA, inherit.aes = FALSE )
mapping |
Set of aesthetic mappings created by
|
data |
A data frame. If specified, overrides the default data frame defined at the top level of the plot. |
stat |
The statistical transformation to use on the data for this layer, as a string. |
position |
Position adjustment, either as a string, or the result of a call to a position adjustment function. |
... |
other arguments passed on to
|
parse |
If |
nudge_x , nudge_y
|
Horizontal and vertical adjustments to nudge the
starting position of each text label. The units for |
default.colour , default.color
|
A colour definition to use for elements not targeted by the colour aesthetic. |
colour.target , color.target
|
A vector of character strings; |
default.alpha |
numeric in [0..1] A transparency value to use for elements not targeted by the alpha aesthetic. |
alpha.target |
A vector of character strings; |
label.padding |
Amount of padding around label. Defaults to 0.25 lines. |
label.r |
Radius of rounded corners. Defaults to 0.15 lines. |
segment.linewidth |
numeric Width of the segments or arrows in mm. |
arrow |
specification for arrow heads, as created by
|
size.unit |
How the 'size' aesthetic is interpreted: as millimetres ('"mm"', default), points ('"pt"'), centimetres ('"cm"'), inches ('"in"'), or picas ('"pc"'). |
na.rm |
If |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
check_overlap |
If |
Geometries geom_text_pairwise()
and
geom_label_pairwise()
have an interface similar to that of
geom_text
and geom_label
, but
add a segment connecting two values along x
. In the most
frequent use case they add a segment connecting pairs of levels from a
grouping factor mapped to the x or y aesthetic. They can
also be used to label ranges of values.
The segment extends from xmin
to xmax
, and the text label is
located at x
with a default that positions the label at the centre
of the bar. The ends of the bar can be terminated with arrow heads given
by parameter arrow
, with a default of a plain segment without
arrow tips. The text label is located slightly above the segment by the
default value of vjust
in geom_text_pairwise()
and on top
of the segment in geom_label_pairwise()
.
Layer functions geom_text_pairwise()
and
geom_label_pairwise()
use by default
position_nudge
. Nudging affects both text label and
bar, and its default of no displacement will very rarely need to be
changed.
Differently to geom_text_repel()
and geom_label_repel()
,
geom_text_pairwise()
and geom_label_pairwise()
do not make
use of additional aesthetics for the segments or boxes, but instead allow
the choice of which elements are targeted by the usual 'ggplot2' aesthetics
and which are rendered using a default constant value. In the grammar of
graphics using the same aesthetic with multiple meanings is not allowed,
thus, the approach used in package 'ggpp' attempts to enforce this.
A plot layer instance.
This geometry is still under development and its user interface subject to change.
Note that when you change the scale
limits for x and/or y of a plot, text labels stay the same
size, as determined by the size
aesthetic, given in millimetres. The
actual size as seen in the plotted output is decided during the rendering
of the plot to a graphics device. Limits are expanded only to include the
anchor point of the labels because the "width" and "height" of a text
element are 0 (as seen by ggplot2). Text labels do have height and width,
but in grid units, not data units. Either function
expand_limits
or the scale expansion can be used to
ensure text labels remain within the plotting area.
You can modify text alignment with the vjust
and
hjust
aesthetics. These can either be a number between 0
(right/bottom) and 1 (top/left) or a character ("left"
,
"middle"
, "right"
, "bottom"
, "center"
,
"top"
). Values outside the range 0..1 displace the text label so
that the anchor point is outside the text label. In addition, you can use
special alignments for justification including "position"
,
"inward"
and "outward"
. Inward always aligns text towards the
center of the plotting area, and outward aligns it away from the center of
the plotting area. If tagged with _mean
or _median
(e.g.,
"outward_mean"
) the mean or median of the data in the panel along
the corresponding axis is used as center. If the characters following the
underscore represent a number (e.g., "outward_10.5"
) the reference
point will be this value in data units. Position justification is computed
based on the direction of the displacement of the position of the label so
that each individual text or label is justified outwards from its original
position. The default justification is "identity"
.
Layer functions geom_text_pairwise()
and
geom_label_pairwise()
require aesthetics xmin
, xmax
,
x
, y
and
label
and support aesthetics: alpha
, colour
,
group
, size
(of text), family
, fontface
,
linewidth
, linetype
, hjust
and vjust
. In addition,
geom_text_pairwise
supports angle
and geom_label_pairwise
supports
fill
. See
aes_colour_fill_alpha
,
aes_linetype_size_shape
,
aes_position
, and
aes_group_order
.
In 'ggplot2' linewidth
when applied to the border of the box drawn
by geom_label()
is given in points rather than in mm because of a
historical error in the code. In other geometries such as
geom_segment()
linewidth
is given in mm. As in
geom_label_pairwise()
it is important to remain consistent among
different linewidth
specifications, mm are used both for the box
border and linking segment. To imitate the behaviour of geom_label()
a correction factor of 0.75 (more exactly 1 pt = 0.7528 mm) can be used for
the line width of the border of the box.
geom_text_s
, geom_label_s
,
geom_text
, geom_label
and
other documentation of package 'ggplot2'.
my.cars <- mtcars my.cars$name <- rownames(my.cars) p1 <- ggplot(my.cars, aes(factor(cyl), mpg)) + geom_boxplot(width = 0.33) # With a factor mapped to x, highlight pairs my.pairs <- data.frame(A = 1:2, B = 2:3, bar.height = c(12, 30), p.value = c(0.01, 0.05678)) p1 + geom_text_pairwise(data = my.pairs, aes(xmin = A, xmax = B, y = bar.height, label = p.value), parse = TRUE) p1 + geom_text_pairwise(data = my.pairs, aes(xmin = A, xmax = B, y = bar.height, label = sprintf("italic(P)~`=`~%.2f", p.value)), arrow = grid::arrow(angle = 90, length = unit(1, "mm"), ends = "both"), parse = TRUE) p1 + geom_text_pairwise(data = my.pairs, aes(xmin = A, xmax = B, y = bar.height, label = sprintf("italic(P)~`=`~%.2f", p.value)), colour = "red", arrow = grid::arrow(angle = 90, length = unit(1, "mm"), ends = "both"), parse = TRUE) p1 + geom_label_pairwise(data = my.pairs, aes(xmin = A, xmax = B, y = bar.height, label = sprintf("italic(P)~`=`~%.2f", p.value)), colour = "red", size = 2.75, arrow = grid::arrow(angle = 30, length = unit(1.5, "mm"), ends = "both"), parse = TRUE) p1 + geom_text_pairwise(data = my.pairs, aes(xmin = A, xmax = B, y = bar.height, label = sprintf("italic(P)~`=`~%.2f", p.value)), colour = "red", colour.target = "segment", arrow = grid::arrow(angle = 90, length = unit(1, "mm"), ends = "both"), parse = TRUE) p1 + geom_text_pairwise(data = my.pairs, aes(xmin = A, xmax = B, y = bar.height, label = sprintf("italic(P)~`=`~%.2f", p.value)), colour = "red", colour.target = "text", arrow = grid::arrow(angle = 90, length = unit(1, "mm"), ends = "both"), parse = TRUE) # with a numeric vector mapped to x, indicate range p2 <- ggplot(my.cars, aes(disp, mpg)) + geom_point() my.ranges <- data.frame(A = c(50, 400), B = c(200, 500), bar.height = 5, text = c("small", "large")) p2 + geom_text_pairwise(data = my.ranges, aes(xmin = A, xmax = B, y = bar.height, label = text)) p2 + geom_text_pairwise(data = my.ranges, aes(xmin = A, xmax = B, y = bar.height, label = text), angle = 90, hjust = -0.1) p2 + geom_label_pairwise(data = my.ranges, aes(xmin = A, xmax = B, y = bar.height, label = text), angle = 90, hjust = -0.1) p2 + geom_label_pairwise(data = my.ranges, aes(xmin = A, xmax = B, y = bar.height, label = text)) p2 + geom_text_pairwise(data = my.ranges, aes(xmin = A, xmax = B, y = bar.height, label = text), arrow = grid::arrow(ends = "both", length = unit(2, "mm")))
my.cars <- mtcars my.cars$name <- rownames(my.cars) p1 <- ggplot(my.cars, aes(factor(cyl), mpg)) + geom_boxplot(width = 0.33) # With a factor mapped to x, highlight pairs my.pairs <- data.frame(A = 1:2, B = 2:3, bar.height = c(12, 30), p.value = c(0.01, 0.05678)) p1 + geom_text_pairwise(data = my.pairs, aes(xmin = A, xmax = B, y = bar.height, label = p.value), parse = TRUE) p1 + geom_text_pairwise(data = my.pairs, aes(xmin = A, xmax = B, y = bar.height, label = sprintf("italic(P)~`=`~%.2f", p.value)), arrow = grid::arrow(angle = 90, length = unit(1, "mm"), ends = "both"), parse = TRUE) p1 + geom_text_pairwise(data = my.pairs, aes(xmin = A, xmax = B, y = bar.height, label = sprintf("italic(P)~`=`~%.2f", p.value)), colour = "red", arrow = grid::arrow(angle = 90, length = unit(1, "mm"), ends = "both"), parse = TRUE) p1 + geom_label_pairwise(data = my.pairs, aes(xmin = A, xmax = B, y = bar.height, label = sprintf("italic(P)~`=`~%.2f", p.value)), colour = "red", size = 2.75, arrow = grid::arrow(angle = 30, length = unit(1.5, "mm"), ends = "both"), parse = TRUE) p1 + geom_text_pairwise(data = my.pairs, aes(xmin = A, xmax = B, y = bar.height, label = sprintf("italic(P)~`=`~%.2f", p.value)), colour = "red", colour.target = "segment", arrow = grid::arrow(angle = 90, length = unit(1, "mm"), ends = "both"), parse = TRUE) p1 + geom_text_pairwise(data = my.pairs, aes(xmin = A, xmax = B, y = bar.height, label = sprintf("italic(P)~`=`~%.2f", p.value)), colour = "red", colour.target = "text", arrow = grid::arrow(angle = 90, length = unit(1, "mm"), ends = "both"), parse = TRUE) # with a numeric vector mapped to x, indicate range p2 <- ggplot(my.cars, aes(disp, mpg)) + geom_point() my.ranges <- data.frame(A = c(50, 400), B = c(200, 500), bar.height = 5, text = c("small", "large")) p2 + geom_text_pairwise(data = my.ranges, aes(xmin = A, xmax = B, y = bar.height, label = text)) p2 + geom_text_pairwise(data = my.ranges, aes(xmin = A, xmax = B, y = bar.height, label = text), angle = 90, hjust = -0.1) p2 + geom_label_pairwise(data = my.ranges, aes(xmin = A, xmax = B, y = bar.height, label = text), angle = 90, hjust = -0.1) p2 + geom_label_pairwise(data = my.ranges, aes(xmin = A, xmax = B, y = bar.height, label = text)) p2 + geom_text_pairwise(data = my.ranges, aes(xmin = A, xmax = B, y = bar.height, label = text), arrow = grid::arrow(ends = "both", length = unit(2, "mm")))
Linked text geometries are most useful for adding data labels to plots. 'geom_text_s()' and 'geom_label_s()' add text to the plot and for nudged positions link the original location to the nudged text with a segment or arrow.
geom_label_s( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., parse = FALSE, nudge_x = 0, nudge_y = 0, default.colour = "black", default.color = default.colour, colour.target = c("text", "box"), color.target = colour.target, default.alpha = NA, alpha.target = "all", label.padding = grid::unit(0.25, "lines"), label.r = grid::unit(0.15, "lines"), segment.linewidth = 0.5, add.segments = TRUE, box.padding = 1e-06, point.padding = 1e-06, min.segment.length = 0, arrow = NULL, size.unit = "mm", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE ) geom_text_s( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., parse = FALSE, nudge_x = 0, nudge_y = 0, default.colour = "black", default.color = default.colour, colour.target = "text", color.target = colour.target, default.alpha = NA, alpha.target = "all", add.segments = TRUE, box.padding = 0.25, point.padding = 1e-06, segment.linewidth = 0.5, min.segment.length = 0, arrow = NULL, check_overlap = FALSE, size.unit = "mm", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE )
geom_label_s( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., parse = FALSE, nudge_x = 0, nudge_y = 0, default.colour = "black", default.color = default.colour, colour.target = c("text", "box"), color.target = colour.target, default.alpha = NA, alpha.target = "all", label.padding = grid::unit(0.25, "lines"), label.r = grid::unit(0.15, "lines"), segment.linewidth = 0.5, add.segments = TRUE, box.padding = 1e-06, point.padding = 1e-06, min.segment.length = 0, arrow = NULL, size.unit = "mm", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE ) geom_text_s( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., parse = FALSE, nudge_x = 0, nudge_y = 0, default.colour = "black", default.color = default.colour, colour.target = "text", color.target = colour.target, default.alpha = NA, alpha.target = "all", add.segments = TRUE, box.padding = 0.25, point.padding = 1e-06, segment.linewidth = 0.5, min.segment.length = 0, arrow = NULL, check_overlap = FALSE, size.unit = "mm", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE )
mapping |
Set of aesthetic mappings created by
|
data |
A data frame. If specified, overrides the default data frame defined at the top level of the plot. |
stat |
The statistical transformation to use on the data for this layer, as a string. |
position |
Position adjustment, either as a string, or the result of a call to a position adjustment function. |
... |
other arguments passed on to
|
parse |
If |
nudge_x , nudge_y
|
Horizontal and vertical adjustments to nudge the
starting position of each text label. The units for |
default.colour , default.color
|
A colour definition to use for elements not targeted by the colour aesthetic. |
colour.target , color.target
|
A vector of character strings; |
default.alpha |
numeric in [0..1] A transparency value to use for elements not targeted by the alpha aesthetic. |
alpha.target |
A vector of character strings; |
label.padding |
Amount of padding around label. Defaults to 0.25 lines. |
label.r |
Radius of rounded corners. Defaults to 0.15 lines. |
segment.linewidth |
numeric Width of the segments or arrows in mm. |
add.segments |
logical Display connecting segments or arrows between original positions and displaced ones if both are available. |
box.padding , point.padding
|
numeric By how much each end of the segments should shortened in mm. |
min.segment.length |
numeric Segments shorter that the minimum length are not rendered, in mm. |
arrow |
specification for arrow heads, as created by
|
size.unit |
How the 'size' aesthetic is interpreted: as millimetres ('"mm"', default), points ('"pt"'), centimetres ('"cm"'), inches ('"in"'), or picas ('"pc"'). |
na.rm |
If |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
check_overlap |
If |
Geometries geom_text_s()
and geom_label_s()
have an
interface similar to that of geom_text
and
geom_label
, but support additional features.
Similarly to geom_text_repel()
and geom_label_repel()
when
used together with position functions defined in package 'ggpp' they draw a
segment linking the label at a displaced position to the original position,
usually a point corresponding to an observation to which the label refers.
Another difference is that they allow control of to which graphical
elements the mappings to colour and alpha aesthetics are applied.
Differently to geom_label()
, geom_label_s()
obeys aesthetic
mappings to linewidth
and linetype
applied to the line at the
edge of the label box. These features are reflected in the plot key, except
for the segment, assumed not to be used to display information
only in coordination with other graphic elements.
In geom_label_s()
the default fill
is similar to
"white"
but with its alpha
component set to 0.75. This
differs from "white"
used in geom_label()
: the default fill
is semitransparent with the intention that accidental occlusion of
observations is obvious irrespective of the order in which layers are added
to the plot.
Layer functions geom_text_s()
and geom_label_s()
use by
default position_nudge_keep
which is backwards compatible
with position_nudge
. In contrast to
position_nudge
, position_nudge_keep
and all other position functions defined in packages 'ggpp' and 'ggrepel'
keep the original coordinates, thus allowing the plotting of connecting
segments and arrows.
Differently to geom_text_repel()
and geom_label_repel()
,
geom_text_s()
and geom_label_s()
do not make use of
additional aesthetics for the segments or boxes, but instead allow the
choice of which elements are targeted by the aesthetics and which are
rendered in a default colour. In the grammar of graphics using the same
aesthetic with multiple meanings is not allowed, thus, the approach used in
the geometry layer functions from package 'ggpp' attempts to enforce this.
A plot layer instance.
Note that when you change the scale
limits for x and/or y of a plot, text labels stay the same
size, as determined by the size
aesthetic, given in millimetres. The
actual size as seen in the plotted output is decided during the rendering
of the plot to a graphics device. Limits are expanded only to include the
anchor point of the labels because the "width" and "height" of a text
element are 0 (as seen by ggplot2). Text labels do have height and width,
but in grid units, not data units.
You can modify text alignment with the vjust
and
hjust
aesthetics. These can either be a number between 0
(right/bottom) and 1 (top/left) or a character ("left"
,
"middle"
, "right"
, "bottom"
, "center"
,
"top"
). In addition, you can use special alignments for
justification including "position"
, "inward"
and
"outward"
. Inward always aligns text towards the center of the
plotting area, and outward aligns it away from the center of the plotting
area. If tagged with _mean
or _median
(e.g.,
"outward_mean"
) the mean or median of the data in the panel along
the corresponding axis is used as center. If the characters following the
underscore represent a number (e.g., "outward_10.5"
) the reference
point will be this value in data units. Position justification is computed
based on the direction of the displacement of the position of the label so
that each individual text or label is justified outwards from its original
position. The default justification is "position"
.
If no position displacement is applied, or a position function defined in
'ggplot2' is used, these geometries behave similarly to the corresponding
ones from package 'ggplot2' with a default justification of 0.5
and
no segment drawn.
The user interface is for the most part stable starting from 'ggpp' (==
0.5.7). In 'ggpp' (== 0.5.0) support for aesthetics related to segments was
removed, and replaced by parameters and a new mechanism for targeting the
usual colour
and alpha
aesthetics to text, border, and
segment.
Layer functions geom_text_s()
and
geom_label_s()
require aesthetics x
, y
and
label
and support aesthetics: alpha
, colour
,
group
, size
(of text), family
, fontface
,
lineheight
, hjust
and vjust
. In addition,
geom_text_s
supports angle
and geom_label_s
supports
fill
, linewidth
and linetype
. See
aes_colour_fill_alpha
,
aes_linetype_size_shape
,
aes_position
, and
aes_group_order
.
In 'ggplot2' linewidth
when applied to the border of the box drawn
by geom_label()
is given in points rather than in mm because of a
historical error in the code. In other geometries such as
geom_segment()
linewidth
is given in mm. As in
geom_label_s()
it is important to remain consistent among
different linewidth
specifications, mm are used both for the box
border and linking segment. To imitate the behaviour of geom_label()
a correction factor of 0.75 (more exactly 1 pt = 0.7528 mm) can be used for
the line width of the border of the box.
Many layer functions from package 'ggpp' are
designed to work seamlessly with position functions that keep, rather than
discard, the original x
and y
positions in data
when
computing a new displaced position. See position_nudge_keep
,
position_dodge_keep
, position_jitter_keep
,
position_nudge_center
, position_nudge_line
,
position_nudge_to
, position_dodgenudge
,
position_jitternudge
, and position_stacknudge
for examples and details of their use.
geom_text
, geom_label
and other documentation of package 'ggplot2'.
my.cars <- mtcars[c(TRUE, FALSE, FALSE, FALSE), ] my.cars$name <- rownames(my.cars) # no nudging ggplot(my.cars, aes(wt, mpg, label = name)) + geom_text_s() + expand_limits(x = c(2, 6)) # base plot p <- ggplot(my.cars, aes(wt, mpg, label = name)) + geom_point() # Using nudging p + geom_text_s(nudge_x = 0.12) + expand_limits(x = 6.2) p + geom_text_s(nudge_x = -0.12) + expand_limits(x = 1.5) p + geom_text_s(nudge_x = 0.12, arrow = arrow(length = grid::unit(1.5, "mm")), point.padding = 0.4) + expand_limits(x = 6.2) p + geom_text_s(nudge_y = 0.1, nudge_x = 0.07) + expand_limits(x = 6.2) p + geom_text_s(nudge_y = 1, angle = 90) + expand_limits(y = 30) p + geom_text_s(angle = 90, nudge_y = 1, arrow = arrow(length = grid::unit(1.5, "mm")), colour.target = "segment", colour = "red") + expand_limits(y = 30) p + geom_text_s(aes(colour = factor(cyl)), angle = 90, nudge_y = 1, arrow = arrow(length = grid::unit(1.5, "mm")), alpha.target = "segment", alpha = 0.3) + expand_limits(y = 30) p + geom_label_s(nudge_x = 0.12) + expand_limits(x = 6.2) p + geom_label_s(nudge_x = 0.12, linetype = "dotted", linewidth = 0.3) + expand_limits(x = 6.2) p + geom_label_s(aes(colour = factor(cyl)), nudge_x = 0.12, colour.target = "box", linewidth = 0.5, label.r = unit(0, "lines")) + expand_limits(x = 6.2) p + geom_label_s(nudge_x = 0.12, linewidth = 0) + expand_limits(x = 6.2) # No segments p + geom_label_s(nudge_x = 0.05, segment.linewidth = 0) + expand_limits(x = 6.2) # Nudging away from arbitrary point p + geom_label_s(hjust = "outward_1", nudge_x = 0.12) + expand_limits(x = 6.2) p + geom_label_s(hjust = "inward_3", nudge_y = 0.4) p + geom_label_s(nudge_y = 1, angle = 90) + expand_limits(y = 30) # Add aesthetic mappings and adjust arrows p + geom_text_s(aes(colour = factor(cyl)), angle = 90, nudge_y = 1, arrow = arrow(angle = 20, length = grid::unit(1.5, "mm"), ends = "first", type = "closed")) + scale_colour_discrete(l = 40) + # luminance, make colours darker expand_limits(y = 27) p + geom_text_s(aes(colour = factor(cyl)), angle = 90, nudge_y = 1, arrow = arrow(angle = 20, length = grid::unit(1.5, "mm"), ends = "first", type = "closed")) + scale_colour_discrete(l = 40) + # luminance, make colours darker expand_limits(y = 27) p + geom_label_s(aes(colour = factor(cyl)), colour.target = c("box", "text"), nudge_x = 0.3, arrow = arrow(angle = 20, length = grid::unit(1/3, "lines"))) + scale_colour_discrete(l = 40) + # luminance, make colours darker expand_limits(x = 7) p + geom_label_s(aes(colour = factor(cyl)), nudge_x = 0.3, colour.target = c("box", "segment"), linewidth = 0.5, arrow = arrow(angle = 20, length = grid::unit(1/3, "lines"))) + scale_colour_discrete(l = 40) + # luminance, make colours darker expand_limits(x = 7) p + geom_label_s(aes(colour = factor(cyl), fill = factor(cyl)), nudge_x = 0.3, alpha.target = "box", alpha = 0.1, linewidth = 0.5, arrow = arrow(angle = 20, length = grid::unit(1/3, "lines"))) + scale_colour_discrete(l = 40) + # luminance, make colours darker expand_limits(x = 7)#' # Scale height of text, rather than sqrt(height) p + geom_text_s(aes(size = wt), nudge_x = -0.1) + scale_radius(range = c(3,6)) + # override scale_area() expand_limits(x = c(1.8, 5.5))
my.cars <- mtcars[c(TRUE, FALSE, FALSE, FALSE), ] my.cars$name <- rownames(my.cars) # no nudging ggplot(my.cars, aes(wt, mpg, label = name)) + geom_text_s() + expand_limits(x = c(2, 6)) # base plot p <- ggplot(my.cars, aes(wt, mpg, label = name)) + geom_point() # Using nudging p + geom_text_s(nudge_x = 0.12) + expand_limits(x = 6.2) p + geom_text_s(nudge_x = -0.12) + expand_limits(x = 1.5) p + geom_text_s(nudge_x = 0.12, arrow = arrow(length = grid::unit(1.5, "mm")), point.padding = 0.4) + expand_limits(x = 6.2) p + geom_text_s(nudge_y = 0.1, nudge_x = 0.07) + expand_limits(x = 6.2) p + geom_text_s(nudge_y = 1, angle = 90) + expand_limits(y = 30) p + geom_text_s(angle = 90, nudge_y = 1, arrow = arrow(length = grid::unit(1.5, "mm")), colour.target = "segment", colour = "red") + expand_limits(y = 30) p + geom_text_s(aes(colour = factor(cyl)), angle = 90, nudge_y = 1, arrow = arrow(length = grid::unit(1.5, "mm")), alpha.target = "segment", alpha = 0.3) + expand_limits(y = 30) p + geom_label_s(nudge_x = 0.12) + expand_limits(x = 6.2) p + geom_label_s(nudge_x = 0.12, linetype = "dotted", linewidth = 0.3) + expand_limits(x = 6.2) p + geom_label_s(aes(colour = factor(cyl)), nudge_x = 0.12, colour.target = "box", linewidth = 0.5, label.r = unit(0, "lines")) + expand_limits(x = 6.2) p + geom_label_s(nudge_x = 0.12, linewidth = 0) + expand_limits(x = 6.2) # No segments p + geom_label_s(nudge_x = 0.05, segment.linewidth = 0) + expand_limits(x = 6.2) # Nudging away from arbitrary point p + geom_label_s(hjust = "outward_1", nudge_x = 0.12) + expand_limits(x = 6.2) p + geom_label_s(hjust = "inward_3", nudge_y = 0.4) p + geom_label_s(nudge_y = 1, angle = 90) + expand_limits(y = 30) # Add aesthetic mappings and adjust arrows p + geom_text_s(aes(colour = factor(cyl)), angle = 90, nudge_y = 1, arrow = arrow(angle = 20, length = grid::unit(1.5, "mm"), ends = "first", type = "closed")) + scale_colour_discrete(l = 40) + # luminance, make colours darker expand_limits(y = 27) p + geom_text_s(aes(colour = factor(cyl)), angle = 90, nudge_y = 1, arrow = arrow(angle = 20, length = grid::unit(1.5, "mm"), ends = "first", type = "closed")) + scale_colour_discrete(l = 40) + # luminance, make colours darker expand_limits(y = 27) p + geom_label_s(aes(colour = factor(cyl)), colour.target = c("box", "text"), nudge_x = 0.3, arrow = arrow(angle = 20, length = grid::unit(1/3, "lines"))) + scale_colour_discrete(l = 40) + # luminance, make colours darker expand_limits(x = 7) p + geom_label_s(aes(colour = factor(cyl)), nudge_x = 0.3, colour.target = c("box", "segment"), linewidth = 0.5, arrow = arrow(angle = 20, length = grid::unit(1/3, "lines"))) + scale_colour_discrete(l = 40) + # luminance, make colours darker expand_limits(x = 7) p + geom_label_s(aes(colour = factor(cyl), fill = factor(cyl)), nudge_x = 0.3, alpha.target = "box", alpha = 0.1, linewidth = 0.5, arrow = arrow(angle = 20, length = grid::unit(1/3, "lines"))) + scale_colour_discrete(l = 40) + # luminance, make colours darker expand_limits(x = 7)#' # Scale height of text, rather than sqrt(height) p + geom_text_s(aes(size = wt), nudge_x = -0.1) + scale_radius(range = c(3,6)) + # override scale_area() expand_limits(x = c(1.8, 5.5))
geom_plot
and geom_plot_npc
add ggplot objects as insets to the
base ggplot, using syntax similar to that of
geom_label
and geom_text_s
.
In most respects they behave as any other ggplot geometry: they add a layer
containing one or more grobs and grouping and faceting works as usual. The
most common use of geom_plot
is to add data labels that are themselves
ggplots rather than text. geom_plot_npc
is used to add ggplots
as annotations to plots, but contrary to layer function annotate()
,
geom_plot_npc
is data driven and respects grouping and facets,
thus plot insets can differ among panels.
geom_plot( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., nudge_x = 0, nudge_y = 0, default.colour = "black", default.color = default.colour, colour.target = "box", color.target = colour.target, default.alpha = 1, alpha.target = "all", add.segments = TRUE, box.padding = 0.25, point.padding = 1e-06, segment.linewidth = 0.5, min.segment.length = 0, arrow = NULL, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE ) geom_plot_npc( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE )
geom_plot( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., nudge_x = 0, nudge_y = 0, default.colour = "black", default.color = default.colour, colour.target = "box", color.target = colour.target, default.alpha = 1, alpha.target = "all", add.segments = TRUE, box.padding = 0.25, point.padding = 1e-06, segment.linewidth = 0.5, min.segment.length = 0, arrow = NULL, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE ) geom_plot_npc( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific data set - only needed if you want to override the plot defaults. |
stat |
The statistical transformation to use on the data for this layer, as a string. |
position |
Position adjustment, either as a string, or the result of a call to a position adjustment function. |
... |
other arguments passed on to |
nudge_x , nudge_y
|
Horizontal and vertical adjustments to nudge the
starting position of each text label. The units for |
default.colour , default.color
|
A colour definition to use for elements not targeted by the colour aesthetic. |
colour.target , color.target
|
A vector of character strings; |
default.alpha |
numeric in [0..1] A transparency value to use for elements not targeted by the alpha aesthetic. |
alpha.target |
A vector of character strings; |
add.segments |
logical Display connecting segments or arrows between original positions and displaced ones if both are available. |
box.padding , point.padding
|
numeric By how much each end of the segments should shortened in mm. |
segment.linewidth |
numeric Width of the segments or arrows in mm. |
min.segment.length |
numeric Segments shorter that the minimum length are not rendered, in mm. |
arrow |
specification for arrow heads, as created by
|
na.rm |
If |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
You can modify the size of inset plots with the vp.width
and
vp.height
aesthetics. These can take a number between 0 (smallest
possible inset) and 1 (whole plotting area width or height). The default
value for for both of these aesthetics is 1/5. Thus, in contrast to
geom_text
and geom_text_s
the size of
the insets remains the same relative to the size of the plotting area
irrespective of how the plot is rendered. The aspect ratio of insets is
preserved and size is adjusted until the whole inset fits within the
viewport.
By default this geom uses position_nudge_center
which is
backwards compatible with position_nudge
but
provides additional control on the direction of the nudging. In contrast to
position_nudge
, position_nudge_center
and all other position functions defined in packages 'ggpp' and 'ggrepel'
keep the original coordinates thus allowing the plotting of connecting
segments and arrows.
This geom works only with tibbles as data
, as its expects a list of
ggplot objects ("gg"
class) to be mapped to the label
aesthetic.
The x
and y
aesthetics determine the position of the whole
inset plot, similarly to that of a text label, justification is interpreted
as indicating the position of the plot with respect to its x and y
coordinates in the data, and angle
is used to rotate the plot as a
whole.
Of these two geoms only geom_plot
supports the plotting of
segments, as geom_plot_npc
uses a coordinate system that is
unrelated to data units and data.In the case of geom_plot_npc()
,
npcx
and npcy
aesthetics determine the position of the inset
plot.
A plot layer instance.
You can modify text alignment with the vjust
and
hjust
aesthetics. These can either be a number between 0
(right/bottom) and 1 (top/left) or a character ("left"
,
"middle"
, "right"
, "bottom"
, "center"
,
"top"
). In addition, you can use special alignments for
justification including "position"
, "inward"
and
"outward"
. Inward always aligns text towards the center of the
plotting area, and outward aligns it away from the center of the plotting
area. If tagged with _mean
or _median
(e.g.,
"outward_mean"
) the mean or median of the data in the panel along
the corresponding axis is used as center. If the characters following the
underscore represent a number (e.g., "outward_10.5"
) the reference
point will be this value in data units. Position justification is computed
based on the direction of the displacement of the position of the label so
that each individual text or label is justified outwards from its original
position. The default justification is "position"
.
If no position displacement is applied, or a position function defined in
'ggplot2' is used, these geometries behave similarly to the corresponding
ones from package 'ggplot2' with a default justification of 0.5
and
no segment drawn.
Many layer functions from package 'ggpp' are
designed to work seamlessly with position functions that keep, rather than
discard, the original x
and y
positions in data
when
computing a new displaced position. See position_nudge_keep
,
position_dodge_keep
, position_jitter_keep
,
position_nudge_center
, position_nudge_line
,
position_nudge_to
, position_dodgenudge
,
position_jitternudge
, and position_stacknudge
for examples and details of their use.
The "width" and "height" of an inset as for a text element are 0, so stacking and dodging inset plots will not work by default, and axis limits are not automatically expanded to include all inset plots. Obviously, insets do have height and width, but they are physical units, not data units. The amount of space they occupy on the main plot is not constant in data units of the base plot: when you modify scale limits, inset plots stay the same size relative to the physical size of the base plot.
The insets are stored nested within the main ggplot object and contain their own copy of the data, and are rendered as grid grobs as normal ggplots at the time the main ggplot is rendered. They can have different themes.
Use annotate
as redefined in 'ggpp' when adding insets
as annotations (automatically available unless 'ggpp' is not attached).
annotate
cannot be used with the npcx
and
npcy
pseudo-aesthetics.
The idea of implementing a geom_custom()
for grobs has
been discussed as an issue at
https://github.com/tidyverse/ggplot2/issues/1399.
Other geometries adding layers with insets:
geom_table()
# inset plot with enlarged detail from a region of the main plot library(tibble) p <- ggplot(data = mtcars, mapping = aes(wt, mpg)) + geom_point() df <- tibble(x = 0.01, y = 0.01, plot = list(p + coord_cartesian(xlim = c(3, 4), ylim = c(13, 16)) + labs(x = NULL, y = NULL) + theme_bw(10))) p + expand_limits(x = 0, y = 0) + geom_plot_npc(data = df, aes(npcx = x, npcy = y, label = plot)) p + expand_limits(x = 0, y = 0) + geom_plot_npc(data = df, aes(npcx = x, npcy = y, label = plot, vp.width = 1/2, vp.height = 1/4)) p + expand_limits(x = 0, y = 0) + geom_plot_npc(data = df, aes(npcx = x, npcy = y, label = plot), vp.width = 1/4, vp.height = 1/4) p + geom_plot(data = df, aes(x = x + 3, y = y + 20, label = plot), nudge_x = -1, nudge_y = - 7, hjust = 0.5, vjust = 0.5, arrow = arrow(length = unit(0.5, "lines")), colour = "red", vp.width = 1/5, vp.height = 1/5)
# inset plot with enlarged detail from a region of the main plot library(tibble) p <- ggplot(data = mtcars, mapping = aes(wt, mpg)) + geom_point() df <- tibble(x = 0.01, y = 0.01, plot = list(p + coord_cartesian(xlim = c(3, 4), ylim = c(13, 16)) + labs(x = NULL, y = NULL) + theme_bw(10))) p + expand_limits(x = 0, y = 0) + geom_plot_npc(data = df, aes(npcx = x, npcy = y, label = plot)) p + expand_limits(x = 0, y = 0) + geom_plot_npc(data = df, aes(npcx = x, npcy = y, label = plot, vp.width = 1/2, vp.height = 1/4)) p + expand_limits(x = 0, y = 0) + geom_plot_npc(data = df, aes(npcx = x, npcy = y, label = plot), vp.width = 1/4, vp.height = 1/4) p + geom_plot(data = df, aes(x = x + 3, y = y + 20, label = plot), nudge_x = -1, nudge_y = - 7, hjust = 0.5, vjust = 0.5, arrow = arrow(length = unit(0.5, "lines")), colour = "red", vp.width = 1/5, vp.height = 1/5)
The geometry "geom_point_s"
provides a super set of the capabilities of
geom geom_point
from package 'ggplot2' by allowing
plotting of arrows or segments joining the original position of displaced observations
to their current position rendered as points or graphic symbols. The most
common use is to demonstrate the action of different position functions. It
can be also used to highlight observations.
geom_point_s( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., nudge_x = 0, nudge_y = 0, move.point = TRUE, arrow = grid::arrow(length = unit(1/3, "lines"), ends = "first"), default.colour = "black", default.color = default.colour, colour.target = "point", color.target = colour.target, default.alpha = NA, alpha.target = "all", add.segments = TRUE, box.padding = 0.25, point.padding = 1e-06, segment.linewidth = 0.5, min.segment.length = 0, na.rm = FALSE, show.legend = NA, inherit.aes = TRUE )
geom_point_s( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., nudge_x = 0, nudge_y = 0, move.point = TRUE, arrow = grid::arrow(length = unit(1/3, "lines"), ends = "first"), default.colour = "black", default.color = default.colour, colour.target = "point", color.target = colour.target, default.alpha = NA, alpha.target = "all", add.segments = TRUE, box.padding = 0.25, point.padding = 1e-06, segment.linewidth = 0.5, min.segment.length = 0, na.rm = FALSE, show.legend = NA, inherit.aes = TRUE )
mapping |
Set of aesthetic mappings created by
|
data |
A data frame. If specified, overrides the default data frame defined at the top level of the plot. |
stat |
The statistical transformation to use on the data for this layer, as a string. |
position |
Position adjustment, either as a string, or the result of a call to a position adjustment function. |
... |
other arguments passed on to
|
nudge_x , nudge_y
|
Horizontal and vertical adjustments to nudge the
starting position of each text label. The units for |
move.point |
logical If |
arrow |
specification for arrow heads, as created by
|
default.colour , default.color
|
A colour definition to use for elements not targeted by the colour aesthetic. |
colour.target , color.target
|
A character string, one of |
default.alpha |
numeric in [0..1] A transparency value to use for elements not targeted by the alpha aesthetic. |
alpha.target |
A character string, one of |
add.segments |
logical Display connecting segments or arrows between original positions and displaced ones if both are available. |
box.padding , point.padding
|
numeric By how much each end of the segments should shortened in mm. |
segment.linewidth |
numeric Width of the segments or arrows in mm. |
min.segment.length |
numeric Segments shorter that the minimum length are not rendered, in mm. |
na.rm |
If |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
The plotting of segments is similar in idea to that implemented in
geom_text_repel
and relies on position functions
that rename instead of only replacing the original x
and y
coordinates from the data
object.
By default this geom uses position_nudge_center
which is backwards
compatible with position_nudge
but provides additional control
on the direction of the nudging.
A plot layer instance.
Many layer functions from package 'ggpp' are
designed to work seamlessly with position functions that keep, rather than
discard, the original x
and y
positions in data
when
computing a new displaced position. See position_nudge_keep
,
position_dodge_keep
, position_jitter_keep
,
position_nudge_center
, position_nudge_line
,
position_nudge_to
, position_dodgenudge
,
position_jitternudge
, and position_stacknudge
for examples and details of their use.
The insets are stored nested within the main ggplot object and contain their own copy of the data, and are rendered as grid grobs as normal ggplots at the time the main ggplot is rendered. They can have different themes.
Use annotate
as redefined in 'ggpp' when adding insets
as annotations (automatically available unless 'ggpp' is not attached).
annotate
cannot be used with the npcx
and
npcy
pseudo-aesthetics.
# Same output as with geom_point() ggplot(mpg[1:20, ], aes(cyl, hwy)) + geom_point_s(colour = "blue") # with segment drawn after nudging ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point_s(position = position_nudge_keep(x = 0.2), colour = "red") + geom_point_s(colour = "blue") + expand_limits(x = c(3.5, 8.5)) ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point_s(position = position_nudge_keep(x = 0.2), colour = "blue", move.point = FALSE) + expand_limits(x = c(3.5, 8.5)) # with segment drawn after nudging ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point_s(position = position_nudge_keep(x = 0.2), colour = "red", colour.target = "all") + geom_point_s(colour = "blue") ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point_s(position = position_nudge_keep(x = 0.2), colour = "red", colour.target = "segment") + geom_point_s(colour = "blue") ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point_s(position = position_nudge_keep(x = 0.2), colour = "red", colour.target = "point") + geom_point_s(colour = "blue") ggplot(mpg[1:50, ], aes(cyl, hwy, label = drv)) + geom_point_s(position = position_jitternudge(width = 0.66, height = 2, seed = 456, nudge.from = "jittered", kept.origin = "original"), colour = "red", alpha = 0.3, alpha.target = "segment", arrow = grid::arrow(length = grid::unit(0.4, "lines"), ends = "first")) + geom_point_s(colour = "blue")
# Same output as with geom_point() ggplot(mpg[1:20, ], aes(cyl, hwy)) + geom_point_s(colour = "blue") # with segment drawn after nudging ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point_s(position = position_nudge_keep(x = 0.2), colour = "red") + geom_point_s(colour = "blue") + expand_limits(x = c(3.5, 8.5)) ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point_s(position = position_nudge_keep(x = 0.2), colour = "blue", move.point = FALSE) + expand_limits(x = c(3.5, 8.5)) # with segment drawn after nudging ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point_s(position = position_nudge_keep(x = 0.2), colour = "red", colour.target = "all") + geom_point_s(colour = "blue") ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point_s(position = position_nudge_keep(x = 0.2), colour = "red", colour.target = "segment") + geom_point_s(colour = "blue") ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point_s(position = position_nudge_keep(x = 0.2), colour = "red", colour.target = "point") + geom_point_s(colour = "blue") ggplot(mpg[1:50, ], aes(cyl, hwy, label = drv)) + geom_point_s(position = position_jitternudge(width = 0.66, height = 2, seed = 456, nudge.from = "jittered", kept.origin = "original"), colour = "red", alpha = 0.3, alpha.target = "segment", arrow = grid::arrow(length = grid::unit(0.4, "lines"), ends = "first")) + geom_point_s(colour = "blue")
geom_vhlines()
adds in a single layer both vertical and horizontal
guide lines. Can be thought of as a convenience function that helps with
producing consistent vertical and horizontal guide lines. It behaves like
geom_vline()
and geom_hline()
.
geom_quadrant_lines()
displays the boundaries of four quadrants
with an arbitrary origin. The quadrants are specified in the same way as
in stat_quadrant_counts()
and is intended to be used to add guide
lines consistent with the counts by quadrant computed by this stat.
geom_quadrant_lines( mapping = NULL, data = NULL, stat = "identity", position = "identity", pool.along = c("none", "x", "y", "xy"), xintercept = 0, yintercept = 0, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE, ... ) geom_vhlines( mapping = NULL, data = NULL, stat = "identity", position = "identity", xintercept = NULL, yintercept = NULL, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE, ... )
geom_quadrant_lines( mapping = NULL, data = NULL, stat = "identity", position = "identity", pool.along = c("none", "x", "y", "xy"), xintercept = 0, yintercept = 0, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE, ... ) geom_vhlines( mapping = NULL, data = NULL, stat = "identity", position = "identity", xintercept = NULL, yintercept = NULL, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE, ... )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific data set - only needed if you want to override the plot defaults. |
stat |
The statistic object to use display the data |
position |
The position adjustment to use for overlapping points on this layer |
pool.along |
character, one of |
xintercept , yintercept
|
numeric vectors the coordinates of the origin of the quadrants. |
na.rm |
a logical indicating whether NA values should be stripped before the computation proceeds. |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
... |
other arguments passed on to |
While geom_vhlines()
does not provide defaults for the
intercepts and accepts vectors of length > 1, geom_quadrant_lines()
sets by default the intercepts to zero producing the natural quadrants and
only accepts vectors of length one per panel. That is geom_vhlines()
can be used to plot a grid while geom_quadrant_lines()
plots at
most one vertical and one horizontal line. In the case of
geom_quadrant_lines()
the pooling along axes can be specified in the
same way as in stat_quadrant_counts()
.
A plot layer instance.
geom_abline
, the topic where
geom_vline()
and geom_hline()
are described.
Other Functions for quadrant and volcano plots:
stat_panel_counts()
,
stat_quadrant_counts()
# generate artificial data set.seed(4321) x <- 1:100 y <- rnorm(length(x), mean = 10) my.data <- data.frame(x, y) ggplot(my.data, aes(x, y)) + geom_quadrant_lines() + geom_point() ggplot(my.data, aes(x, y)) + geom_quadrant_lines(linetype = "dotted") + geom_point() ggplot(my.data, aes(x, y)) + geom_quadrant_lines(xintercept = 50, yintercept = 10, colour = "blue") + geom_point() ggplot(my.data, aes(x, y)) + geom_quadrant_lines(xintercept = 50, pool.along = "y", colour = "blue") + geom_point() ggplot(my.data, aes(x, y)) + geom_vhlines(xintercept = c(25, 50, 75), yintercept = 10 , linetype = "dotted", colour = "red") + geom_point() + theme_bw() ggplot(my.data, aes(x, y)) + geom_vhlines(xintercept = c(25, 50, 75), yintercept = c(10, 8), linetype = "dotted", colour = "red") + geom_point() + theme_bw()
# generate artificial data set.seed(4321) x <- 1:100 y <- rnorm(length(x), mean = 10) my.data <- data.frame(x, y) ggplot(my.data, aes(x, y)) + geom_quadrant_lines() + geom_point() ggplot(my.data, aes(x, y)) + geom_quadrant_lines(linetype = "dotted") + geom_point() ggplot(my.data, aes(x, y)) + geom_quadrant_lines(xintercept = 50, yintercept = 10, colour = "blue") + geom_point() ggplot(my.data, aes(x, y)) + geom_quadrant_lines(xintercept = 50, pool.along = "y", colour = "blue") + geom_point() ggplot(my.data, aes(x, y)) + geom_vhlines(xintercept = c(25, 50, 75), yintercept = 10 , linetype = "dotted", colour = "red") + geom_point() + theme_bw() ggplot(my.data, aes(x, y)) + geom_vhlines(xintercept = c(25, 50, 75), yintercept = c(10, 8), linetype = "dotted", colour = "red") + geom_point() + theme_bw()
geom_table
and geom_table_npc
add data frames as table insets
to the base ggplot, using syntax similar to that of
geom_text
and geom_text_s
. In most
respects they behave as any other ggplot geometry: they add a layer
containing one or more grobs and grouping and faceting works as usual. The
most common use of geom_table
is to add data labels that are whole
tables rather than text. geom_table_npc
is used to add tables
as annotations to plots, but contrary to layer function annotate
,
geom_table_npc
is data driven and respects grouping and facets,
thus plot insets can differ among panels.
geom_table( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., nudge_x = 0, nudge_y = 0, default.colour = "black", default.color = default.colour, colour.target = "box", color.target = colour.target, default.alpha = 1, alpha.target = "all", add.segments = TRUE, box.padding = 0.25, point.padding = 1e-06, segment.linewidth = 0.5, min.segment.length = 0, arrow = NULL, table.theme = NULL, table.rownames = FALSE, table.colnames = TRUE, table.hjust = 0.5, parse = FALSE, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE ) geom_table_npc( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., table.theme = NULL, table.rownames = FALSE, table.colnames = TRUE, table.hjust = 0.5, parse = FALSE, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE )
geom_table( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., nudge_x = 0, nudge_y = 0, default.colour = "black", default.color = default.colour, colour.target = "box", color.target = colour.target, default.alpha = 1, alpha.target = "all", add.segments = TRUE, box.padding = 0.25, point.padding = 1e-06, segment.linewidth = 0.5, min.segment.length = 0, arrow = NULL, table.theme = NULL, table.rownames = FALSE, table.colnames = TRUE, table.hjust = 0.5, parse = FALSE, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE ) geom_table_npc( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., table.theme = NULL, table.rownames = FALSE, table.colnames = TRUE, table.hjust = 0.5, parse = FALSE, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific data set - only needed if you want to override the plot defaults. |
stat |
The statistical transformation to use on the data for this layer, as a string. |
position |
Position adjustment, either as a string, or the result of a |
... |
other arguments passed on to |
nudge_x , nudge_y
|
Horizontal and vertical adjustments to nudge the
starting position of each text label. The units for |
default.colour , default.color
|
A colour definition to use for elements not targeted by the colour aesthetic. |
colour.target , color.target
|
A vector of character strings; |
default.alpha |
numeric in [0..1] A transparency value to use for elements not targeted by the alpha aesthetic. |
alpha.target |
A vector of character strings; |
add.segments |
logical Display connecting segments or arrows between original positions and displaced ones if both are available. |
box.padding , point.padding
|
numeric By how much each end of the segments should shortened in mm. |
segment.linewidth |
numeric Width of the segments or arrows in mm. |
min.segment.length |
numeric Segments shorter that the minimum length are not rendered, in mm. |
arrow |
specification for arrow heads, as created by
|
table.theme |
NULL, list or function A gridExtra ttheme defintion, or a constructor for a ttheme or NULL for default. |
table.rownames , table.colnames
|
logical flag to enable or disable printing of row names and column names. |
table.hjust |
numeric Horizontal justification for the core and column headings of the table. |
parse |
If TRUE, the labels will be parsed into expressions and
displayed as described in |
na.rm |
If |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
By default geom_table()
uses position_nudge_center
which is
backwards compatible with position_nudge
but
provides additional control on the direction of the nudging. In contrast to
position_nudge
, position_nudge_center
and all other position functions defined in packages 'ggpp' and 'ggrepel'
keep the original coordinates thus allowing the plotting of connecting
segments and arrows.
This geom works only with tibbles as data
, as its expects a list of
data frames (or tibbles) to be mapped to the label
aesthetic. A
table is built with function gridExtra::gtable
for each data frame
in the list, and formatted according to a table theme or ttheme
. The
character strings in the data frame can be parsed into R expressions so the
inset tables can include maths.
If the argument passed to table.theme
is a constructor function
(passing its name without parenthesis), the values mapped to size
,
colour
, fill
, alpha
, and family
aesthetics will
the passed to this theme constructor for each individual table. In
contrast, if a ready constructed ttheme
stored as a list object is
passed as argument (e.g., by calling the constructor, using constructor
name followed by parenthesis), it will be used as is, i.e., mappings to
aesthetics such as colour
are ignored if present. By default the
constructor ttheme_gtdefault
is used and colour
and
fill
, are mapped to NA
. Mapping these aesthetics to NA
triggers the use of the default base_colour
of the ttheme
. As
the table is built with function gridExtra::gtable()
, for formatting
details, please, consult tableGrob
.
The x
and y
aesthetics determine the position of the whole
inset table, similarly to that of a text label, justification is
interpreted as indicating the position of the inset table with respect to
its horizontal and vertical axes (rows and columns in the
data frame), and angle
is used to rotate the inset table as a whole.
Of these two geoms only geom_grob
supports the plotting of
segments, as geom_grob_npc
uses a coordinate system that is
unrelated to data units and data.In the case of geom_table_npc
,
npcx
and npcy
aesthetics determine the position of the inset
table. Justification as described above for .
A plot layer instance.
You can modify text alignment with the vjust
and
hjust
aesthetics. These can either be a number between 0
(right/bottom) and 1 (top/left) or a character ("left"
,
"middle"
, "right"
, "bottom"
, "center"
,
"top"
). In addition, you can use special alignments for
justification including "position"
, "inward"
and
"outward"
. Inward always aligns text towards the center of the
plotting area, and outward aligns it away from the center of the plotting
area. If tagged with _mean
or _median
(e.g.,
"outward_mean"
) the mean or median of the data in the panel along
the corresponding axis is used as center. If the characters following the
underscore represent a number (e.g., "outward_10.5"
) the reference
point will be this value in data units. Position justification is computed
based on the direction of the displacement of the position of the label so
that each individual text or label is justified outwards from its original
position. The default justification is "position"
.
If no position displacement is applied, or a position function defined in
'ggplot2' is used, these geometries behave similarly to the corresponding
ones from package 'ggplot2' with a default justification of 0.5
and
no segment drawn.
Many layer functions from package 'ggpp' are
designed to work seamlessly with position functions that keep, rather than
discard, the original x
and y
positions in data
when
computing a new displaced position. See position_nudge_keep
,
position_dodge_keep
, position_jitter_keep
,
position_nudge_center
, position_nudge_line
,
position_nudge_to
, position_dodgenudge
,
position_jitternudge
, and position_stacknudge
for examples and details of their use.
The "width" and "height" of an inset as for a text element are 0, so stacking and dodging inset plots will not work by default, and axis limits are not automatically expanded to include all inset plots. Obviously, insets do have height and width, but they are physical units, not data units. The amount of space they occupy on the main plot is not constant in data units of the base plot: when you modify scale limits, inset plots stay the same size relative to the physical size of the base plot.
Complex tables with annotations or different colouring of rows or cells
can be constructed with functions in package 'gridExtra' or in any other
way as long as they can be saved as grid graphical objects and then added
to a ggplot as a new layer with geom_grob
.
This geometry is inspired on answers to two questions in Stackoverflow. In contrast to these earlier examples, the current geom obeys the grammar of graphics, and attempts to be consistent with the behaviour of 'ggplot2' geometries. https://stackoverflow.com/questions/12318120/adding-table-within-the-plotting-region-of-a-ggplot-in-r https://stackoverflow.com/questions/25554548/adding-sub-tables-on-each-panel-of-a-facet-ggplot-in-r?
Formatting of tables stat_fmt_table
,
ttheme_gtdefault
, ttheme_set
,
tableGrob
.
Other geometries adding layers with insets:
geom_plot()
library(dplyr) library(tibble) mtcars %>% group_by(cyl) %>% summarize(wt = mean(wt), mpg = mean(mpg)) %>% ungroup() %>% mutate(wt = sprintf("%.2f", wt), mpg = sprintf("%.1f", mpg)) -> tb df <- tibble(x = 5.45, y = 34, tb = list(tb)) # using defaults ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb)) ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.rownames = TRUE, table.theme = ttheme_gtstripes) # settings aesthetics to constants ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), color = "red", fill = "#FFCCCC", family = "serif", size = 5, angle = 90, vjust = 0) # passing a theme constructor as argument ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtminimal) + theme_classic() df2 <- tibble(x = 5.45, y = c(34, 29, 24), x1 = c(2.29, 3.12, 4.00), y1 = c(26.6, 19.7, 15.1), cyl = c(4, 6, 8), tb = list(tb[1, 1:3], tb[2, 1:3], tb[3, 1:3])) # mapped aesthetics ggplot(mtcars, aes(wt, mpg, color = factor(cyl))) + geom_point() + geom_table(data = df2, inherit.aes = TRUE, mapping = aes(x = x, y = y, label = tb)) # nudging and segments ggplot(mtcars, aes(wt, mpg, color = factor(cyl))) + geom_point(show.legend = FALSE) + geom_table(data = df2, inherit.aes = TRUE, mapping = aes(x = x1, y = y1, label = tb), nudge_x = 0.7, nudge_y = 3, vjust = 0.5, hjust = 0.5, arrow = arrow(length = unit(0.5, "lines"))) + theme_classic() # Using native plot coordinates instead of data coordinates dfnpc <- tibble(x = 0.95, y = 0.95, tb = list(tb)) ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table_npc(data = dfnpc, aes(npcx = x, npcy = y, label = tb))
library(dplyr) library(tibble) mtcars %>% group_by(cyl) %>% summarize(wt = mean(wt), mpg = mean(mpg)) %>% ungroup() %>% mutate(wt = sprintf("%.2f", wt), mpg = sprintf("%.1f", mpg)) -> tb df <- tibble(x = 5.45, y = 34, tb = list(tb)) # using defaults ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb)) ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.rownames = TRUE, table.theme = ttheme_gtstripes) # settings aesthetics to constants ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), color = "red", fill = "#FFCCCC", family = "serif", size = 5, angle = 90, vjust = 0) # passing a theme constructor as argument ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtminimal) + theme_classic() df2 <- tibble(x = 5.45, y = c(34, 29, 24), x1 = c(2.29, 3.12, 4.00), y1 = c(26.6, 19.7, 15.1), cyl = c(4, 6, 8), tb = list(tb[1, 1:3], tb[2, 1:3], tb[3, 1:3])) # mapped aesthetics ggplot(mtcars, aes(wt, mpg, color = factor(cyl))) + geom_point() + geom_table(data = df2, inherit.aes = TRUE, mapping = aes(x = x, y = y, label = tb)) # nudging and segments ggplot(mtcars, aes(wt, mpg, color = factor(cyl))) + geom_point(show.legend = FALSE) + geom_table(data = df2, inherit.aes = TRUE, mapping = aes(x = x1, y = y1, label = tb), nudge_x = 0.7, nudge_y = 3, vjust = 0.5, hjust = 0.5, arrow = arrow(length = unit(0.5, "lines"))) + theme_classic() # Using native plot coordinates instead of data coordinates dfnpc <- tibble(x = 0.95, y = 0.95, tb = list(tb)) ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table_npc(data = dfnpc, aes(npcx = x, npcy = y, label = tb))
Small arrows on plot margins can supplement a 2d display with annotations.
Arrows can be used to highlight specific values along a margin. The geometries
geom_x_margin_arrow()
and geom_y_margin_arrow()
behave
similarly geom_vline()
and geom_hline()
and share their "double
personality" as both annotations and geometries.
geom_x_margin_arrow( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., xintercept, sides = "b", arrow.length = 0.03, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE ) geom_y_margin_arrow( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., yintercept, sides = "l", arrow.length = 0.03, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE )
geom_x_margin_arrow( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., xintercept, sides = "b", arrow.length = 0.03, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE ) geom_y_margin_arrow( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., yintercept, sides = "l", arrow.length = 0.03, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific dataset - only needed if you want to override the plot defaults. |
stat |
The statistical transformation to use on the data for this layer, as a string. |
position |
Position adjustment, either as a string, or the result of a call to a position adjustment function. |
... |
other arguments passed on to |
xintercept , yintercept
|
numeric Parameters that control the position of the marginal points. If these are set, data, mapping and show.legend are overridden. |
sides |
A string that controls which sides of the plot the rugs appear
on. It can be set to a string containing any combination of |
arrow.length |
numeric value expressed in npc units for the length of the arows inwards from the edge of the plotting area. |
na.rm |
If |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
A plot layer instance.
Other Geometries for marginal annotations in ggplots:
geom_x_margin_grob()
,
geom_x_margin_point()
p <- ggplot(mtcars, aes(wt, mpg)) + geom_point() p p + geom_x_margin_arrow(xintercept = 3.5) p + geom_y_margin_arrow(yintercept = c(18, 28, 15)) p + geom_x_margin_arrow(data = data.frame(x = c(2.5, 4.5)), mapping = aes(xintercept = x)) p + geom_x_margin_arrow(data = data.frame(x = c(2.5, 4.5)), mapping = aes(xintercept = x), sides="tb")
p <- ggplot(mtcars, aes(wt, mpg)) + geom_point() p p + geom_x_margin_arrow(xintercept = 3.5) p + geom_y_margin_arrow(yintercept = c(18, 28, 15)) p + geom_x_margin_arrow(data = data.frame(x = c(2.5, 4.5)), mapping = aes(xintercept = x)) p + geom_x_margin_arrow(data = data.frame(x = c(2.5, 4.5)), mapping = aes(xintercept = x), sides="tb")
Margin grobs can supplement a 2d display with annotations. Margin grobs such
as icons or symbols can highlight individual values along a margin. The
geometries geom_x_margin_grob()
and geom_y_margin_grob()
behave
similarly geom_vline()
and geom_hline()
and share their "double
personality" as both annotations and geometries.
geom_x_margin_grob( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., xintercept, sides = "b", grob.shift = 0, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE ) geom_y_margin_grob( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., yintercept, sides = "l", grob.shift = 0, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE )
geom_x_margin_grob( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., xintercept, sides = "b", grob.shift = 0, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE ) geom_y_margin_grob( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., yintercept, sides = "l", grob.shift = 0, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific dataset - only needed if you want to override the plot defaults. |
stat |
The statistical transformation to use on the data for this layer, as a string. |
position |
Position adjustment, either as a string, or the result of a call to a position adjustment function. |
... |
other arguments passed on to |
xintercept , yintercept
|
numeric Parameters that control the position of the marginal points. If these are set, data, mapping and show.legend are overridden. |
sides |
A character string of length one that controls on which side of
the plot the grob annotations appear on. It can be set to a string
containing one of |
grob.shift |
numeric value expressed in npc units for the shift of the marginal grob inwards from the edge of the plotting area. |
na.rm |
If |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
A plot layer instance.
You can modify text alignment with the vjust
and
hjust
aesthetics. These can either be a number between 0
(right/bottom) and 1 (top/left) or a character ("left"
,
"middle"
, "right"
, "bottom"
, "center"
,
"top"
). In addition, you can use special alignments for
justification including "position"
, "inward"
and
"outward"
. Inward always aligns text towards the center of the
plotting area, and outward aligns it away from the center of the plotting
area. If tagged with _mean
or _median
(e.g.,
"outward_mean"
) the mean or median of the data in the panel along
the corresponding axis is used as center. If the characters following the
underscore represent a number (e.g., "outward_10.5"
) the reference
point will be this value in data units. Position justification is computed
based on the direction of the displacement of the position of the label so
that each individual text or label is justified outwards from its original
position. The default justification is "position"
.
If no position displacement is applied, or a position function defined in
'ggplot2' is used, these geometries behave similarly to the corresponding
ones from package 'ggplot2' with a default justification of 0.5
and
no segment drawn.
Many layer functions from package 'ggpp' are
designed to work seamlessly with position functions that keep, rather than
discard, the original x
and y
positions in data
when
computing a new displaced position. See position_nudge_keep
,
position_dodge_keep
, position_jitter_keep
,
position_nudge_center
, position_nudge_line
,
position_nudge_to
, position_dodgenudge
,
position_jitternudge
, and position_stacknudge
for examples and details of their use.
grid-package
, geom_rug
,
and other documentation of package 'ggplot2'.
Other Geometries for marginal annotations in ggplots:
geom_x_margin_arrow()
,
geom_x_margin_point()
# We can add icons to the margin of a plot to signal events
# We can add icons to the margin of a plot to signal events
Margin points can supplement a 2d display with annotations. Margin points
can highlight individual values along a margin. The geometries
geom_x_margin_point()
and geom_y_margin_point()
behave
similarly geom_vline()
and geom_hline()
and share their "double
personality" as both annotations and geometries.
geom_x_margin_point( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., xintercept, sides = "b", point.shift = 0.017, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE ) geom_y_margin_point( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., yintercept, sides = "l", point.shift = 0.017, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE )
geom_x_margin_point( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., xintercept, sides = "b", point.shift = 0.017, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE ) geom_y_margin_point( mapping = NULL, data = NULL, stat = "identity", position = "identity", ..., yintercept, sides = "l", point.shift = 0.017, na.rm = FALSE, show.legend = FALSE, inherit.aes = FALSE )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific dataset - only needed if you want to override the plot defaults. |
stat |
The statistical transformation to use on the data for this layer, as a string. |
position |
Position adjustment, either as a string, or the result of a call to a position adjustment function. |
... |
other arguments passed on to |
xintercept , yintercept
|
numeric Parameters that control the position of the marginal points. If these are set, data, mapping and show.legend are overridden. |
sides |
A string that controls which sides of the plot the rugs appear
on. It can be set to a string containing any combination of |
point.shift |
numeric value expressed in npc units for the shift of the rug points inwards from the edge of the plotting area. |
na.rm |
If |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
A plot layer instance.
Other Geometries for marginal annotations in ggplots:
geom_x_margin_arrow()
,
geom_x_margin_grob()
p <- ggplot(mtcars, aes(wt, mpg)) + geom_point() p p + geom_x_margin_point(xintercept = 3.5) p + geom_y_margin_point(yintercept = c(18, 28, 15)) p + geom_x_margin_point(data = data.frame(x = c(2.5, 4.5)), mapping = aes(xintercept = x)) p + geom_x_margin_point(data = data.frame(x = c(2.5, 4.5)), mapping = aes(xintercept = x), sides = "tb")
p <- ggplot(mtcars, aes(wt, mpg)) + geom_point() p p + geom_x_margin_point(xintercept = 3.5) p + geom_y_margin_point(yintercept = c(18, 28, 15)) p + geom_x_margin_point(data = data.frame(x = c(2.5, 4.5)), mapping = aes(xintercept = x)) p + geom_x_margin_point(data = data.frame(x = c(2.5, 4.5)), mapping = aes(xintercept = x), sides = "tb")
ggplot()
initializes a ggplot object. It can be used to
declare the input spectral object for a graphic and to optionally specify the
set of plot aesthetics intended to be common throughout all
subsequent layers unless specifically overridden.
## S3 method for class 'ts' ggplot( data, mapping = NULL, ..., time.resolution = "day", as.numeric = TRUE, environment = parent.frame() ) ## S3 method for class 'xts' ggplot( data, mapping = NULL, ..., time.resolution = "day", as.numeric = TRUE, environment = parent.frame() )
## S3 method for class 'ts' ggplot( data, mapping = NULL, ..., time.resolution = "day", as.numeric = TRUE, environment = parent.frame() ) ## S3 method for class 'xts' ggplot( data, mapping = NULL, ..., time.resolution = "day", as.numeric = TRUE, environment = parent.frame() )
data |
Default spectrum dataset to use for plot. If not a spectrum, the
methods used will be those defined in package |
mapping |
Default list of aesthetic mappings to use for plot. If not specified, in the case of spectral objects, a default mapping will be used. |
... |
Other arguments passed on to methods. Not currently used. |
time.resolution |
character The time unit to which the returned time values will be rounded. |
as.numeric |
logical If TRUE convert time to numeric, expressed as fractional calendar years. |
environment |
If an variable defined in the aesthetic mapping is not
found in the data, ggplot will look for it in this environment. It defaults
to using the environment in which |
ggplot()
is typically used to construct a plot
incrementally, using the + operator to add layers to the
existing ggplot object. This is advantageous in that the
code is explicit about which layers are added and the order
in which they are added. For complex graphics with multiple
layers, initialization with ggplot
is recommended.
There are three common ways to invoke ggplot
:
ggplot(ts, aes(x, y, <other aesthetics>))
ggplot(ts)
The first method is recommended if all layers use the same data and the same set of aesthetics, although this method can also be used to add a layer using data from another data frame. See the first example below. The second method specifies the default spectrum object to use for the plot, and the units to be used for y in the plot, but no aesthetics are defined up front. This is useful when one data frame is used predominantly as layers are added, but the aesthetics may vary from one layer to another. The third method specifies the default spectrum object to use for the plot, but no aesthetics are defined up front. This is useful when one spectrum is used predominantly as layers are added, but the aesthetics may vary from one layer to another.
A "ggplot"
object.
Current implementation does not merge default mapping with user supplied mapping. If user supplies a mapping, it is used as is. To add to the default mapping, aes() can be used by itself to compose the ggplot.
ggplot(lynx) + geom_line()
ggplot(lynx) + geom_line()
A dataset containing photosynthesis measurements on four ivy plants.
ivy.df
ivy.df
A data.frame
object with 36 rows and 6 variables.
For each plant a light response curve of photosynthesis was measured using a custom-built system and software that allowed controlling the concentrations of water vapour and carbon dioxide at the surface of the leaves, i.e., inside the air boundary layer.
Aphalo, P. J. (1991) Interactions in Stomatal Function. PhD thesis, University of Edinburgh. http://hdl.handle.net/1842/14758.
Other Plant growth and morphology data:
birch.df
colnames(ivy.df) head(ivy.df)
colnames(ivy.df) head(ivy.df)
position_dodgenudge()
combines into one function the action of
position_dodge
and
position_nudge
and position_dodge2nudge()
combines into one function the action of
position_dodge2
and
position_nudge
. They are useful when labelling plots
such as grouped bars, columns, etc. and when adding dodged to text labels
linked to observations plotted without dodge. It can replace other position
functions as it is backwards compatible. Like all other position functions in
'ggpp' and 'ggrepel' it preserves the initial position to allow drawing of
segments or arrow linking the original position to the displaced one.
position_dodgenudge( width = 1, preserve = c("total", "single"), x = 0, y = 0, direction = c("none", "split", "split.x", "split.y", "center"), kept.origin = c("dodged", "original", "none") ) position_dodge_keep( width = 1, preserve = c("total", "single"), kept.origin = "original" ) position_dodge2_keep( width = 1, preserve = c("total", "single"), kept.origin = "original" ) position_dodge2nudge( width = 1, preserve = c("total", "single"), padding = 0.1, reverse = FALSE, x = 0, y = 0, direction = c("none", "split", "split.x", "split.y", "center"), kept.origin = c("dodged", "original", "none") )
position_dodgenudge( width = 1, preserve = c("total", "single"), x = 0, y = 0, direction = c("none", "split", "split.x", "split.y", "center"), kept.origin = c("dodged", "original", "none") ) position_dodge_keep( width = 1, preserve = c("total", "single"), kept.origin = "original" ) position_dodge2_keep( width = 1, preserve = c("total", "single"), kept.origin = "original" ) position_dodge2nudge( width = 1, preserve = c("total", "single"), padding = 0.1, reverse = FALSE, x = 0, y = 0, direction = c("none", "split", "split.x", "split.y", "center"), kept.origin = c("dodged", "original", "none") )
width |
Dodging width, when different to the width of the individual elements. This is useful when you want to align narrow geoms with wider geoms. See the examples. |
preserve |
Should dodging preserve the total width of all elements at a position, or the width of a single element?. |
x , y
|
Amount of vertical and horizontal distance to move. A numeric vector of length 1, or of the same length as rows there are in 'data', with nudge values in data rows order. |
direction |
One of |
kept.origin |
One of |
padding |
Padding between elements at the same position. Elements are shrunk by this proportion to allow space between them. Defaults to 0.1. |
reverse |
If TRUE, will reverse the default stacking order. This is useful if you're rotating both the plot and legend. |
The applied dodge is identical to that by
position_dodge
or
position_dodge2
while nudging is similar to that by
position_nudge
.
There are two posible uses for these functions. First they can be used to
label dodged bars or boxplots. In this case, it is mandatory to use the same
argument to width
when passing position_dodge()
to
geom_col()
and position_dodgenudge()
to geom_text()
or
geom_label()
or their repulsive equivalents. Otherwise the arrows or
segments will fail to connect to the labels. In other words jittering is
computed twice. Jitter should be identical with the same arguments as
position_dodgenudge()
as this last function simply call the same code
from package 'ggplot2'.
The second use is to dodge labels to be connected to elements that have not
been jittered. The return of original positions instead of the dodged
ones is achieved by passing origin = "original"
instead of the default
of origin = "dodged"
.
A "Position"
object.
Michał Krassowski, edited by Pedro J. Aphalo.
https://github.com/slowkow/ggrepel/issues/161.
position_nudge
,
position_nudge_repel
.
Other position adjustments:
position_jitternudge()
,
position_nudge_center()
,
position_nudge_keep()
,
position_nudge_line()
,
position_nudge_to()
,
position_stacknudge()
df <- data.frame(x1 = c(1, 2, 1, 3, -1), x2 = c("a", "a", "b", "b", "b"), grp = c("some long name", "other name", "some name", "another name", "some long name")) # Add labels to a horizontal column plot (stacked by default) ggplot(data = df, aes(x1, x2, group = grp)) + geom_col(aes(fill = grp), width = 0.8, position = position_dodge()) + geom_vline(xintercept = 0) + geom_text( aes(label = grp), position = position_dodgenudge(x = 0.09, direction = "split", width = 0.8), angle = 90, size = 3) + theme(legend.position = "none") ggplot(data = df, aes(x2, x1, group = grp)) + geom_col(aes(fill = grp), width = 0.75, position = position_dodge(width = 0.75)) + geom_vline(xintercept = 0) + geom_text(aes(label = grp), position = position_dodgenudge(y = 0.1, direction = "split", width = 0.75), size = 3) + theme(legend.position = "none")
df <- data.frame(x1 = c(1, 2, 1, 3, -1), x2 = c("a", "a", "b", "b", "b"), grp = c("some long name", "other name", "some name", "another name", "some long name")) # Add labels to a horizontal column plot (stacked by default) ggplot(data = df, aes(x1, x2, group = grp)) + geom_col(aes(fill = grp), width = 0.8, position = position_dodge()) + geom_vline(xintercept = 0) + geom_text( aes(label = grp), position = position_dodgenudge(x = 0.09, direction = "split", width = 0.8), angle = 90, size = 3) + theme(legend.position = "none") ggplot(data = df, aes(x2, x1, group = grp)) + geom_col(aes(fill = grp), width = 0.75, position = position_dodge(width = 0.75)) + geom_vline(xintercept = 0) + geom_text(aes(label = grp), position = position_dodgenudge(y = 0.1, direction = "split", width = 0.75), size = 3) + theme(legend.position = "none")
position_jitternudge()
combines into one function the action of
position_jitter
and
position_nudge
. It is useful when labels to jittered
plots and when adding jitter to text labels linked to points plotted without
jitter. It can replace other position functions as it is backwards
compatible. Like all other position functions in 'ggpp' and 'ggrepel' it
preserves the initial position to allow drawing of segments or arrow linking
the original position to the displaced one.
position_jitternudge( width = NULL, height = NULL, seed = NA, x = 0, y = 0, direction = c("as.is", "alternate", "split"), nudge.from = c("original", "original.x", "original.y", "jittered", "jittered.y", "jittered.x"), kept.origin = c("jittered", "original", "none") ) position_jitter_keep( width = NULL, height = NULL, seed = NA, kept.origin = "original" )
position_jitternudge( width = NULL, height = NULL, seed = NA, x = 0, y = 0, direction = c("as.is", "alternate", "split"), nudge.from = c("original", "original.x", "original.y", "jittered", "jittered.y", "jittered.x"), kept.origin = c("jittered", "original", "none") ) position_jitter_keep( width = NULL, height = NULL, seed = NA, kept.origin = "original" )
width , height
|
Amount of vertical and horizontal jitter. The jitter is added in both positive and negative directions, so the total spread is twice the value specified here. If omitted, defaults to 40 resolution of the data: this means the jitter values will occupy 80 implied bins. Categorical data is aligned on the integers, so a width or height of 0.5 will spread the data so it's not possible to see the distinction between the categories. |
seed |
A random seed to make the jitter reproducible. Useful if you need
to apply the same jitter twice, e.g., for a point and a corresponding
label. The random seed is reset after jittering. If |
x , y
|
Amount of vertical and horizontal distance to move. A numeric
vector of length 1, or of the same length as rows there are in |
direction |
One of |
nudge.from |
One of |
kept.origin |
One of |
Jitter with position_jitternudge()
is identical to that with
position_jitter
while nudging is enhanced compared
to position_nudge
by taking into use cases specific
to the combination of jitter and nudge.
There are two posible uses for this function. First it can be used to label
jittered points in a plot. In this case, it is mandatory to use the same
arguments to width
, height
and seed
when passing
position_jitter()
to geom_point()
and
position_jitternudge()
to geom_text()
or to
geom_label()
or their repulsive equivalents. Otherwise the arrows or
segments will fail to connect to the labels. In other words jittering is
computed twice. Jitter should be identical with the same arguments as
position_jitternudge()
as this last function calls the same code
imported from package 'ggplot2'.
The second use is to jitter labels to be connected to points that have not
been jittered. The return of original positions instead of the jittered
ones is achieved by passing origin = "original"
to override the
default origin = "jittered"
.
A "Position"
object. The layer function within it returns a
data frame, with the jittered + nudged values in columns x
and
y
and by default the jittered values with no nudging as
x_orig
and y_orig
. With nudge.from = "original"
the
original values with no jitter and no nudge applied are returned as
x_orig
and y_orig
.
When direction = "split"
is used together with no jitter, the
split to left and right, or up and down is done at random.
Michał Krassowski, edited by Pedro J. Aphalo.
https://github.com/slowkow/ggrepel/issues/161.
position_jitter
,
position_nudge
,
position_nudge_repel
.
Other position adjustments:
position_dodgenudge()
,
position_nudge_center()
,
position_nudge_keep()
,
position_nudge_line()
,
position_nudge_to()
,
position_stacknudge()
jitter <- position_jitter(width = 0.2, height = 2, seed = 123) jitter_nudge <- position_jitternudge(width = 0.2, height = 2, seed = 123, x = 0.1, direction = "split", nudge.from = "jittered") ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point(position = jitter) + geom_text_s(position = jitter_nudge) jitter_nudge <- position_jitternudge(width = 0.2, height = 2, seed = 123, x = 0.35, direction = "split", nudge.from = "original.x") ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point(position = jitter) + geom_text_s(position = jitter_nudge) jitter <- position_jitter(width = 0, height = 2, seed = 123) jitter_nudge <- position_jitternudge(width = 0, height = 2, seed = 123, x = 0.4, direction = "split", nudge.from = "original.x") ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point(position = jitter) + geom_text_s(position = jitter_nudge) jitter_nudge <- position_jitternudge(width = 0, height = 2, seed = 123, x = 0.4, direction = "alternate", nudge.from = "original.x") ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point(position = jitter) + geom_text_s(position = jitter_nudge) # No nudge, show how points have moved with jitter ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point() + geom_point_s(position = position_jitter_keep(width = 0.3, height = 2, seed = 123), color = "red", arrow = grid::arrow(length = unit(0.4, "lines")))
jitter <- position_jitter(width = 0.2, height = 2, seed = 123) jitter_nudge <- position_jitternudge(width = 0.2, height = 2, seed = 123, x = 0.1, direction = "split", nudge.from = "jittered") ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point(position = jitter) + geom_text_s(position = jitter_nudge) jitter_nudge <- position_jitternudge(width = 0.2, height = 2, seed = 123, x = 0.35, direction = "split", nudge.from = "original.x") ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point(position = jitter) + geom_text_s(position = jitter_nudge) jitter <- position_jitter(width = 0, height = 2, seed = 123) jitter_nudge <- position_jitternudge(width = 0, height = 2, seed = 123, x = 0.4, direction = "split", nudge.from = "original.x") ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point(position = jitter) + geom_text_s(position = jitter_nudge) jitter_nudge <- position_jitternudge(width = 0, height = 2, seed = 123, x = 0.4, direction = "alternate", nudge.from = "original.x") ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point(position = jitter) + geom_text_s(position = jitter_nudge) # No nudge, show how points have moved with jitter ggplot(mpg[1:20, ], aes(cyl, hwy, label = drv)) + geom_point() + geom_point_s(position = position_jitter_keep(width = 0.3, height = 2, seed = 123), color = "red", arrow = grid::arrow(length = unit(0.4, "lines")))
position_nudge_center()
is generally useful for adjusting the position of
labels or text, both on a discrete or continuous scale. In contrast to
position_nudge
, position_nudge_center()
returns in data
both
the original coordinates and the nudged coordinates.
position_nudge_center( x = 0, y = 0, center_x = NULL, center_y = NULL, direction = NULL, obey_grouping = NULL, kept.origin = c("original", "none") ) position_nudge_centre( x = 0, y = 0, center_x = NULL, center_y = NULL, direction = NULL, obey_grouping = NULL, kept.origin = c("original", "none") )
position_nudge_center( x = 0, y = 0, center_x = NULL, center_y = NULL, direction = NULL, obey_grouping = NULL, kept.origin = c("original", "none") ) position_nudge_centre( x = 0, y = 0, center_x = NULL, center_y = NULL, direction = NULL, obey_grouping = NULL, kept.origin = c("original", "none") )
x , y
|
Amount of vertical and horizontal distance to move. A numeric
vector, that is recycled if shorter than the number of rows in |
center_x , center_y
|
The coordinates of the virtual origin out from which
nudging radiates or splits in opposite directions. A numeric vector of
length 1 or of the same length as rows there are in |
direction |
One of |
obey_grouping |
A logical flag indicating whether to obey or not groupings of the observations. By default, grouping is obeyed when both of the variables mapped to x and y are continuous numeric and ignored otherwise. |
kept.origin |
One of |
This position function is backwards compatible with position_nudge
but extends it by adding support for nudging that varies across the plotting
region, either in opposite directions or radially from a virtual center
point.
Positive values as arguments to x
and y
are added to
the original position along either axis. If no arguments are passed to
center_x
, center_y
or direction
, the nudging is
applied as is, as is the case if direction = "none"
. If
non-NULL
arguments are passed to both center_x
and
center_y
, direction = "radial"
is assumed. In this case, if
x
and/or y
positive nudging is applied radially outwards from
the center, while if negative, inwards towards the center. When a
non-NULL
argument is passed only to one of center_x
or
center_y
, direction = "split"
is assumed. In this case when
the initial location of the point is to the left of center_x
,
-x
is used instead of x
for nudging, and when the initial
location of the point is to the below of center_y
, -y
is used
instead of y
for nudging. If non-NULL
arguments are passed to
both center_x
and center_y
, and direction
is passed
"split"
as argument, then the split as described above is applied to
both to x and y coordinates.
A "Position"
object.
Some situations are handled as special cases. When direction =
"split"
or direction = "radial"
, observations at exactly the _center_
are nudged using x
and y
unchanged. Whendirection = "split"
,
and
both center_x
and center_y
have been supplied, segments are drawn at
eight different possible angles. When segments are exactly horizontal or
vertical they would be shorter than when drawn at the other four angles, in
which case x
or y
are adjusted to ensure these segments are of the same
lengths as those at other angles.
This position is most useful when labelling points forming a cloud or grouped along vertical or horizontal lines or "divides".
[ggplot2::position_nudge()], [ggrepel::position_nudge_repel()].
Other position adjustments:
position_dodgenudge()
,
position_jitternudge()
,
position_nudge_keep()
,
position_nudge_line()
,
position_nudge_to()
,
position_stacknudge()
df <- data.frame( x = c(1,3,2,5,4,2.5), y = c("abc","cd","d","c","bcd","a") ) # Plain nudging, same as with ggplot2::position_nudge() ggplot(df, aes(x, y, label = y)) + geom_point() + geom_text_s(hjust = "left", vjust = "bottom", position = position_nudge(x = 0.2, y = 0.2)) ggplot(df, aes(x, y, label = y)) + geom_point() + geom_text_s(add.segments = FALSE, position = position_nudge_center(x = 0.2, y = 0.2) ) # "split" nudging ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), add.segments = FALSE, position = position_nudge_center(x = 0.2, y = 0.2, direction = "split")) ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), position = position_nudge_center(x = 0.4, direction = "split")) ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), position = position_nudge_center(y = 0.2, direction = "split")) ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), position = position_nudge_center(x = 0.2, y = 0.3, center_y = 2, center_x = 1.5, direction = "split")) ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), position = position_nudge_center(x = 0.06, y = 0.08, center_y = 2)) ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), position = position_nudge_center(x = 0.1, center_x = 2.51)) ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), position = position_nudge_center(x = 0.06, y = 0.08, center_x = median, center_y = median, direction = "split")) # "Radial" nudging ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), position = position_nudge_center(x = 0.1, y = 0.2, direction = "radial")) ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), position = position_nudge_center(x = -0.1, y = -0.1, direction = "radial")) df <- data.frame( x = -10:10, z = (-10:10)^2, y = letters[1:21], group = rep(c("a", "b"), rep(c(11, 10))) ) ggplot(df, aes(x, z)) + geom_point() + geom_line() + geom_text_s(aes(label = y), position = position_nudge_center(x = 0.9, y = 2.7, center_x = mean, center_y = max)) ggplot(df, aes(x, z, color = group)) + geom_point() + geom_line(color = "black", linetype = "dotted") + geom_text_s(aes(label = y), position = position_nudge_center(x = -1.2, y = -3, center_x = 0, center_y = "above_max")) ggplot(df, aes(x, z, color = group)) + geom_point() + geom_line(color = "black", linetype = "dotted") + geom_text(aes(label = y), vjust = "inward", hjust = "inward", position = position_nudge_center(x = -0.9, y = -2.7, center_x = mean, center_y = max, obey_grouping = FALSE))
df <- data.frame( x = c(1,3,2,5,4,2.5), y = c("abc","cd","d","c","bcd","a") ) # Plain nudging, same as with ggplot2::position_nudge() ggplot(df, aes(x, y, label = y)) + geom_point() + geom_text_s(hjust = "left", vjust = "bottom", position = position_nudge(x = 0.2, y = 0.2)) ggplot(df, aes(x, y, label = y)) + geom_point() + geom_text_s(add.segments = FALSE, position = position_nudge_center(x = 0.2, y = 0.2) ) # "split" nudging ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), add.segments = FALSE, position = position_nudge_center(x = 0.2, y = 0.2, direction = "split")) ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), position = position_nudge_center(x = 0.4, direction = "split")) ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), position = position_nudge_center(y = 0.2, direction = "split")) ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), position = position_nudge_center(x = 0.2, y = 0.3, center_y = 2, center_x = 1.5, direction = "split")) ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), position = position_nudge_center(x = 0.06, y = 0.08, center_y = 2)) ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), position = position_nudge_center(x = 0.1, center_x = 2.51)) ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), position = position_nudge_center(x = 0.06, y = 0.08, center_x = median, center_y = median, direction = "split")) # "Radial" nudging ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), position = position_nudge_center(x = 0.1, y = 0.2, direction = "radial")) ggplot(df, aes(x, y)) + geom_point() + geom_text_s(aes(label = y), position = position_nudge_center(x = -0.1, y = -0.1, direction = "radial")) df <- data.frame( x = -10:10, z = (-10:10)^2, y = letters[1:21], group = rep(c("a", "b"), rep(c(11, 10))) ) ggplot(df, aes(x, z)) + geom_point() + geom_line() + geom_text_s(aes(label = y), position = position_nudge_center(x = 0.9, y = 2.7, center_x = mean, center_y = max)) ggplot(df, aes(x, z, color = group)) + geom_point() + geom_line(color = "black", linetype = "dotted") + geom_text_s(aes(label = y), position = position_nudge_center(x = -1.2, y = -3, center_x = 0, center_y = "above_max")) ggplot(df, aes(x, z, color = group)) + geom_point() + geom_line(color = "black", linetype = "dotted") + geom_text(aes(label = y), vjust = "inward", hjust = "inward", position = position_nudge_center(x = -0.9, y = -2.7, center_x = mean, center_y = max, obey_grouping = FALSE))
The function position_nudge_keep()
has an additional parameters
compared to position_nudge
, obey_grouping
and
by default the same behaviour when the values passed as arguments to x
and y
have length one.
position_nudge_keep( x = 0, y = 0, obey_grouping = NULL, kept.origin = c("original", "none") )
position_nudge_keep( x = 0, y = 0, obey_grouping = NULL, kept.origin = c("original", "none") )
x , y
|
Amount of vertical and horizontal distance to move. A numeric
vector of length 1, or of the same length as rows there are in |
obey_grouping |
A logical flag indicating whether to obey or not groupings of the observations. By default, grouping is obeyed when both of the variables mapped to x and y are continuous numeric and ignored otherwise. |
kept.origin |
One of |
When x
or y
have length > 1, they are treated
specially. If the lengths is the same as there are rows in data, the nudges
are applied in the order of the rows in data. When they are shorter, they
are recycled and applied to the data values after ordering. This makes it
possible to have alternating mudging right and left or up and down. If
obey_grouping = TRUE
is passed in the call, the alternation will
take place within groups.
As other position functions from package 'ggpp', position_nudge_keep()
by default renames and keeps the original positions of the observations in
data
making it possible to draw connecting segments or conencting
arrows.
A "Position"
object.
Irrespective of the action, the ordering of rows in data
is
preserved.
Other position adjustments:
position_dodgenudge()
,
position_jitternudge()
,
position_nudge_center()
,
position_nudge_line()
,
position_nudge_to()
,
position_stacknudge()
df <- data.frame( x = c(1,3,2,5,4,2.5), y = c("abc","cd","d","c","bcd","a") ) # Plain nudging, same as with ggplot2::position_nudge() ggplot(df, aes(x, y, label = y)) + geom_point() + geom_text_s(hjust = "left", vjust = "bottom", position = position_nudge_keep(x = 0.2, y = 0.2)) # alternating nudging ggplot(df, aes(x, y, label = y)) + geom_point() + geom_text_s(position = position_nudge_keep(x = c(0.2, -0.2))) # direct nudging ggplot(df, aes(x, y, label = y)) + geom_point() + geom_text_s(position = position_nudge_keep(x = rep_len(c(0.2, -0.2), 6)))
df <- data.frame( x = c(1,3,2,5,4,2.5), y = c("abc","cd","d","c","bcd","a") ) # Plain nudging, same as with ggplot2::position_nudge() ggplot(df, aes(x, y, label = y)) + geom_point() + geom_text_s(hjust = "left", vjust = "bottom", position = position_nudge_keep(x = 0.2, y = 0.2)) # alternating nudging ggplot(df, aes(x, y, label = y)) + geom_point() + geom_text_s(position = position_nudge_keep(x = c(0.2, -0.2))) # direct nudging ggplot(df, aes(x, y, label = y)) + geom_point() + geom_text_s(position = position_nudge_keep(x = rep_len(c(0.2, -0.2), 6)))
position_nudge_line()
is generally useful for adjusting the starting
position of labels or text to be repelled while preserving the original
position as the start of the segments. The difference compared to
position_nudge_center
is that the nudging is away from from a
line or curve fitted to the data points or supplied as coefficients. While
position_nudge_center()
is most useful for "round-shaped", vertically-
or horizontally elongated clouds of points, position_nudge_line()
is
most suitable when observations follow a linear or curvilinear relationship
between x and y values. In contrast to
position_nudge
, position_nudge_line()
returns
in 'data' both the original coordinates and the nudged coordinates.
position_nudge_line( x = NA_real_, y = NA_real_, xy_relative = c(0.03, 0.03), abline = NULL, method = NULL, formula = y ~ x, direction = c("automatic", "none", "split"), line_nudge = 1, kept.origin = c("original", "none") )
position_nudge_line( x = NA_real_, y = NA_real_, xy_relative = c(0.03, 0.03), abline = NULL, method = NULL, formula = y ~ x, direction = c("automatic", "none", "split"), line_nudge = 1, kept.origin = c("original", "none") )
x , y
|
Amount of vertical and horizontal distance to move. A numeric vector of length 1 or longer. |
xy_relative |
Nudge relative to x and y data expanse, ignored unless
|
abline |
a vector of length two giving the intercept and slope. |
method |
One of |
formula |
A model formula for |
direction |
One of |
line_nudge |
A positive multiplier >= 1, increasing nudging away from the curve or line compared to nudging from points. |
kept.origin |
One of |
The default amount of nudging is 3
x and y axes, which in most cases is good. In most cases it is best to
apply nudging along a direction perpendicular to the line or curve, if this
is the aim, passing an argument to only one of x
, y
or
xy_relative
will be enough. When direction = "split"
nudging
is away from an implicit line or curve on either side with positive
nudging. The line or curve can be smooth spline or linear regression fitted
on-the-fly to the data points, or a straight line defined by its
coefficients passed to abline
. The fitting is well defined only if
the observations fall roughly on a curve or straight line that is monotonic
in y
. By means of line_nudge
one can increment nudging away
from the line or curve compared to away from the points, which is useful
for example to keep labels outside of a confidence band. Direction defaults
to "split"
when line_nudge
> 1, and otherwise to
"none"
.
A "Position"
object.
For method = "lm"
only model formulas corresponding to
polynomials with no missing terms are supported. If usingpoly
in the model formula, raw = TRUE
is required.
In practice, x
and y
should have the same sign for nudging to
work correctly.
This position is most useful when labeling points conforming a cloud along an arbitrary curve or line.
position_nudge
,
position_nudge_repel
.
Other position adjustments:
position_dodgenudge()
,
position_jitternudge()
,
position_nudge_center()
,
position_nudge_keep()
,
position_nudge_to()
,
position_stacknudge()
set.seed(16532) df <- data.frame( x = -10:10, y = (-10:10)^2, yy = (-10:10)^2 + rnorm(21, 0, 4), yyy = (-10:10) + rnorm(21, 0, 4), l = letters[1:21] ) # Setting the nudging distance ggplot(df, aes(x, y, label = l)) + geom_line(linetype = "dotted") + geom_point() + geom_text(position = position_nudge_line()) ggplot(df, aes(x, y, label = l)) + geom_line(linetype = "dotted") + geom_point() + geom_text_s(position = position_nudge_line()) ggplot(df, aes(x, y, label = l)) + geom_line(linetype = "dotted") + geom_point() + geom_text(position = position_nudge_line(xy_relative = -0.03)) ggplot(df, aes(x, y, label = l)) + geom_line(linetype = "dotted") + geom_point() + geom_text(position = position_nudge_line(x = 0.6, y = 3.2)) ggplot(df, aes(x, y, label = l)) + geom_line(linetype = "dotted") + geom_point() + geom_text(position = position_nudge_line(x = -0.6, y = -4)) # Other curves, using defaults ggplot(df, aes(x, -y, label = l)) + geom_line(linetype = "dotted") + geom_point() + geom_text(position = position_nudge_line()) ggplot(subset(df, x >= 0), aes(y, sqrt(y), label = l)) + geom_line(linetype = "dotted") + geom_point() + geom_text(position = position_nudge_line()) # Points scattered near a curve or line, we use 'direction = "split"' ggplot(df, aes(x)) + geom_line(aes(y = y), linetype = "dotted") + geom_point(aes(y = yy)) + geom_text(aes(y = yy, label = l), position = position_nudge_line(direction = "split")) ggplot(subset(df, x >= 0), aes(y, yy)) + stat_smooth(method = "lm", formula = y ~ x) + geom_point() + geom_text(aes(label = l), position = position_nudge_line(direction = "split")) # increasing the nudging for labels near the line ggplot(subset(df, x >= 0), aes(y, yy)) + stat_smooth(method = "lm", formula = y ~ x) + geom_point() + geom_text(aes(label = l), position = position_nudge_line(line_nudge = 2, direction = "split")) # fitting a linear model instead of the default spline ggplot(subset(df, x >= 0), aes(y, yy)) + stat_smooth(method = "lm", formula = y ~ x) + geom_point() + geom_text(aes(label = l), position = position_nudge_line(method = "lm", direction = "split")) ggplot(subset(df, x >= 0), aes(x, x^2)) + stat_smooth(method = "lm", formula = y ~ poly(x, 2, raw = TRUE)) + geom_point() + geom_text(aes(label = l), position = position_nudge_line(method = "lm", formula = y ~ poly(x, 2, raw = TRUE)))
set.seed(16532) df <- data.frame( x = -10:10, y = (-10:10)^2, yy = (-10:10)^2 + rnorm(21, 0, 4), yyy = (-10:10) + rnorm(21, 0, 4), l = letters[1:21] ) # Setting the nudging distance ggplot(df, aes(x, y, label = l)) + geom_line(linetype = "dotted") + geom_point() + geom_text(position = position_nudge_line()) ggplot(df, aes(x, y, label = l)) + geom_line(linetype = "dotted") + geom_point() + geom_text_s(position = position_nudge_line()) ggplot(df, aes(x, y, label = l)) + geom_line(linetype = "dotted") + geom_point() + geom_text(position = position_nudge_line(xy_relative = -0.03)) ggplot(df, aes(x, y, label = l)) + geom_line(linetype = "dotted") + geom_point() + geom_text(position = position_nudge_line(x = 0.6, y = 3.2)) ggplot(df, aes(x, y, label = l)) + geom_line(linetype = "dotted") + geom_point() + geom_text(position = position_nudge_line(x = -0.6, y = -4)) # Other curves, using defaults ggplot(df, aes(x, -y, label = l)) + geom_line(linetype = "dotted") + geom_point() + geom_text(position = position_nudge_line()) ggplot(subset(df, x >= 0), aes(y, sqrt(y), label = l)) + geom_line(linetype = "dotted") + geom_point() + geom_text(position = position_nudge_line()) # Points scattered near a curve or line, we use 'direction = "split"' ggplot(df, aes(x)) + geom_line(aes(y = y), linetype = "dotted") + geom_point(aes(y = yy)) + geom_text(aes(y = yy, label = l), position = position_nudge_line(direction = "split")) ggplot(subset(df, x >= 0), aes(y, yy)) + stat_smooth(method = "lm", formula = y ~ x) + geom_point() + geom_text(aes(label = l), position = position_nudge_line(direction = "split")) # increasing the nudging for labels near the line ggplot(subset(df, x >= 0), aes(y, yy)) + stat_smooth(method = "lm", formula = y ~ x) + geom_point() + geom_text(aes(label = l), position = position_nudge_line(line_nudge = 2, direction = "split")) # fitting a linear model instead of the default spline ggplot(subset(df, x >= 0), aes(y, yy)) + stat_smooth(method = "lm", formula = y ~ x) + geom_point() + geom_text(aes(label = l), position = position_nudge_line(method = "lm", direction = "split")) ggplot(subset(df, x >= 0), aes(x, x^2)) + stat_smooth(method = "lm", formula = y ~ poly(x, 2, raw = TRUE)) + geom_point() + geom_text(aes(label = l), position = position_nudge_line(method = "lm", formula = y ~ poly(x, 2, raw = TRUE)))
position_nudge_to()
is generally useful for adjusting the position of
labels or text, both on a discrete or continuous scale.
position_nudge_to()
differs from position_nudge
in that the coordinates of the new position are given directly, rather than
as a displacement from the original location. It optionally sets an even
distance among positions. As other position functions in this package, it
preserves the original position to allow the text to be linked back to its
original position with a segment or arrow.
position_nudge_to( x = NULL, y = NULL, x.action = c("none", "spread"), y.action = c("none", "spread"), x.distance = "equal", y.distance = "equal", x.expansion = 0, y.expansion = 0, kept.origin = c("original", "none") )
position_nudge_to( x = NULL, y = NULL, x.action = c("none", "spread"), y.action = c("none", "spread"), x.distance = "equal", y.distance = "equal", x.expansion = 0, y.expansion = 0, kept.origin = c("original", "none") )
x , y
|
Coordinates of the destination position. A vector of mode
|
x.action , y.action
|
character string, one of |
x.distance , y.distance
|
character or numeric Currently only |
x.expansion , y.expansion
|
numeric vectors of length 1 or 2, as a fraction of width of the range. |
kept.origin |
One of |
The nudged to x
and/or y
values replace the original ones in
data
, while the original coordinates are returned in x_orig
and y_orig
. Values supported are those of mode numeric,
thus including dates and times.
If the length of x
and/or y
is more than one but less than
rows are present in the data, the vector is both recycled and reordered so
that the nudges are applied sequentially based on the data values. If their
length matches the number of rows in data, they are assumed to be already
in data order.
A "Position"
object.
Irrespective of the action, the ordering of rows in data
is
preserved.
position_nudge
,
position_nudge_repel
.
Other position adjustments:
position_dodgenudge()
,
position_jitternudge()
,
position_nudge_center()
,
position_nudge_keep()
,
position_nudge_line()
,
position_stacknudge()
df <- data.frame( x = c(1,3,2,5,4,2.5), y = c(2, 1, 2.5, 1.8, 2.8, 1.5), label = c("abc","cd","d","c","bcd","a") ) # default does nothing ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text(position = position_nudge_to()) # a single y (or x) value nudges all observations to this data value ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text(position = position_nudge_to(y = 3)) # with a suitable geom, segments or arrows can be added ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = 3)) # alternating in y value order because y has fewer values than rows in data ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = c(3, 0))) ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = c(0, 3))) # in data row order because y has as many values as rows in data ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = rep_len(c(0, 3), 6))) # spread the values at equal distance within the available space ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = 3, x.action = "spread")) # spread the values at equal distance within the expanded available space ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = 3, x.action = "spread", x.expansion = 0.1)) # spread the values at equal distance within the contracted available space ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = 3, x.action = "spread", x.expansion = -0.1)) # spread the values at equal distance within the range given by x ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = 3, x = c(2,4), x.action = "spread"), hjust = "center") ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = 3, x = c(0,6), x.action = "spread"), hjust = "center")
df <- data.frame( x = c(1,3,2,5,4,2.5), y = c(2, 1, 2.5, 1.8, 2.8, 1.5), label = c("abc","cd","d","c","bcd","a") ) # default does nothing ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text(position = position_nudge_to()) # a single y (or x) value nudges all observations to this data value ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text(position = position_nudge_to(y = 3)) # with a suitable geom, segments or arrows can be added ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = 3)) # alternating in y value order because y has fewer values than rows in data ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = c(3, 0))) ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = c(0, 3))) # in data row order because y has as many values as rows in data ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = rep_len(c(0, 3), 6))) # spread the values at equal distance within the available space ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = 3, x.action = "spread")) # spread the values at equal distance within the expanded available space ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = 3, x.action = "spread", x.expansion = 0.1)) # spread the values at equal distance within the contracted available space ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = 3, x.action = "spread", x.expansion = -0.1)) # spread the values at equal distance within the range given by x ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = 3, x = c(2,4), x.action = "spread"), hjust = "center") ggplot(df, aes(x, y, label = label)) + geom_point() + geom_text_s(position = position_nudge_to(y = 3, x = c(0,6), x.action = "spread"), hjust = "center")
position_stacknudge()
is useful when labelling plots such as stacked
bars, stacked columns, stacked lines, etc. In contrast to
position_nudge
, position_stacknudge()
returns
in data
both the original coordinates and the nudged coordinates.
position_stacknudge( vjust = 1, reverse = FALSE, x = 0, y = 0, direction = c("none", "split", "split.x", "split.y"), kept.origin = c("stacked", "original", "none") ) position_fillnudge( vjust = 1, reverse = FALSE, x = 0, y = 0, direction = c("none", "split", "split.x", "split.y"), kept.origin = c("stacked", "original", "none") ) position_stack_keep(vjust = 1, reverse = FALSE, kept.origin = "original") position_fill_keep(vjust = 1, reverse = FALSE, kept.origin = "original") position_stack_minmax( vjust = 1, reverse = FALSE, x = 0, y = 0, direction = c("none", "split", "split.x", "split.y"), kept.origin = c("stacked", "original", "none") )
position_stacknudge( vjust = 1, reverse = FALSE, x = 0, y = 0, direction = c("none", "split", "split.x", "split.y"), kept.origin = c("stacked", "original", "none") ) position_fillnudge( vjust = 1, reverse = FALSE, x = 0, y = 0, direction = c("none", "split", "split.x", "split.y"), kept.origin = c("stacked", "original", "none") ) position_stack_keep(vjust = 1, reverse = FALSE, kept.origin = "original") position_fill_keep(vjust = 1, reverse = FALSE, kept.origin = "original") position_stack_minmax( vjust = 1, reverse = FALSE, x = 0, y = 0, direction = c("none", "split", "split.x", "split.y"), kept.origin = c("stacked", "original", "none") )
vjust |
Vertical adjustment for geoms that have a position (like points or lines), not a dimension (like bars or areas). Set to 0 to align with the bottom, 0.5 for the middle, and 1 (the default) for the top. |
reverse |
If TRUE, will reverse the default stacking order. This is useful if you're rotating both the plot and legend. |
x , y
|
Amount of vertical and horizontal distance to move. A numeric
vector of length 1, or of the same length as rows there are in |
direction |
One of |
kept.origin |
One of |
position_fillnudge()
is useful when labelling plots such as filled
bars, filled columns, filled lines, etc. In contrast to
position_nudge
, position_fillnudge()
returns
in data
both the original coordinates and the nudged coordinates.
The wrapper position_nudge_keep()
has the same signature and
behaviour as position_nudge
nad provides an easier to
remember name when the need is only to have access to both the original and
nudged coordinates.
These position functions are backwards compatible with
position_nudge
but extends it by adding support for
stacking and for geometries that make use of the original position to draw
connecting segments or arrows.
The wrapper position_stack_keep()
has the same signature and
behaviour as position_stack
and provides an easier to
remember name when the need is only to have access to both the original and
nudged coordinates.
The wrapper position_fill_keep()
has the same signature and
behaviour as position_fill
and provides an easier to
remember name when the need is only to have access to both the original and
nudged coordinates.
The wrapper position_stack_minmax()
has the same signature and
behaviour as position_stacknudge
but stacks y, ymin and
ymax in parallel, making it possible to stack summaries with error bars,
works correctly with geom_pointrange()
, geom_linerange()
and
geom_errorbar()
.
A "Position"
object.
Michał Krassowski, edited by Pedro J. Aphalo.
https://github.com/slowkow/ggrepel/issues/161.
position_nudge
,
position_stack
,
position_nudge_repel
.
Other position adjustments:
position_dodgenudge()
,
position_jitternudge()
,
position_nudge_center()
,
position_nudge_keep()
,
position_nudge_line()
,
position_nudge_to()
df <- data.frame(x1 = c("a", "a", "b", "b", "b"), x2 = c(1, 2, 1, 3, -1), grp = c("some long name", "other name", "some name", "another name", "some long name")) # Add labels to a horizontal column plot (stacked by default) ggplot(data = df, aes(x1, x2, group = grp)) + geom_col(aes(fill = grp), width=0.5) + geom_vline(xintercept = 0) + geom_text( aes(label = grp), position = position_stacknudge(vjust = 0.5, y = 0.3)) + theme(legend.position = "none") # Add labels to a vertical column plot (stacked by default) ggplot(data = df, aes(x2, x1, group = grp)) + geom_col(aes(fill = grp), width=0.5) + geom_vline(xintercept = 0) + geom_text( aes(label = grp), position = position_stacknudge(vjust = 0.5, x = -0.3), angle = 90) + theme(legend.position = "none") # Add labels to a vertical column plot (stacked by default) ggplot(data = subset(df, x1 >= 0), aes(x1, x2, group = grp)) + geom_col(aes(fill = grp), width=0.5, position = position_fill()) + geom_vline(xintercept = 0) + geom_text( aes(label = grp), position = position_fillnudge(vjust = 0.5, x = -0.3), angle = 90) + theme(legend.position = "none") # Add label at a fixed distance from the top of each column slice ggplot(data = df, aes(x1, x2, group = grp)) + geom_col(aes(fill = grp), width=0.5) + geom_vline(xintercept = 0) + geom_text( aes(label = grp), position = position_stacknudge(vjust = 1, y = -0.2)) + theme(legend.position = "none") # Use geom_text_s(), geom_text_repel() or geom_label_repel() to link # label to labelled segment or object with an arrow ggplot(data = df, aes(x2, x1, group = grp)) + geom_col(aes(fill = grp), width=0.5) + geom_vline(xintercept = 0) + geom_text_s( aes(label = grp), position = position_stacknudge(vjust = 0.5, y = 0.35), vjust = "bottom") + theme(legend.position = "none") ggplot(birch_dw.df, aes(y = dry.weight * 1e-3, x = Density, fill = Part)) + stat_summary(geom = "col", fun = mean, position = "stack", alpha = 0.7, width = 0.67) + stat_summary(geom = "linerange", fun.data = mean_cl_normal, position = position_stack_minmax()) + labs(y = "Seedling dry mass (g)") + scale_fill_grey(start = 0.7, end = 0.3) + facet_wrap(facets = vars(Container))
df <- data.frame(x1 = c("a", "a", "b", "b", "b"), x2 = c(1, 2, 1, 3, -1), grp = c("some long name", "other name", "some name", "another name", "some long name")) # Add labels to a horizontal column plot (stacked by default) ggplot(data = df, aes(x1, x2, group = grp)) + geom_col(aes(fill = grp), width=0.5) + geom_vline(xintercept = 0) + geom_text( aes(label = grp), position = position_stacknudge(vjust = 0.5, y = 0.3)) + theme(legend.position = "none") # Add labels to a vertical column plot (stacked by default) ggplot(data = df, aes(x2, x1, group = grp)) + geom_col(aes(fill = grp), width=0.5) + geom_vline(xintercept = 0) + geom_text( aes(label = grp), position = position_stacknudge(vjust = 0.5, x = -0.3), angle = 90) + theme(legend.position = "none") # Add labels to a vertical column plot (stacked by default) ggplot(data = subset(df, x1 >= 0), aes(x1, x2, group = grp)) + geom_col(aes(fill = grp), width=0.5, position = position_fill()) + geom_vline(xintercept = 0) + geom_text( aes(label = grp), position = position_fillnudge(vjust = 0.5, x = -0.3), angle = 90) + theme(legend.position = "none") # Add label at a fixed distance from the top of each column slice ggplot(data = df, aes(x1, x2, group = grp)) + geom_col(aes(fill = grp), width=0.5) + geom_vline(xintercept = 0) + geom_text( aes(label = grp), position = position_stacknudge(vjust = 1, y = -0.2)) + theme(legend.position = "none") # Use geom_text_s(), geom_text_repel() or geom_label_repel() to link # label to labelled segment or object with an arrow ggplot(data = df, aes(x2, x1, group = grp)) + geom_col(aes(fill = grp), width=0.5) + geom_vline(xintercept = 0) + geom_text_s( aes(label = grp), position = position_stacknudge(vjust = 0.5, y = 0.35), vjust = "bottom") + theme(legend.position = "none") ggplot(birch_dw.df, aes(y = dry.weight * 1e-3, x = Density, fill = Part)) + stat_summary(geom = "col", fun = mean, position = "stack", alpha = 0.7, width = 0.67) + stat_summary(geom = "linerange", fun.data = mean_cl_normal, position = position_stack_minmax()) + labs(y = "Seedling dry mass (g)") + scale_fill_grey(start = 0.7, end = 0.3) + facet_wrap(facets = vars(Container))
A dataset containing reshaped and simplified output from an analysis of data from RNAseq done with package edgeR. Original data from gene expression in the plant species Arabidopsis thaliana.
quadrant_example.df
quadrant_example.df
A data.frame
object with 6088 rows and 6 variables
Rai, Neha; O'Hara, Andrew; Farkas, Daniel; Safronov, Omid; Ratanasopa, Khuanpiroon; Wang, Fang; Lindfors, Anders V.; Jenkins, Gareth I.; Lehto, Tarja; Salojärvi, Jarkko; Brosché, Mikael; Strid. Åke; Aphalo, Pedro José; Morales, Luis Orlando (2020) The photoreceptor UVR8 mediates the perception of both UV-B and UV-A wavelengths up to 350 nm of sunlight with responsivity moderated by cryptochromes. Plant, Cell & Environment, 43:1513-1527.
Other Transcriptomics data:
volcano_example.df
colnames(quadrant_example.df) head(quadrant_example.df)
colnames(quadrant_example.df) head(quadrant_example.df)
scale_npcx_continuous()
and scale_npcy_continuous()
are
scales for continuous npcx and npcy aesthetics expressed in "npc" units.
There are no variants. Obviously limits are always the full range of "npc"
units and transformations meaningless. These scales are used by the newly
defined aesthetics npcx
and npcy
.
scale_npcx_continuous(...) scale_npcy_continuous(...)
scale_npcx_continuous(...) scale_npcy_continuous(...)
... |
Other arguments passed on to |
A "Scale"
object.
stat_summary_xy()
and stat_centroid()
are similar to
ggplot2::stat_summary()
but summarize both x
and y
values in the same plot layer. Differently to stat_summary()
no
grouping based on data values
is done; the grouping respected is that
already present based on mappings to aesthetics. This makes it possible to
highlight the actual location of the centroid with geom_point()
,
geom_text()
, and similar geometries. Instead, if we use
geom_rug()
they are only a convenience avoiding the need to add two
separate layers and flipping one of them using orientation = "y"
.
stat_apply_group( mapping = NULL, data = NULL, geom = "line", .fun.x = NULL, .fun.x.args = list(), .fun.y = NULL, .fun.y.args = list(), position = "identity", na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, ... ) stat_summary_xy( mapping = NULL, data = NULL, geom = "point", .fun.x = NULL, .fun.x.args = list(), .fun.y = NULL, .fun.y.args = list(), position = "identity", na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, ... ) stat_centroid( mapping = NULL, data = NULL, geom = "point", .fun = NULL, .fun.args = list(), position = "identity", na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, ... )
stat_apply_group( mapping = NULL, data = NULL, geom = "line", .fun.x = NULL, .fun.x.args = list(), .fun.y = NULL, .fun.y.args = list(), position = "identity", na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, ... ) stat_summary_xy( mapping = NULL, data = NULL, geom = "point", .fun.x = NULL, .fun.x.args = list(), .fun.y = NULL, .fun.y.args = list(), position = "identity", na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, ... ) stat_centroid( mapping = NULL, data = NULL, geom = "point", .fun = NULL, .fun.args = list(), position = "identity", na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, ... )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific dataset - only needed if you want to override the plot defaults. |
geom |
The geometric object to use display the data |
.fun.x , .fun.y , .fun
|
function to be applied or the name of the function to be applied as a character string. |
.fun.x.args , .fun.y.args , .fun.args
|
additional arguments to be passed to the function as a named list. |
position |
The position adjustment to use for overlapping points on this layer |
na.rm |
a logical value indicating whether NA values should be stripped before the computation proceeds. |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
... |
other arguments passed on to |
stat_apply_group
applies functions to data.
When possible it is preferable to use transformations through scales or
summary functions such as ggplot2::stat_summary()
,
stat_summary_xy()
or stat_centroid()
. There are some
computations that are not scale transformations but are not usual summaries
either, as the number of data values does not decrease all the way to one row
per group. A typical case for a summary is the computation of quantiles. For
transformations are cumulative ones, e.g., using cumsum()
,
runmed()
and similar functions. Obviously, it is always possible to
apply such functions to the data before plotting and passing them to a single
layer function. However, it can be useful to apply such functions on-the-fly
to ensure that grouping is consistent between computations and aesthetics.
One particularity of these statistics is that they can apply simultaneously
different functions to x
values and to y
values when needed. In
contrast to these statistics, geom_smooth
applies a
function that takes both x
and y
values as arguments.
These four statistics are similar. They differ on whether they return a single or multiple rows of data per group.
A data frame with the same variables as the data input, with either a
single or multiple rows, with the values of x
and y
variables
replaced by the values returned by the applied functions, or possibly
filled with NA
if no function was supplied or available by default.
If the applied function returns a named vector, the names are copied into
columns x.names
and/or y.names
. If the summary function
applied returns a one row data frame, it will be column bound keeping
the column names, but overwritting columns x and/or y with y from the
summary data frame. In the names returned by .fun.x
the letter
"y" is replaced by "x". These allows the use of the same functions as in
ggplot2::stat_summary()
.
x-value as returned by .fun.x
, with names removed
y-value as returned by .fun.y
, with names removed
if the x-value returned by .fun.x
is named, these names
if the y-value returned by .fun.y
is named, these names
values returned by .fun.x
under these names, if present
values returned by .fun.y
under these names, if present
additional values as returned by .fun.y
under other names
The applied function(s) must accept as first argument a vector that
matches the variables mapped to x
or y
aesthetics. For
stat_summary_xy()
and stat_centroid()
the function(s) to be
applied is(are) expected to return a vector of length 1 or a data frame
with only one row, as mean_se()
, mean_cl_normal()
mean_cl_boot()
, mean_sdl()
and median_hilow()
from
'ggplot2' do.
For stat_apply_group
the vectors returned by the
the functions applied to x
and y
must be of exactly the same
length. When only one of .fun.x
or .fun.y
are passed a
function as argument, the other variable in the returned data is filled
with NA_real_
. If other values are desired, they can be set by means
of a user-defined function.
Answers to question "R ggplot on-the-fly calculation by grouping variable" at https://stackoverflow.com/questions/51412522.
set.seed(123456) my.df <- data.frame(X = rep(1:20,2), Y = runif(40), category = rep(c("A","B"), each = 20)) # make sure rows are ordered for X as we will use functions that rely on this my.df <- my.df[order(my.df[["X"]]), ] # Centroid ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_centroid(shape = "cross", size = 6) + geom_point() ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_centroid(geom = "rug", linewidth = 1.5, .fun = median) + geom_point() ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_centroid(geom = "text", aes(label = category)) + geom_point() ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_summary_xy(geom = "pointrange", .fun.x = mean, .fun.y = mean_se) + geom_point() # quantiles ggplot(my.df, aes(x = X, y = Y, colour = category)) + geom_point() + stat_apply_group(geom = "rug", .fun.y = quantile, .fun.x = quantile) ggplot(my.df, aes(x = X, y = Y)) + geom_point() + stat_apply_group(geom = "rug", sides = "lr", color = "darkred", .fun.y = quantile) + stat_apply_group(geom = "text", hjust = "right", color = "darkred", .fun.y = quantile, .fun.x = function(x) {rep(22, 5)}, # set x to 22 mapping = aes(label = after_stat(y.names))) + expand_limits(x = 21) my.probs <- c(0.25, 0.5, 0.75) ggplot(my.df, aes(x = X, y = Y, colour = category)) + geom_point() + stat_apply_group(geom = "hline", aes(yintercept = after_stat(y)), .fun.y = quantile, .fun.y.args = list(probs = my.probs)) # cummulative summaries ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_apply_group(.fun.x = function(x) {x}, .fun.y = cummax) ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_apply_group(.fun.x = cumsum, .fun.y = cumsum) # diff returns a shorter vector by 1 for each group ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_apply_group(.fun.x = function(x) {x[-1L]}, .fun.y = diff, na.rm = TRUE) # Running summaries ggplot(my.df, aes(x = X, y = Y, colour = category)) + geom_point() + stat_apply_group(.fun.x = function(x) {x}, .fun.y = runmed, .fun.y.args = list(k = 5)) # Rescaling per group ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_apply_group(.fun.x = function(x) {x}, .fun.y = function(x) {(x - min(x)) / (max(x) - min(x))}) # inspecting the returned data if (requireNamespace("gginnards", quietly = TRUE)) { library(gginnards) ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_centroid(.fun = mean_se, geom = "debug") ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_summary_xy(.fun.y = mean_se, geom = "debug") ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_apply_group(.fun.y = cumsum, geom = "debug") ggplot(my.df, aes(x = X, y = Y, colour = category)) + geom_point() + stat_apply_group(geom = "debug", .fun.x = quantile, .fun.x.args = list(probs = my.probs), .fun.y = quantile, .fun.y.args = list(probs = my.probs)) }
set.seed(123456) my.df <- data.frame(X = rep(1:20,2), Y = runif(40), category = rep(c("A","B"), each = 20)) # make sure rows are ordered for X as we will use functions that rely on this my.df <- my.df[order(my.df[["X"]]), ] # Centroid ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_centroid(shape = "cross", size = 6) + geom_point() ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_centroid(geom = "rug", linewidth = 1.5, .fun = median) + geom_point() ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_centroid(geom = "text", aes(label = category)) + geom_point() ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_summary_xy(geom = "pointrange", .fun.x = mean, .fun.y = mean_se) + geom_point() # quantiles ggplot(my.df, aes(x = X, y = Y, colour = category)) + geom_point() + stat_apply_group(geom = "rug", .fun.y = quantile, .fun.x = quantile) ggplot(my.df, aes(x = X, y = Y)) + geom_point() + stat_apply_group(geom = "rug", sides = "lr", color = "darkred", .fun.y = quantile) + stat_apply_group(geom = "text", hjust = "right", color = "darkred", .fun.y = quantile, .fun.x = function(x) {rep(22, 5)}, # set x to 22 mapping = aes(label = after_stat(y.names))) + expand_limits(x = 21) my.probs <- c(0.25, 0.5, 0.75) ggplot(my.df, aes(x = X, y = Y, colour = category)) + geom_point() + stat_apply_group(geom = "hline", aes(yintercept = after_stat(y)), .fun.y = quantile, .fun.y.args = list(probs = my.probs)) # cummulative summaries ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_apply_group(.fun.x = function(x) {x}, .fun.y = cummax) ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_apply_group(.fun.x = cumsum, .fun.y = cumsum) # diff returns a shorter vector by 1 for each group ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_apply_group(.fun.x = function(x) {x[-1L]}, .fun.y = diff, na.rm = TRUE) # Running summaries ggplot(my.df, aes(x = X, y = Y, colour = category)) + geom_point() + stat_apply_group(.fun.x = function(x) {x}, .fun.y = runmed, .fun.y.args = list(k = 5)) # Rescaling per group ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_apply_group(.fun.x = function(x) {x}, .fun.y = function(x) {(x - min(x)) / (max(x) - min(x))}) # inspecting the returned data if (requireNamespace("gginnards", quietly = TRUE)) { library(gginnards) ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_centroid(.fun = mean_se, geom = "debug") ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_summary_xy(.fun.y = mean_se, geom = "debug") ggplot(my.df, aes(x = X, y = Y, colour = category)) + stat_apply_group(.fun.y = cumsum, geom = "debug") ggplot(my.df, aes(x = X, y = Y, colour = category)) + geom_point() + stat_apply_group(geom = "debug", .fun.x = quantile, .fun.x.args = list(probs = my.probs), .fun.y = quantile, .fun.y.args = list(probs = my.probs)) }
stat_dens1d_filter
Filters-out/filters-in observations in
regions of a plot panel with high density of observations, based on the
values mapped to one of x
and y
aesthetics.
stat_dens1d_filter_g
does the same filtering by group instead of by
panel. This second stat is useful for highlighting observations, while the
first one tends to be most useful when the aim is to prevent clashes among
text labels. By default the data are handled all together, but it is also
possible to control labeling separately in each tail.
stat_dens1d_filter( mapping = NULL, data = NULL, geom = "point", position = "identity", ..., keep.fraction = 0.1, keep.number = Inf, keep.sparse = TRUE, keep.these = FALSE, exclude.these = FALSE, these.target = "label", pool.along = c("x", "none"), xintercept = 0, invert.selection = FALSE, bw = "SJ", kernel = "gaussian", adjust = 1, n = 512, return.density = FALSE, orientation = c("x", "y"), na.rm = TRUE, show.legend = FALSE, inherit.aes = TRUE ) stat_dens1d_filter_g( mapping = NULL, data = NULL, geom = "point", position = "identity", keep.fraction = 0.1, keep.number = Inf, keep.sparse = TRUE, keep.these = FALSE, exclude.these = FALSE, these.target = "label", pool.along = c("x", "none"), xintercept = 0, invert.selection = FALSE, na.rm = TRUE, show.legend = FALSE, inherit.aes = TRUE, bw = "SJ", adjust = 1, kernel = "gaussian", n = 512, return.density = FALSE, orientation = c("x", "y"), ... )
stat_dens1d_filter( mapping = NULL, data = NULL, geom = "point", position = "identity", ..., keep.fraction = 0.1, keep.number = Inf, keep.sparse = TRUE, keep.these = FALSE, exclude.these = FALSE, these.target = "label", pool.along = c("x", "none"), xintercept = 0, invert.selection = FALSE, bw = "SJ", kernel = "gaussian", adjust = 1, n = 512, return.density = FALSE, orientation = c("x", "y"), na.rm = TRUE, show.legend = FALSE, inherit.aes = TRUE ) stat_dens1d_filter_g( mapping = NULL, data = NULL, geom = "point", position = "identity", keep.fraction = 0.1, keep.number = Inf, keep.sparse = TRUE, keep.these = FALSE, exclude.these = FALSE, these.target = "label", pool.along = c("x", "none"), xintercept = 0, invert.selection = FALSE, na.rm = TRUE, show.legend = FALSE, inherit.aes = TRUE, bw = "SJ", adjust = 1, kernel = "gaussian", n = 512, return.density = FALSE, orientation = c("x", "y"), ... )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific dataset - only needed if you want to override the plot defaults. |
geom |
The geometric object to use display the data. |
position |
The position adjustment to use for overlapping points on this layer |
... |
other arguments passed on to |
keep.fraction |
numeric vector of length 1 or 2 [0..1]. The fraction of
the observations (or rows) in |
keep.number |
integer vector of length 1 or 2. Set the maximum number of
observations to retain, effective only if obeying |
keep.sparse |
logical If |
keep.these , exclude.these
|
character vector, integer vector, logical
vector or function that takes one or more variables in data selected by
|
these.target |
character, numeric or logical selecting one or more
column(s) of |
pool.along |
character, one of |
xintercept |
numeric The split point for the data filtering. If
|
invert.selection |
logical If |
bw |
numeric or character The smoothing bandwidth to be used. If
numeric, the standard deviation of the smoothing kernel. If character, a
rule to choose the bandwidth, as listed in |
kernel |
character See |
adjust |
numeric A multiplicative bandwidth adjustment. This makes it
possible to adjust the bandwidth while still using the a bandwidth
estimator through an argument passed to |
n |
numeric Number of equally spaced points at which the density is to
be estimated for applying the cut point. See |
return.density |
logical vector of lenght 1. If |
orientation |
character The aesthetic along which density is computed.
Given explicitly by setting orientation to either |
na.rm |
a logical value indicating whether |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
The 1D density of observations of x or y is computed
with function density
and used to select observations,
passing to the geom a subset of the rows in its data
input. The
default is to select observations in sparse regions of the plot, but the
selection can be inverted so that only observations in the densest regions
are returned. Specific observations can be protected from being deselected
and "kept" by passing a suitable argument to keep.these
. Logical and
integer vectors work as indexes to rows in data
, while a values in a
character vector are compared to the character values mapped to the
label
aesthetic. A function passed as argument to keep.these will
receive as argument the values in the variable mapped to label
and
should return a character, logical or numeric vector as described above. If
no variable has been mapped to label
, row names are used in its
place.
How many rows are retained in addition to those in keep.these
is
controlled with arguments passed to keep.number
and
keep.fraction
. keep.number
sets the maximum number of
observations selected, whenever keep.fraction
results in fewer
observations selected, it is obeyed. If 'xintercept' is a finite value
within the x range of the data and pool.along
is passed "none"
the data as are split into two groups
and keep.number
and keep.fraction
are applied separately to
each tail with density still computed jointly from all observations. If the
length of keep.number
and keep.fraction
is one, this value
is used for both tails, if their length is two, the first value is use
for the left tail and the second value for the right tail.
Computation of density and of the default bandwidth require at least
two observations with different values. If data do not fulfill this
condition, they are kept only if keep.fraction = 1
. This is correct
behavior for a single observation, but can be surprising in the case of
multiple observations.
Parameters keep.these
and exclude.these
make it possible to
force inclusion or exclusion of observations after the density is computed.
In case of conflict, exclude.these
overrides keep.these
.
A plot layer instance. Using as output data
a subset of the
rows in input data
retained based on a 1D filtering criterion.
Which points are kept and which not depends on how dense and flexible
is the density curve estimate. This depends on the values passed as
arguments to parameters n
, bw
and kernel
. It is
also important to be aware that both geom_text()
and
geom_text_repel()
can avoid over plotting by discarding labels at
the plot rendering stage, i.e., what is plotted may differ from what is
returned by this statistic.
density
used internally.
Other statistics returning a subset of data:
stat_dens1d_labels()
,
stat_dens2d_filter()
,
stat_dens2d_labels()
random_string <- function(len = 6) { paste(sample(letters, len, replace = TRUE), collapse = "") } # Make random data. set.seed(1001) d <- tibble::tibble( x = rnorm(100), y = rnorm(100), group = rep(c("A", "B"), c(50, 50)), lab = replicate(100, { random_string() }) ) d$xg <- d$x d$xg[51:100] <- d$xg[51:100] + 1 # highlight the 1/10 of observations in sparsest regions of the plot ggplot(data = d, aes(x, y)) + geom_point() + geom_rug(sides = "b") + stat_dens1d_filter(colour = "red") + stat_dens1d_filter(geom = "rug", colour = "red", sides = "b") # highlight the 1/4 of observations in densest regions of the plot ggplot(data = d, aes(x, y)) + geom_point() + geom_rug(sides = "b") + stat_dens1d_filter(colour = "blue", keep.fraction = 1/4, keep.sparse = FALSE) + stat_dens1d_filter(geom = "rug", colour = "blue", keep.fraction = 1/4, keep.sparse = FALSE, sides = "b") # switching axes ggplot(data = d, aes(x, y)) + geom_point() + geom_rug(sides = "l") + stat_dens1d_filter(colour = "red", orientation = "y") + stat_dens1d_filter(geom = "rug", colour = "red", orientation = "y", sides = "l") # highlight 1/10 plus 1/10 observations in high and low density regions ggplot(data = d, aes(x, y)) + geom_point() + geom_rug(sides = "b") + stat_dens1d_filter(colour = "red") + stat_dens1d_filter(geom = "rug", colour = "red", sides = "b") + stat_dens1d_filter(colour = "blue", keep.sparse = FALSE) + stat_dens1d_filter(geom = "rug", colour = "blue", keep.sparse = FALSE, sides = "b") # selecting the 1/10 observations in sparsest regions and their complement ggplot(data = d, aes(x, y)) + stat_dens1d_filter(colour = "red") + stat_dens1d_filter(geom = "rug", colour = "red", sides = "b") + stat_dens1d_filter(colour = "blue", invert.selection = TRUE) + stat_dens1d_filter(geom = "rug", colour = "blue", invert.selection = TRUE, sides = "b") # density filtering done jointly across groups ggplot(data = d, aes(xg, y, colour = group)) + geom_point() + geom_rug(sides = "b", colour = "black") + stat_dens1d_filter(shape = 1, size = 3, keep.fraction = 1/4, adjust = 2) # density filtering done independently for each group ggplot(data = d, aes(xg, y, colour = group)) + geom_point() + geom_rug(sides = "b") + stat_dens1d_filter_g(shape = 1, size = 3, keep.fraction = 1/4, adjust = 2) # density filtering done jointly across groups by overriding grouping ggplot(data = d, aes(xg, y, colour = group)) + geom_point() + geom_rug(sides = "b") + stat_dens1d_filter_g(colour = "black", shape = 1, size = 3, keep.fraction = 1/4, adjust = 2) # label observations ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens1d_filter(geom = "text", hjust = "outward") # looking under the hood with gginnards::geom_debug() gginnards.installed <- requireNamespace("gginnards", quietly = TRUE) if (gginnards.installed) { library(gginnards) ggplot(data = d, aes(x, y, label = lab, colour = group)) + stat_dens1d_filter(geom = "debug") ggplot(data = d, aes(x, y, label = lab, colour = group)) + stat_dens1d_filter(geom = "debug", return.density = TRUE) }
random_string <- function(len = 6) { paste(sample(letters, len, replace = TRUE), collapse = "") } # Make random data. set.seed(1001) d <- tibble::tibble( x = rnorm(100), y = rnorm(100), group = rep(c("A", "B"), c(50, 50)), lab = replicate(100, { random_string() }) ) d$xg <- d$x d$xg[51:100] <- d$xg[51:100] + 1 # highlight the 1/10 of observations in sparsest regions of the plot ggplot(data = d, aes(x, y)) + geom_point() + geom_rug(sides = "b") + stat_dens1d_filter(colour = "red") + stat_dens1d_filter(geom = "rug", colour = "red", sides = "b") # highlight the 1/4 of observations in densest regions of the plot ggplot(data = d, aes(x, y)) + geom_point() + geom_rug(sides = "b") + stat_dens1d_filter(colour = "blue", keep.fraction = 1/4, keep.sparse = FALSE) + stat_dens1d_filter(geom = "rug", colour = "blue", keep.fraction = 1/4, keep.sparse = FALSE, sides = "b") # switching axes ggplot(data = d, aes(x, y)) + geom_point() + geom_rug(sides = "l") + stat_dens1d_filter(colour = "red", orientation = "y") + stat_dens1d_filter(geom = "rug", colour = "red", orientation = "y", sides = "l") # highlight 1/10 plus 1/10 observations in high and low density regions ggplot(data = d, aes(x, y)) + geom_point() + geom_rug(sides = "b") + stat_dens1d_filter(colour = "red") + stat_dens1d_filter(geom = "rug", colour = "red", sides = "b") + stat_dens1d_filter(colour = "blue", keep.sparse = FALSE) + stat_dens1d_filter(geom = "rug", colour = "blue", keep.sparse = FALSE, sides = "b") # selecting the 1/10 observations in sparsest regions and their complement ggplot(data = d, aes(x, y)) + stat_dens1d_filter(colour = "red") + stat_dens1d_filter(geom = "rug", colour = "red", sides = "b") + stat_dens1d_filter(colour = "blue", invert.selection = TRUE) + stat_dens1d_filter(geom = "rug", colour = "blue", invert.selection = TRUE, sides = "b") # density filtering done jointly across groups ggplot(data = d, aes(xg, y, colour = group)) + geom_point() + geom_rug(sides = "b", colour = "black") + stat_dens1d_filter(shape = 1, size = 3, keep.fraction = 1/4, adjust = 2) # density filtering done independently for each group ggplot(data = d, aes(xg, y, colour = group)) + geom_point() + geom_rug(sides = "b") + stat_dens1d_filter_g(shape = 1, size = 3, keep.fraction = 1/4, adjust = 2) # density filtering done jointly across groups by overriding grouping ggplot(data = d, aes(xg, y, colour = group)) + geom_point() + geom_rug(sides = "b") + stat_dens1d_filter_g(colour = "black", shape = 1, size = 3, keep.fraction = 1/4, adjust = 2) # label observations ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens1d_filter(geom = "text", hjust = "outward") # looking under the hood with gginnards::geom_debug() gginnards.installed <- requireNamespace("gginnards", quietly = TRUE) if (gginnards.installed) { library(gginnards) ggplot(data = d, aes(x, y, label = lab, colour = group)) + stat_dens1d_filter(geom = "debug") ggplot(data = d, aes(x, y, label = lab, colour = group)) + stat_dens1d_filter(geom = "debug", return.density = TRUE) }
stat_dens1d_labels()
Sets values mapped to the
label
aesthetic to ""
or a user provided character string
based on the local density in regions of a plot panel. Its main use is
together with repulsive geoms from package ggrepel
to restrict labeling to the low density tails of a distribution. By default
the data are handled all together, but it is also possible to control
labeling separately in each tail.
If there is no mapping to label
in data
, the mapping is set
to rownames(data)
, with a message.
stat_dens1d_labels( mapping = NULL, data = NULL, geom = "text", position = "identity", ..., keep.fraction = 0.1, keep.number = Inf, keep.sparse = TRUE, keep.these = FALSE, exclude.these = FALSE, these.target = "label", pool.along = c("x", "none"), xintercept = 0, invert.selection = FALSE, bw = "SJ", kernel = "gaussian", adjust = 1, n = 512, orientation = c("x", "y"), label.fill = "", return.density = FALSE, na.rm = TRUE, show.legend = FALSE, inherit.aes = TRUE )
stat_dens1d_labels( mapping = NULL, data = NULL, geom = "text", position = "identity", ..., keep.fraction = 0.1, keep.number = Inf, keep.sparse = TRUE, keep.these = FALSE, exclude.these = FALSE, these.target = "label", pool.along = c("x", "none"), xintercept = 0, invert.selection = FALSE, bw = "SJ", kernel = "gaussian", adjust = 1, n = 512, orientation = c("x", "y"), label.fill = "", return.density = FALSE, na.rm = TRUE, show.legend = FALSE, inherit.aes = TRUE )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific dataset - only needed if you want to override the plot defaults. |
geom |
The geometric object to use display the data. |
position |
The position adjustment to use for overlapping points on this layer |
... |
other arguments passed on to |
keep.fraction |
numeric vector of length 1 or 2 [0..1]. The fraction of
the observations (or rows) in |
keep.number |
integer vector of length 1 or 2. Set the maximum number of
observations to retain, effective only if obeying |
keep.sparse |
logical If |
keep.these , exclude.these
|
character vector, integer vector, logical
vector or function that takes one or more variables in data selected by
|
these.target |
character, numeric or logical selecting one or more
column(s) of |
pool.along |
character, one of |
xintercept |
numeric The split point for the data filtering. |
invert.selection |
logical If |
bw |
numeric or character The smoothing bandwidth to be used. If
numeric, the standard deviation of the smoothing kernel. If character, a
rule to choose the bandwidth, as listed in |
kernel |
character See |
adjust |
numeric A multiplicative bandwidth adjustment. This makes it
possible to adjust the bandwidth while still using the a bandwidth
estimator through an argument passed to |
n |
numeric Number of equally spaced points at which the density is to
be estimated for applying the cut point. See |
orientation |
character The aesthetic along which density is computed. Given explicitly by setting orientation to either "x" or "y". |
label.fill |
character vector of length 1 or a function. |
return.density |
logical vector of lenght 1. If |
na.rm |
a logical value indicating whether NA values should be stripped before the computation proceeds. |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
stat_dens1d_labels()
is designed to work together with
geometries from package 'ggrepel'. To avoid text labels being plotted over
unlabelled points the corresponding rows in data need to be retained but
labels replaced with the empty character string, ""
. Function
stat_dens1d_filter
cannot be used with the repulsive geoms
from 'ggrepel' because it drops the observations.
stat_dens1d_labels()
can be useful also in other situations, as the
substitution character string can be set by the user by passing an argument
to label.fill
. If this argument is NULL
the unselected rows
are filtered out.
The local density of observations along x or y is computed
with function density
and used to select observations,
passing to the geom all the rows in its data
input but with with the
text of labels replaced in those "not kept". The default is to select
observations in sparse regions of the plot, but the selection can be
inverted so that only observations in the densest regions are returned.
Specific observations can be protected from having the label replaced by
passing a suitable argument to keep.these
. Logical and integer
vectors function as indexes to rows in data
, while a character
vector is compared to values in the variable mapped to the label
aesthetic. A function passed as argument to keep.these will receive as
argument the values in the variable mapped to label
and should
return a character, logical or numeric vector as described above.
How many labels are retained intact in addition to those in
keep.these
is controlled with arguments passed to keep.number
and keep.fraction
. keep.number
sets the maximum number of
observations selected, whenever keep.fraction
results in fewer
observations selected, it is obeyed. If xintercept
is a finite value
within the x range of the data and pool.along
is passed
"none"
the data are split into two groups and keep.number
and
keep.fraction
are applied separately to each tail with density still
computed jointly from all observations. If the length of keep.number
and keep.fraction
is one, half this value is used each tail, if
their length is two, the first value is use for the left tail and the
second value for the right tail (or if using orientation = "y"
the
lower and upper tails, respectively).
Computation of density and of the default bandwidth require at least
two observations with different values. If data do not fulfill this
condition, they are kept only if keep.fraction = 1
. This is correct
behavior for a single observation, but can be surprising in the case of
multiple observations.
Parameters keep.these
and exclude.these
make it possible to
force inclusion or exclusion of labels after the density is computed.
In case of conflict, exclude.these
overrides keep.these
.
A plot layer instance. Using as output data
the input
data
after value substitution based on a 1D the filtering criterion.
Which points are kept and which not depends on how dense and flexible
is the density curve estimate. This depends on the values passed as
arguments to parameters n
, bw
and kernel
. It is
also important to be aware that both geom_text()
and
geom_text_repel()
can avoid overplotting by discarding labels at
the plot rendering stage, i.e., what is plotted may differ from what is
returned by this statistic.
density
used internally.
Other statistics returning a subset of data:
stat_dens1d_filter()
,
stat_dens2d_filter()
,
stat_dens2d_labels()
random_string <- function(len = 6) { paste(sample(letters, len, replace = TRUE), collapse = "") } # Make random data. set.seed(1005) d <- tibble::tibble( x = rnorm(100), y = rnorm(100), group = rep(c("A", "B"), c(50, 50)), lab = replicate(100, { random_string() }) ) # using defaults ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens1d_labels() ggrepel.installed <- requireNamespace("ggrepel", quietly = TRUE) if (ggrepel.installed) { library(ggrepel) # using defaults ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens1d_labels(geom = "text_repel") # if no mapping to label is found, it is set row names ggplot(data = d, aes(x, y)) + geom_point() + stat_dens1d_labels(geom = "text_repel") ggplot(data = d, aes(x, y)) + geom_point() + stat_dens1d_labels(geom = "text_repel", pool.along = "none") ggplot(data = d, aes(x, y)) + geom_point() + stat_dens1d_labels(geom = "text_repel", keep.number = c(0, 10), pool.along = "none") ggplot(data = d, aes(x, y)) + geom_point() + stat_dens1d_labels(geom = "text_repel", keep.fraction = c(0, 0.2), pool.along = "none") # using defaults, along y-axis ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens1d_labels(orientation = "y", geom = "text_repel") # example labelling with coordiantes ggplot(data = d, aes(x, y, label = sprintf("x = %.2f\ny = %.2f", x, y))) + geom_point() + stat_dens1d_filter(colour = "red") + stat_dens1d_labels(geom = "text_repel", colour = "red", size = 3) ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens1d_labels(geom = "text_repel") ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens1d_labels(geom = "text_repel", label.fill = NA) # we keep labels starting with "a" across the whole plot, but all in sparse # regions. To achieve this we pass as argument to label.fill a fucntion # instead of a character string. label.fun <- function(x) {ifelse(grepl("^a", x), x, "")} ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens1d_labels(geom = "text_repel", label.fill = label.fun) } # Using geom_debug() we can see that all 100 rows in \code{d} are # returned. But only those labelled in the previous example still contain # the original labels. gginnards.installed <- requireNamespace("gginnards", quietly = TRUE) if (gginnards.installed) { library(gginnards) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens1d_labels(geom = "debug") ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens1d_labels(geom = "debug", return.density = TRUE) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens1d_labels(geom = "debug", label.fill = NULL, return.density = TRUE) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens1d_labels(geom = "debug", label.fill = NA, return.density = TRUE) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens1d_labels(geom = "debug", label.fill = FALSE, return.density = TRUE) }
random_string <- function(len = 6) { paste(sample(letters, len, replace = TRUE), collapse = "") } # Make random data. set.seed(1005) d <- tibble::tibble( x = rnorm(100), y = rnorm(100), group = rep(c("A", "B"), c(50, 50)), lab = replicate(100, { random_string() }) ) # using defaults ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens1d_labels() ggrepel.installed <- requireNamespace("ggrepel", quietly = TRUE) if (ggrepel.installed) { library(ggrepel) # using defaults ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens1d_labels(geom = "text_repel") # if no mapping to label is found, it is set row names ggplot(data = d, aes(x, y)) + geom_point() + stat_dens1d_labels(geom = "text_repel") ggplot(data = d, aes(x, y)) + geom_point() + stat_dens1d_labels(geom = "text_repel", pool.along = "none") ggplot(data = d, aes(x, y)) + geom_point() + stat_dens1d_labels(geom = "text_repel", keep.number = c(0, 10), pool.along = "none") ggplot(data = d, aes(x, y)) + geom_point() + stat_dens1d_labels(geom = "text_repel", keep.fraction = c(0, 0.2), pool.along = "none") # using defaults, along y-axis ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens1d_labels(orientation = "y", geom = "text_repel") # example labelling with coordiantes ggplot(data = d, aes(x, y, label = sprintf("x = %.2f\ny = %.2f", x, y))) + geom_point() + stat_dens1d_filter(colour = "red") + stat_dens1d_labels(geom = "text_repel", colour = "red", size = 3) ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens1d_labels(geom = "text_repel") ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens1d_labels(geom = "text_repel", label.fill = NA) # we keep labels starting with "a" across the whole plot, but all in sparse # regions. To achieve this we pass as argument to label.fill a fucntion # instead of a character string. label.fun <- function(x) {ifelse(grepl("^a", x), x, "")} ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens1d_labels(geom = "text_repel", label.fill = label.fun) } # Using geom_debug() we can see that all 100 rows in \code{d} are # returned. But only those labelled in the previous example still contain # the original labels. gginnards.installed <- requireNamespace("gginnards", quietly = TRUE) if (gginnards.installed) { library(gginnards) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens1d_labels(geom = "debug") ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens1d_labels(geom = "debug", return.density = TRUE) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens1d_labels(geom = "debug", label.fill = NULL, return.density = TRUE) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens1d_labels(geom = "debug", label.fill = NA, return.density = TRUE) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens1d_labels(geom = "debug", label.fill = FALSE, return.density = TRUE) }
stat_dens2d_filter
Filters-out/filters-in observations in
regions of a plot panel with high density of observations, based on the
values mapped to both x
and y
aesthetics.
stat_dens2d_filter_g
does the filtering by group instead of by
panel. This second stat is useful for highlighting observations, while the
first one tends to be most useful when the aim is to prevent clashes among
text labels. If there is no mapping to label
in data
, the
mapping is silently set to rownames(data)
.
stat_dens2d_filter( mapping = NULL, data = NULL, geom = "point", position = "identity", ..., keep.fraction = 0.1, keep.number = Inf, keep.sparse = TRUE, keep.these = FALSE, exclude.these = FALSE, these.target = "label", pool.along = c("xy", "x", "y", "none"), xintercept = 0, yintercept = 0, invert.selection = FALSE, na.rm = TRUE, show.legend = FALSE, inherit.aes = TRUE, h = NULL, n = NULL, return.density = FALSE ) stat_dens2d_filter_g( mapping = NULL, data = NULL, geom = "point", position = "identity", ..., keep.fraction = 0.1, keep.number = Inf, keep.sparse = TRUE, keep.these = FALSE, exclude.these = FALSE, these.target = "label", pool.along = c("xy", "x", "y", "none"), xintercept = 0, yintercept = 0, invert.selection = FALSE, na.rm = TRUE, show.legend = FALSE, inherit.aes = TRUE, h = NULL, n = NULL, return.density = FALSE )
stat_dens2d_filter( mapping = NULL, data = NULL, geom = "point", position = "identity", ..., keep.fraction = 0.1, keep.number = Inf, keep.sparse = TRUE, keep.these = FALSE, exclude.these = FALSE, these.target = "label", pool.along = c("xy", "x", "y", "none"), xintercept = 0, yintercept = 0, invert.selection = FALSE, na.rm = TRUE, show.legend = FALSE, inherit.aes = TRUE, h = NULL, n = NULL, return.density = FALSE ) stat_dens2d_filter_g( mapping = NULL, data = NULL, geom = "point", position = "identity", ..., keep.fraction = 0.1, keep.number = Inf, keep.sparse = TRUE, keep.these = FALSE, exclude.these = FALSE, these.target = "label", pool.along = c("xy", "x", "y", "none"), xintercept = 0, yintercept = 0, invert.selection = FALSE, na.rm = TRUE, show.legend = FALSE, inherit.aes = TRUE, h = NULL, n = NULL, return.density = FALSE )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific dataset - only needed if you want to override the plot defaults. |
geom |
The geometric object to use display the data. |
position |
The position adjustment to use for overlapping points on this layer |
... |
other arguments passed on to |
keep.fraction |
numeric [0..1]. The fraction of the observations (or
rows) in |
keep.number |
integer Set the maximum number of observations to retain,
effective only if obeying |
keep.sparse |
logical If |
keep.these , exclude.these
|
character vector, integer vector, logical
vector or function that takes one or more variables in data selected by
|
these.target |
character, numeric or logical selecting one or more
column(s) of |
pool.along |
character, one of |
xintercept , yintercept
|
numeric The center point of the quadrants. |
invert.selection |
logical If |
na.rm |
a logical value indicating whether NA values should be stripped before the computation proceeds. |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
h |
vector of bandwidths for x and y directions. Defaults to normal reference bandwidth (see bandwidth.nrd). A scalar value will be taken to apply to both directions. |
n |
Number of grid points in each direction. Can be scalar or a length-2 integer vector |
return.density |
logical vector of lenght 1. If |
The local density of observations in 2D (x and y) is
computed with function kde2d
and used to select
observations, passing to the geom a subset of the rows in its data
input. The default is to select observations in sparse regions of the plot,
but the selection can be inverted so that only observations in the densest
regions are returned. Specific observations can be protected from being
deselected and "kept" by passing a suitable argument to keep.these
.
Logical and integer vectors work as indexes to rows in data
, while a
character vector values are compared to the character values mapped to the
label
aesthetic. A function passed as argument to keep.these will
receive as argument the values in the variable mapped to label
and
should return a character, logical or numeric vector as described above. If
no variable has been mapped to label
, row names are used in its
place.
How many rows are retained in addition to those in keep.these
is
controlled with arguments passed to keep.number
and
keep.fraction
. keep.number
sets the maximum number of
observations selected, whenever keep.fraction
results in fewer
observations selected, it is obeyed.
Computation of density and of the default bandwidth require at least
two observations with different values. If data do not fulfill this
condition, they are kept only if keep.fraction = 1
. This is correct
behavior for a single observation, but can be surprising in the case of
multiple observations.
Parameters keep.these
and exclude.these
make it possible to
force inclusion or exclusion of observations after the density is computed.
In case of conflict, exclude.these
overrides keep.these
.
A plot layer instance. Using as output data
a subset of the
rows in input data
retained based on a 2D-density-based filtering
criterion.
Which points are kept and which not depends on how dense a grid is used
and how flexible the density surface estimate is. This depends on the
values passed as arguments to parameters n
, bw
and
kernel
. It is also important to be aware that both
geom_text()
and geom_text_repel()
can avoid overplotting by
discarding labels at the plot rendering stage, i.e., what is plotted may
differ from what is returned by this statistic.
stat_dens2d_labels
and kde2d
used
internally. Parameters n
, h
in these statistics correspond to
the parameters with the same name in this imported function. Limits are set
to the limits of the plot scales.
Other statistics returning a subset of data:
stat_dens1d_filter()
,
stat_dens1d_labels()
,
stat_dens2d_labels()
random_string <- function(len = 6) { paste(sample(letters, len, replace = TRUE), collapse = "") } # Make random data. set.seed(1001) d <- tibble::tibble( x = rnorm(100), y = rnorm(100), group = rep(c("A", "B"), c(50, 50)), lab = replicate(100, { random_string() }) ) # filter (and here highlight) 1/10 observations in sparsest regions ggplot(data = d, aes(x, y)) + geom_point() + stat_dens2d_filter(colour = "red") # filter observations not in the sparsest regions ggplot(data = d, aes(x, y)) + geom_point() + stat_dens2d_filter(colour = "blue", invert.selection = TRUE) # filter observations in dense regions of the plot ggplot(data = d, aes(x, y)) + geom_point() + stat_dens2d_filter(colour = "blue", keep.sparse = FALSE) # filter 1/2 the observations ggplot(data = d, aes(x, y)) + geom_point() + stat_dens2d_filter(colour = "red", keep.fraction = 0.5) # filter 1/2 the observations but cap their number to maximum 12 observations ggplot(data = d, aes(x, y)) + geom_point() + stat_dens2d_filter(colour = "red", keep.fraction = 0.5, keep.number = 12) # density filtering done jointly across groups ggplot(data = d, aes(x, y, colour = group)) + geom_point() + stat_dens2d_filter(shape = 1, size = 3, keep.fraction = 1/4) # density filtering done independently for each group ggplot(data = d, aes(x, y, colour = group)) + geom_point() + stat_dens2d_filter_g(shape = 1, size = 3, keep.fraction = 1/4) # density filtering done jointly across groups by overriding grouping ggplot(data = d, aes(x, y, colour = group)) + geom_point() + stat_dens2d_filter_g(colour = "black", shape = 1, size = 3, keep.fraction = 1/4) # label observations ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens2d_filter(geom = "text") ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens2d_filter(geom = "text", keep.these = function(x) {grepl("^u", x)}) ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens2d_filter(geom = "text", keep.these = function(x) {grepl("^u", x)}) ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens2d_filter(geom = "text", keep.these = 1:30) # looking under the hood with gginnards::geom_debug() gginnards.installed <- requireNamespace("gginnards", quietly = TRUE) if (gginnards.installed) { library(gginnards) ggplot(data = d, aes(x, y, label = lab, colour = group)) + stat_dens2d_filter(geom = "debug") ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens2d_filter(geom = "debug", return.density = TRUE) }
random_string <- function(len = 6) { paste(sample(letters, len, replace = TRUE), collapse = "") } # Make random data. set.seed(1001) d <- tibble::tibble( x = rnorm(100), y = rnorm(100), group = rep(c("A", "B"), c(50, 50)), lab = replicate(100, { random_string() }) ) # filter (and here highlight) 1/10 observations in sparsest regions ggplot(data = d, aes(x, y)) + geom_point() + stat_dens2d_filter(colour = "red") # filter observations not in the sparsest regions ggplot(data = d, aes(x, y)) + geom_point() + stat_dens2d_filter(colour = "blue", invert.selection = TRUE) # filter observations in dense regions of the plot ggplot(data = d, aes(x, y)) + geom_point() + stat_dens2d_filter(colour = "blue", keep.sparse = FALSE) # filter 1/2 the observations ggplot(data = d, aes(x, y)) + geom_point() + stat_dens2d_filter(colour = "red", keep.fraction = 0.5) # filter 1/2 the observations but cap their number to maximum 12 observations ggplot(data = d, aes(x, y)) + geom_point() + stat_dens2d_filter(colour = "red", keep.fraction = 0.5, keep.number = 12) # density filtering done jointly across groups ggplot(data = d, aes(x, y, colour = group)) + geom_point() + stat_dens2d_filter(shape = 1, size = 3, keep.fraction = 1/4) # density filtering done independently for each group ggplot(data = d, aes(x, y, colour = group)) + geom_point() + stat_dens2d_filter_g(shape = 1, size = 3, keep.fraction = 1/4) # density filtering done jointly across groups by overriding grouping ggplot(data = d, aes(x, y, colour = group)) + geom_point() + stat_dens2d_filter_g(colour = "black", shape = 1, size = 3, keep.fraction = 1/4) # label observations ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens2d_filter(geom = "text") ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens2d_filter(geom = "text", keep.these = function(x) {grepl("^u", x)}) ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens2d_filter(geom = "text", keep.these = function(x) {grepl("^u", x)}) ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens2d_filter(geom = "text", keep.these = 1:30) # looking under the hood with gginnards::geom_debug() gginnards.installed <- requireNamespace("gginnards", quietly = TRUE) if (gginnards.installed) { library(gginnards) ggplot(data = d, aes(x, y, label = lab, colour = group)) + stat_dens2d_filter(geom = "debug") ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens2d_filter(geom = "debug", return.density = TRUE) }
stat_dens2d_labels()
Sets values mapped to the
label
aesthetic to ""
or a user provided character string
based on the local density in regions of a plot panel. Its main use is
together with repulsive geoms from package ggrepel
.
If there is no mapping to label
in data
, the mapping is set
to rownames(data)
, with a message.
stat_dens2d_labels( mapping = NULL, data = NULL, geom = "text", position = "identity", ..., keep.fraction = 0.1, keep.number = Inf, keep.sparse = TRUE, keep.these = FALSE, exclude.these = FALSE, these.target = "label", pool.along = c("xy", "x", "y", "none"), xintercept = 0, yintercept = 0, invert.selection = FALSE, h = NULL, n = NULL, label.fill = "", return.density = FALSE, na.rm = TRUE, show.legend = FALSE, inherit.aes = TRUE )
stat_dens2d_labels( mapping = NULL, data = NULL, geom = "text", position = "identity", ..., keep.fraction = 0.1, keep.number = Inf, keep.sparse = TRUE, keep.these = FALSE, exclude.these = FALSE, these.target = "label", pool.along = c("xy", "x", "y", "none"), xintercept = 0, yintercept = 0, invert.selection = FALSE, h = NULL, n = NULL, label.fill = "", return.density = FALSE, na.rm = TRUE, show.legend = FALSE, inherit.aes = TRUE )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific dataset - only needed if you want to override the plot defaults. |
geom |
The geometric object to use display the data. |
position |
The position adjustment to use for overlapping points on this layer |
... |
other arguments passed on to |
keep.fraction |
numeric [0..1]. The fraction of the observations (or
rows) in |
keep.number |
integer Set the maximum number of observations to retain,
effective only if obeying |
keep.sparse |
logical If |
keep.these , exclude.these
|
character vector, integer vector, logical
vector or function that takes one or more variables in data selected by
|
these.target |
character, numeric or logical selecting one or more
column(s) of |
pool.along |
character, one of |
xintercept , yintercept
|
numeric The split points for the data filtering. |
invert.selection |
logical If |
h |
vector of bandwidths for x and y directions. Defaults to normal reference bandwidth (see bandwidth.nrd). A scalar value will be taken to apply to both directions. |
n |
Number of grid points in each direction. Can be scalar or a length-2 integer vector |
label.fill |
character vector of length 1, a function or |
return.density |
logical vector of lenght 1. If |
na.rm |
a logical value indicating whether NA values should be stripped before the computation proceeds. |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
stat_dens2d_labels()
is designed to work together with
geometries from package 'ggrepel'. To avoid text labels being plotted over
unlabelled points all the rows in data need to be retained but
labels replaced with the empty character string, ""
. Function
stat_dens2d_filter
cannot be used with the repulsive geoms
from 'ggrepel' because it drops observations.
stat_dens2d_labels()
can be useful also in other situations, as the
substitution character string can be set by the user by passing an argument
to label.fill
. If this argument is NULL
the unselected rows
are filtered out identically as by stat_dens2d_filter
.
The local density of observations in 2D (x and y) is computed
with function kde2d
and used to select observations,
passing to the geom all the rows in its data
input but with with the
text of labels replaced in those "not kept". The default is to select
observations in sparse regions of the plot, but the selection can be
inverted so that only observations in the densest regions are returned.
Specific observations can be protected from having the label replaced by
passing a suitable argument to keep.these
. Logical and integer
vectors function as indexes to rows in data
, while a character
vector is compared to values in the variable mapped to the label
aesthetic. A function passed as argument to keep.these
will receive
as its first argument the values in the variable mapped to label
and
should return a character, logical or numeric vector as described above.
How many labels are retained intact in addition to those in
keep.these
is controlled with arguments passed to keep.number
and keep.fraction
. keep.number
sets the maximum number of
observations selected, whenever keep.fraction
results in fewer
observations selected, it is obeyed.
Computation of density and of the default bandwidth require at least
two observations with different values. If data do not fulfill this
condition, they are kept only if keep.fraction = 1
. This is correct
behavior for a single observation, but can be surprising in the case of
multiple observations.
Parameters keep.these
and exclude.these
make it possible to
force inclusion or exclusion of observations after the density is computed.
In case of conflict, exclude.these
overrides keep.these
.
A plot layer instance. Using as output data
the input
data
after value substitution based on a 2D the filtering criterion.
Which points are kept and which not depends on how dense a grid is used
and how flexible the density surface estimate is. This depends on the
values passed as arguments to parameters n
, bw
and
kernel
. It is also important to be aware that both
geom_text()
and geom_text_repel()
can avoid overplotting by
discarding labels at the plot rendering stage, i.e., what is plotted may
differ from what is returned by this statistic.
stat_dens2d_filter
and kde2d
used
internally. Parameters n
, h
in this statistic correspond to
the parameters with the same name in this imported function. Limits are set
to the limits of the plot scales.
Other statistics returning a subset of data:
stat_dens1d_filter()
,
stat_dens1d_labels()
,
stat_dens2d_filter()
random_string <- function(len = 6) { paste(sample(letters, len, replace = TRUE), collapse = "") } # Make random data. set.seed(1001) d <- tibble::tibble( x = rnorm(100), y = rnorm(100), group = rep(c("A", "B"), c(50, 50)), lab = replicate(100, { random_string() }) ) # using defaults ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels() ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels(keep.these = "zoujdg") ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels(keep.these = function(x) {grepl("^z", x)}) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels(geom = "text_s", position = position_nudge_center(x = 0.1, y = 0.1, center_x = mean, center_y = mean), vjust = "outward_mean", hjust = "outward_mean") + expand_limits(x = c(-4, 4.5)) ggrepel.installed <- requireNamespace("ggrepel", quietly = TRUE) if (ggrepel.installed) { library(ggrepel) ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens2d_labels(geom = "text_repel") ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens2d_labels(geom = "text_repel", label.fill = NA) # we keep labels starting with "a" across the whole plot, but all in sparse # regions. To achieve this we pass as argument to label.fill a fucntion # instead of a character string. label.fun <- function(x) {ifelse(grepl("^a", x), x, "")} ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens2d_labels(geom = "text_repel", label.fill = label.fun) } # Using geom_debug() we can see that all 100 rows in \code{d} are # returned. But only those labelled in the previous example still contain # the original labels. gginnards.installed <- requireNamespace("gginnards", quietly = TRUE) if (gginnards.installed) { library(gginnards) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels(geom = "debug") ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels(geom = "debug", return.density = TRUE) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels(geom = "debug", label.fill = NULL) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels(geom = "debug", label.fill = FALSE, return.density = TRUE) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels(geom = "debug", label.fill = NULL, return.density = TRUE) ggplot(data = d, aes(x, y)) + geom_point() + stat_dens2d_labels(geom = "debug") }
random_string <- function(len = 6) { paste(sample(letters, len, replace = TRUE), collapse = "") } # Make random data. set.seed(1001) d <- tibble::tibble( x = rnorm(100), y = rnorm(100), group = rep(c("A", "B"), c(50, 50)), lab = replicate(100, { random_string() }) ) # using defaults ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels() ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels(keep.these = "zoujdg") ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels(keep.these = function(x) {grepl("^z", x)}) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels(geom = "text_s", position = position_nudge_center(x = 0.1, y = 0.1, center_x = mean, center_y = mean), vjust = "outward_mean", hjust = "outward_mean") + expand_limits(x = c(-4, 4.5)) ggrepel.installed <- requireNamespace("ggrepel", quietly = TRUE) if (ggrepel.installed) { library(ggrepel) ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens2d_labels(geom = "text_repel") ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens2d_labels(geom = "text_repel", label.fill = NA) # we keep labels starting with "a" across the whole plot, but all in sparse # regions. To achieve this we pass as argument to label.fill a fucntion # instead of a character string. label.fun <- function(x) {ifelse(grepl("^a", x), x, "")} ggplot(data = d, aes(x, y, label = lab, colour = group)) + geom_point() + stat_dens2d_labels(geom = "text_repel", label.fill = label.fun) } # Using geom_debug() we can see that all 100 rows in \code{d} are # returned. But only those labelled in the previous example still contain # the original labels. gginnards.installed <- requireNamespace("gginnards", quietly = TRUE) if (gginnards.installed) { library(gginnards) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels(geom = "debug") ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels(geom = "debug", return.density = TRUE) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels(geom = "debug", label.fill = NULL) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels(geom = "debug", label.fill = FALSE, return.density = TRUE) ggplot(data = d, aes(x, y, label = lab)) + geom_point() + stat_dens2d_labels(geom = "debug", label.fill = NULL, return.density = TRUE) ggplot(data = d, aes(x, y)) + geom_point() + stat_dens2d_labels(geom = "debug") }
data
stat_fmt_tb
selects, reorders and/or renames columns and
or rows of a tibble nested in data
. It can also apply user supplied
functions to data columns. This stat is intended to be used to pre-process
tibble
objects mapped to the label
aesthetic before adding
them to a plot with geom_table
.
stat_fmt_tb( mapping = NULL, data = NULL, geom = "table", tb.vars = NULL, tb.rows = NULL, tb.funs = list(), digits = 3, position = "identity", table.theme = NULL, table.rownames = FALSE, table.colnames = TRUE, table.hjust = 0.5, parse = FALSE, na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, ... )
stat_fmt_tb( mapping = NULL, data = NULL, geom = "table", tb.vars = NULL, tb.rows = NULL, tb.funs = list(), digits = 3, position = "identity", table.theme = NULL, table.rownames = FALSE, table.colnames = TRUE, table.hjust = 0.5, parse = FALSE, na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, ... )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific dataset - only needed if you want to override the plot defaults. |
geom |
The geometric object to use display the data |
tb.vars , tb.rows
|
character or numeric vectors, optionally named, used to select and/or rename the columns or rows in the table returned. |
tb.funs |
named list of functions to be applied to |
digits |
integer indicating the number of significant digits to be
retained in data. Use |
position |
The position adjustment to use for overlapping points on this layer |
table.theme |
NULL, list or function A 'gridExtra' |
table.rownames , table.colnames
|
logical flag to enable or disabling printing of row names and column names. |
table.hjust |
numeric Horizontal justification for the core and column headings of the table. |
parse |
If |
na.rm |
a logical indicating whether |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
... |
other arguments passed on to |
One or more functions to be applied can be passed in a named list to parameter 'tb.funs'. Functions are matched by name to columns, after column selection and renaming have been applied.
A plot layer instance. Using as output data
a copy of the
input data
in which the data frames mapped to label
have been
modified.
The output of sequentially applying
slice
with tb.rows
as argument and
select
with tb.vars
to a list variable
list mapped to label
and containing a single tibble per row
in data
.
See geom_table
for details on how tables respond
to mapped aesthetics and table themes. For details on predefined table
themes see ttheme_gtdefault
.
my.df <- tibble::tibble( x = c(1, 2), y = c(0, 4), group = c("A", "B"), tbs = list(a = tibble::tibble(Xa = 1:6, Y = rep(c("x", "y"), 3)), b = tibble::tibble(Xb = 1:3, Y = "x")) ) ggplot(my.df, aes(x, y, label = tbs)) + stat_fmt_tb() + expand_limits(x = c(0,3), y = c(-2, 6)) # Hide column names, diplay row names ggplot(my.df, aes(x, y, label = tbs)) + stat_fmt_tb(table.colnames = FALSE, table.rownames = TRUE) + expand_limits(x = c(0,3), y = c(-2, 6)) # Use a theme for the table ggplot(my.df, aes(x, y, label = tbs)) + stat_fmt_tb(table.theme = ttheme_gtlight) + expand_limits(x = c(0,3), y = c(-2, 6)) # selection and renaming by column position ggplot(my.df, aes(x, y, label = tbs)) + stat_fmt_tb(tb.vars = c(value = 1, group = 2), tb.rows = 1:3) + expand_limits(x = c(0,3), y = c(-2, 6)) # apply functions to columns ggplot(my.df, aes(x, y, label = tbs)) + stat_fmt_tb(tb.vars = c(value = 1, group = 2), tb.rows = 1:3, tb.funs = list(group = function(x) {sprintf("italic(%s)", x)}, value = function(x) {ifelse(x > 2, "bold(zz)", x)}), parse = TRUE) + expand_limits(x = c(0,3), y = c(-2, 6)) # selection, reordering and renaming by column position ggplot(my.df, aes(x, y, label = tbs)) + stat_fmt_tb(tb.vars = c(group = 2, value = 1), tb.rows = 1:3) + expand_limits(x = c(0,3), y = c(-2, 6)) # selection and renaming, using partial matching to column name ggplot(my.df, aes(x, y, label = tbs)) + stat_fmt_tb(tb.vars = c(value = "X", group = "Y"), tb.rows = 1:3) + expand_limits(x = c(0,3), y = c(-2, 6))
my.df <- tibble::tibble( x = c(1, 2), y = c(0, 4), group = c("A", "B"), tbs = list(a = tibble::tibble(Xa = 1:6, Y = rep(c("x", "y"), 3)), b = tibble::tibble(Xb = 1:3, Y = "x")) ) ggplot(my.df, aes(x, y, label = tbs)) + stat_fmt_tb() + expand_limits(x = c(0,3), y = c(-2, 6)) # Hide column names, diplay row names ggplot(my.df, aes(x, y, label = tbs)) + stat_fmt_tb(table.colnames = FALSE, table.rownames = TRUE) + expand_limits(x = c(0,3), y = c(-2, 6)) # Use a theme for the table ggplot(my.df, aes(x, y, label = tbs)) + stat_fmt_tb(table.theme = ttheme_gtlight) + expand_limits(x = c(0,3), y = c(-2, 6)) # selection and renaming by column position ggplot(my.df, aes(x, y, label = tbs)) + stat_fmt_tb(tb.vars = c(value = 1, group = 2), tb.rows = 1:3) + expand_limits(x = c(0,3), y = c(-2, 6)) # apply functions to columns ggplot(my.df, aes(x, y, label = tbs)) + stat_fmt_tb(tb.vars = c(value = 1, group = 2), tb.rows = 1:3, tb.funs = list(group = function(x) {sprintf("italic(%s)", x)}, value = function(x) {ifelse(x > 2, "bold(zz)", x)}), parse = TRUE) + expand_limits(x = c(0,3), y = c(-2, 6)) # selection, reordering and renaming by column position ggplot(my.df, aes(x, y, label = tbs)) + stat_fmt_tb(tb.vars = c(group = 2, value = 1), tb.rows = 1:3) + expand_limits(x = c(0,3), y = c(-2, 6)) # selection and renaming, using partial matching to column name ggplot(my.df, aes(x, y, label = tbs)) + stat_fmt_tb(tb.vars = c(value = "X", group = "Y"), tb.rows = 1:3) + expand_limits(x = c(0,3), y = c(-2, 6))
stat_functions()
computes values from functions and returns new data
containing numeric vectors for x
and y
. As function definitions
are passed through data
this statistic follows the grammar of graphics in
its behaviour.
stat_functions( mapping = NULL, data = NULL, n = 101, geom = "line", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ... )
stat_functions( mapping = NULL, data = NULL, n = 101, geom = "line", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ... )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific dataset. Useful if the function curve is to be overlaid on other layers. |
n |
integer Number of points to interpolate along the x axis. |
geom |
The geometric object to use display the data |
position |
The position adjustment to use on this layer |
na.rm |
a logical indicating whether |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
... |
other arguments passed on to |
This statistic can be used to plot values computed by functions. As
it follows the grammar of graphics, grouping and facets are supported. In
this it differs from geom_function
which behaves
like a plot annotation.
Aesthetics xmin
and xmax
should be mapped to numeric values
defining the range of the vector to be created and passed as argument to
the function to compute the y
values, and returned as x
in
data. n
is the length of this x
vector.
A plot layer instance.
Data frame with n
rows or a multiple of
this, one for each
row in data
.
numeric vector
numeric vactor
integer vector, with values corresponding to rows in the input
data
, i.e., for each function
As shown in one example below geom_debug
can be
used to print the computed values returned by any statistic. The output
shown includes also values mapped to aesthetics.
# one function df1 <- data.frame(min = 0, max = pi, fun = I(list(sin))) ggplot(df1, aes(xmin = min, xmax = max, y = fun)) + stat_functions() ggplot(df1, aes(xmin = min, xmax = max, y = fun)) + stat_functions(geom = "point", n = 20) # two functions df2 <- data.frame(min = -pi, max = pi, fun = I(list(sin, cos)), name = c("sin", "cos")) # each function must be in a separate group for correct plotting of lines ggplot(df2, aes(xmin = min, xmax = max, y = fun, group = after_stat(idx))) + stat_functions() ggplot(df2, aes(xmin = min, xmax = max, y = fun, colour = name)) + stat_functions() ggplot(df2, aes(xmin = min, xmax = max, y = fun)) + stat_functions() + facet_grid(~ name) # two curves with same function df3 <- data.frame(min = c(-pi, 0), max = c(0,pi), fun = I(list(sin, sin)), name = c("negative", "positive")) ggplot(df3, aes(xmin = min, xmax = max, y = fun, colour = name)) + stat_functions() # We use geom_debug() to see the computed values gginnards.installed <- requireNamespace("gginnards", quietly = TRUE) if (gginnards.installed) { library(gginnards) ggplot(df1, aes(xmin = min, xmax = max, y = fun)) + stat_functions(geom = "debug") }
# one function df1 <- data.frame(min = 0, max = pi, fun = I(list(sin))) ggplot(df1, aes(xmin = min, xmax = max, y = fun)) + stat_functions() ggplot(df1, aes(xmin = min, xmax = max, y = fun)) + stat_functions(geom = "point", n = 20) # two functions df2 <- data.frame(min = -pi, max = pi, fun = I(list(sin, cos)), name = c("sin", "cos")) # each function must be in a separate group for correct plotting of lines ggplot(df2, aes(xmin = min, xmax = max, y = fun, group = after_stat(idx))) + stat_functions() ggplot(df2, aes(xmin = min, xmax = max, y = fun, colour = name)) + stat_functions() ggplot(df2, aes(xmin = min, xmax = max, y = fun)) + stat_functions() + facet_grid(~ name) # two curves with same function df3 <- data.frame(min = c(-pi, 0), max = c(0,pi), fun = I(list(sin, sin)), name = c("negative", "positive")) ggplot(df3, aes(xmin = min, xmax = max, y = fun, colour = name)) + stat_functions() # We use geom_debug() to see the computed values gginnards.installed <- requireNamespace("gginnards", quietly = TRUE) if (gginnards.installed) { library(gginnards) ggplot(df1, aes(xmin = min, xmax = max, y = fun)) + stat_functions(geom = "debug") }
stat_panel_counts()
counts the number of observations in each panel.
stat_group_counts()
counts the number of observations in each group.
By default they add one or more text labels to the top right corner of each
panel. Grouping is ignored by stat_panel_counts()
. If no grouping
exists, the two statistics behave similarly.
stat_panel_counts( mapping = NULL, data = NULL, geom = "text_npc", position = "identity", label.x = "right", label.y = "top", na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, ... ) stat_group_counts( mapping = NULL, data = NULL, geom = "text_npc", position = "identity", label.x = "right", label.y = "top", hstep = 0, vstep = NULL, digits = 2, na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, ... )
stat_panel_counts( mapping = NULL, data = NULL, geom = "text_npc", position = "identity", label.x = "right", label.y = "top", na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, ... ) stat_group_counts( mapping = NULL, data = NULL, geom = "text_npc", position = "identity", label.x = "right", label.y = "top", hstep = 0, vstep = NULL, digits = 2, na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, ... )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific dataset. Rarely used, as you will not want to override the plot defaults. |
geom |
The geometric object to use display the data |
position |
The position adjustment to use on this layer |
label.x , label.y
|
|
na.rm |
a logical indicating whether |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
... |
other arguments passed on to |
hstep , vstep
|
numeric in npc units, the horizontal and vertical step used between labels for different groups. |
digits |
integer Number of digits for fraction and percent labels. |
These statistics can be used to automatically count observations in
each panel of a plot, and by default add these counts as text labels. These
statistics, unlike stat_quadrant_counts()
requires only one of
x or y aesthetics and can be used together with statistics
that have the same requirement, like stat_density()
.
The default position of the label is in the top right corner. When using
facets even with free limits for x and y axes, the location
of the labels is consistent across panels. This is achieved by use of
geom = "text_npc"
or geom = "label_npc"
. To pass the
positions in native data units to label.x
and label.y
, pass
also explicitly geom = "text"
, geom = "label"
or some other
geometry that use the x and/or y aesthetics. A vector with
the same length as the number of panels in the figure can be used if
needed.
A plot layer instance. Using as output data
the counts of
observations in each plot panel or per group in each plot panel.
Data frame with one or more rows, one for each
group of observations for which counts are counted in data
.
x value of label position in data- or npc units, respectively
y value of label position in data- or npc units, respectively
number of observations as an integer
number of observations as character
As shown in one example below geom_debug
can be
used to print the computed values returned by any statistic. The output
shown includes also values mapped to aesthetics, like label
in the
example. x
and y
are included in the output only if mapped.
If a factor is mapped to x
or to y
aesthetics each level
of the factor constitutes a group, in this case the default positioning and
geom using NPC pseudo aesthetics will have to be overriden by passing
geom = "text"
and data coordinates used. The default for factors
may change in the future.
Other Functions for quadrant and volcano plots:
geom_quadrant_lines()
,
stat_quadrant_counts()
# generate artificial data with numeric x and y set.seed(67821) x <- 1:100 y <- rnorm(length(x), mean = 10) group <- factor(rep(c("A", "B"), times = 50)) my.data <- data.frame(x, y, group) # using automatically generated text labels ggplot(my.data, aes(x, y)) + geom_point() + stat_panel_counts() ggplot(my.data, aes(x, y, colour = group)) + geom_point() + stat_panel_counts() ggplot(my.data, aes(x, y, colour = group)) + geom_point() + stat_group_counts() ggplot(my.data, aes(x, y, colour = group)) + geom_point() + stat_group_counts(label.x = "left", hstep = 0.06, vstep = 0) ggplot(my.data, aes(x, y, colour = group)) + geom_point() + stat_group_counts(aes(label = after_stat(pc.label))) ggplot(my.data, aes(x, y, colour = group)) + geom_point() + stat_group_counts(aes(label = after_stat(pc.label)), digits = 3) ggplot(my.data, aes(x, y, colour = group)) + geom_point() + stat_group_counts(aes(label = after_stat(fr.label))) ggplot(my.data, aes(x, y, colour = group)) + geom_point() + stat_group_counts(aes(label = after_stat(dec.label))) # one of x or y can be a factor # label.x or label.y along the factor can be set to "factor" together # with the use of geom_text() ggplot(mpg, aes(factor(cyl), hwy)) + stat_boxplot() + stat_group_counts(geom = "text", label.y = 10, label.x = "factor") + stat_panel_counts() # Numeric values can be used to build labels with alternative formats # Here with sprintf(), but paste() and format() also work. ggplot(my.data, aes(x, y)) + geom_point() + stat_panel_counts(aes(label = sprintf("%i observations", after_stat(count)))) + scale_y_continuous(expand = expansion(mult = c(0.05, 0.12))) ggplot(mpg, aes(factor(cyl), hwy)) + stat_boxplot() + stat_group_counts(geom = "text", aes(label = sprintf("(%i)", after_stat(count))), label.y = 10, label.x = "factor") ggplot(mpg, aes(factor(cyl), hwy)) + stat_boxplot() + stat_group_counts(aes(label = sprintf("n[%i]~`=`~%i", after_stat(x), after_stat(count))), parse = TRUE, geom = "text", label.y = 10, label.x = "factor") + stat_panel_counts(aes(label = sprintf("sum(n[i])~`=`~%i", after_stat(count))), parse = TRUE) # label position ggplot(my.data, aes(y)) + stat_panel_counts(label.x = "left") + stat_density(alpha = 0.5) ggplot(my.data, aes(y, colour = group)) + stat_group_counts(label.y = "top") + stat_density(aes(fill = group), alpha = 0.3) # The numeric value can be used as a label as is ggplot(mpg, aes(factor(cyl), hwy)) + stat_boxplot() + stat_group_counts(geom = "text", aes(label = after_stat(count)), label.x = "factor", label.y = 10) + annotate(geom = "text", x = 0.55, y = 10, label = "n[i]~`=`", parse = TRUE) # We use geom_debug() to see the computed values gginnards.installed <- requireNamespace("gginnards", quietly = TRUE) if (gginnards.installed) { library(gginnards) ggplot(my.data, aes(x, y)) + geom_point() + stat_panel_counts(geom = "debug") } if (gginnards.installed) { ggplot(my.data, aes(x, y, colour = group)) + geom_point() + stat_group_counts(geom = "debug") }
# generate artificial data with numeric x and y set.seed(67821) x <- 1:100 y <- rnorm(length(x), mean = 10) group <- factor(rep(c("A", "B"), times = 50)) my.data <- data.frame(x, y, group) # using automatically generated text labels ggplot(my.data, aes(x, y)) + geom_point() + stat_panel_counts() ggplot(my.data, aes(x, y, colour = group)) + geom_point() + stat_panel_counts() ggplot(my.data, aes(x, y, colour = group)) + geom_point() + stat_group_counts() ggplot(my.data, aes(x, y, colour = group)) + geom_point() + stat_group_counts(label.x = "left", hstep = 0.06, vstep = 0) ggplot(my.data, aes(x, y, colour = group)) + geom_point() + stat_group_counts(aes(label = after_stat(pc.label))) ggplot(my.data, aes(x, y, colour = group)) + geom_point() + stat_group_counts(aes(label = after_stat(pc.label)), digits = 3) ggplot(my.data, aes(x, y, colour = group)) + geom_point() + stat_group_counts(aes(label = after_stat(fr.label))) ggplot(my.data, aes(x, y, colour = group)) + geom_point() + stat_group_counts(aes(label = after_stat(dec.label))) # one of x or y can be a factor # label.x or label.y along the factor can be set to "factor" together # with the use of geom_text() ggplot(mpg, aes(factor(cyl), hwy)) + stat_boxplot() + stat_group_counts(geom = "text", label.y = 10, label.x = "factor") + stat_panel_counts() # Numeric values can be used to build labels with alternative formats # Here with sprintf(), but paste() and format() also work. ggplot(my.data, aes(x, y)) + geom_point() + stat_panel_counts(aes(label = sprintf("%i observations", after_stat(count)))) + scale_y_continuous(expand = expansion(mult = c(0.05, 0.12))) ggplot(mpg, aes(factor(cyl), hwy)) + stat_boxplot() + stat_group_counts(geom = "text", aes(label = sprintf("(%i)", after_stat(count))), label.y = 10, label.x = "factor") ggplot(mpg, aes(factor(cyl), hwy)) + stat_boxplot() + stat_group_counts(aes(label = sprintf("n[%i]~`=`~%i", after_stat(x), after_stat(count))), parse = TRUE, geom = "text", label.y = 10, label.x = "factor") + stat_panel_counts(aes(label = sprintf("sum(n[i])~`=`~%i", after_stat(count))), parse = TRUE) # label position ggplot(my.data, aes(y)) + stat_panel_counts(label.x = "left") + stat_density(alpha = 0.5) ggplot(my.data, aes(y, colour = group)) + stat_group_counts(label.y = "top") + stat_density(aes(fill = group), alpha = 0.3) # The numeric value can be used as a label as is ggplot(mpg, aes(factor(cyl), hwy)) + stat_boxplot() + stat_group_counts(geom = "text", aes(label = after_stat(count)), label.x = "factor", label.y = 10) + annotate(geom = "text", x = 0.55, y = 10, label = "n[i]~`=`", parse = TRUE) # We use geom_debug() to see the computed values gginnards.installed <- requireNamespace("gginnards", quietly = TRUE) if (gginnards.installed) { library(gginnards) ggplot(my.data, aes(x, y)) + geom_point() + stat_panel_counts(geom = "debug") } if (gginnards.installed) { ggplot(my.data, aes(x, y, colour = group)) + geom_point() + stat_group_counts(geom = "debug") }
stat_quadrant_counts()
counts the number of observations in each
quadrant of a plot panel. By default it adds a text label to the far corner
of each quadrant. It can also be used to obtain the total number of
observations in each of two pairs of quadrants or in the whole panel.
Grouping is ignored, so en every case a single count is computed for each
quadrant in a plot panel.
stat_quadrant_counts( mapping = NULL, data = NULL, geom = "text_npc", position = "identity", quadrants = NULL, pool.along = c("none", "x", "y", "xy"), xintercept = 0, yintercept = 0, label.x = NULL, label.y = NULL, digits = 2, na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, ... )
stat_quadrant_counts( mapping = NULL, data = NULL, geom = "text_npc", position = "identity", quadrants = NULL, pool.along = c("none", "x", "y", "xy"), xintercept = 0, yintercept = 0, label.x = NULL, label.y = NULL, digits = 2, na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, ... )
mapping |
The aesthetic mapping, usually constructed with
|
data |
A layer specific dataset - only needed if you want to override the plot defaults. |
geom |
The geometric object to use display the data |
position |
The position adjustment to use on this layer |
quadrants |
integer vector indicating which quadrants are of interest,
with a |
pool.along |
character, one of |
xintercept , yintercept
|
numeric the coordinates of the origin of the quadrants. |
label.x , label.y
|
|
digits |
integer Number of digits for fraction and percent labels. |
na.rm |
a logical indicating whether |
show.legend |
logical. Should this layer be included in the legends?
|
inherit.aes |
If |
... |
other arguments passed on to |
This statistic can be used to automatically count observations in
each of the four quadrants of a plot, and by default add these counts as
text labels. Values exactly equal to xintercept
or
yintercept
are counted together with those larger than the
intercepts. An argument value of zero, passed to formal parameter
quadrants
is interpreted as a request for the count of all
observations in each plot panel.
The default origin of quadrants is at xintercept = 0
,
yintercept = 0
. Also by default, counts are computed for all
quadrants within the x and y scale limits, but ignoring any
marginal scale expansion. The default positions of the labels is in the
farthest corner or edge of each quadrant using npc coordinates.
Consequently, when using facets even with free limits for x and
y axes, the location of the labels is consistent across panels. This
is achieved by use of geom = "text_npc"
or geom =
"label_npc"
. To pass the positions in native data units, pass geom =
"text"
explicitly as argument.
A plot layer instance. Using as output data
the counts of
observations per plot quadrant.
Data frame with one to four rows, one for each
quadrant for which counts are counted in data
.
integer, one of 0:4
x value of label position in data units
y value of label position in data units
x value of label position in npc units
y value of label position in npc units
number of observations in the quadrant(s)
number of onservations in data
number of observations as character
percent of observations as character
fraction of observations as character
.
As shown in one example below geom_debug
can be
used to print the computed values returned by any statistic. The output
shown includes also values mapped to aesthetics, like label
in the
example.
Other Functions for quadrant and volcano plots:
geom_quadrant_lines()
,
stat_panel_counts()
# generate artificial data set.seed(4321) x <- -50:50 y <- rnorm(length(x), mean = 0) my.data <- data.frame(x, y) # using automatically generated text labels, default origin at (0, 0) ggplot(my.data, aes(x, y)) + geom_point() + geom_quadrant_lines() + stat_quadrant_counts() ggplot(my.data, aes(x, y)) + geom_point() + geom_quadrant_lines() + stat_quadrant_counts(aes(label = after_stat(pc.label))) ggplot(my.data, aes(x, y)) + geom_point() + geom_quadrant_lines() + stat_quadrant_counts(aes(label = after_stat(fr.label))) ggplot(my.data, aes(x, y)) + geom_point() + geom_quadrant_lines() + stat_quadrant_counts(aes(label = after_stat(dec.label))) ggplot(my.data, aes(x, y)) + geom_point() + geom_quadrant_lines() + stat_quadrant_counts(aes(label = sprintf("%i observations", after_stat(count)))) + scale_y_continuous(expand = expansion(c(0.05, 0.15))) # reserve space # user specified origin ggplot(my.data, aes(x, y)) + geom_quadrant_lines(colour = "blue", xintercept = 10, yintercept = -1) + stat_quadrant_counts(colour = "blue", xintercept = 10, yintercept = -1) + geom_point() + scale_y_continuous(expand = expansion(mult = 0.15)) ggplot(my.data, aes(x, y)) + geom_quadrant_lines(colour = "blue", xintercept = 10, yintercept = -1) + stat_quadrant_counts(aes(label = after_stat(pc.label)), colour = "blue", xintercept = 10, yintercept = -1) + geom_point() + scale_y_continuous(expand = expansion(mult = 0.15)) # more digits in labels ggplot(my.data, aes(x, y)) + geom_quadrant_lines(colour = "blue", xintercept = 10, yintercept = -1) + stat_quadrant_counts(aes(label = after_stat(pc.label)), digits = 3, colour = "blue", xintercept = 10, yintercept = -1) + geom_point() + scale_y_continuous(expand = expansion(mult = 0.15)) ggplot(my.data, aes(x, y)) + geom_quadrant_lines(colour = "blue", xintercept = 10, yintercept = -1) + stat_quadrant_counts(aes(label = after_stat(fr.label)), colour = "blue", xintercept = 10, yintercept = -1) + geom_point() + scale_y_continuous(expand = expansion(mult = 0.15)) # grouped quadrants ggplot(my.data, aes(x, y)) + geom_quadrant_lines(colour = "blue", pool.along = "x") + stat_quadrant_counts(colour = "blue", label.x = "right", pool.along = "x") + geom_point() + scale_y_continuous(expand = expansion(mult = 0.15)) # whole panel ggplot(my.data, aes(x, y)) + geom_point() + stat_quadrant_counts(quadrants = 0, label.x = "left", label.y = "bottom") + scale_y_continuous(expand = expansion(mult = c(0.15, 0.05))) # use a different geometry ggplot(my.data, aes(x, y)) + geom_point() + stat_quadrant_counts(geom = "text") # use geom_text() # Numeric values can be used to build labels with alternative formats # Here with sprintf(), but paste() and format() also work. ggplot(my.data, aes(x, y)) + geom_quadrant_lines(colour = "blue") + stat_quadrant_counts(aes(label = sprintf("%i of %i genes", after_stat(count), after_stat(total))), colour = "blue") + geom_point() + scale_y_continuous(expand = expansion(mult = 0.15)) # We use geom_debug() to see the computed values gginnards.installed <- requireNamespace("gginnards", quietly = TRUE) if (gginnards.installed) { library(gginnards) ggplot(my.data, aes(x, y)) + geom_point() + stat_quadrant_counts(geom = "debug") ggplot(my.data, aes(x, y)) + geom_point() + stat_quadrant_counts(geom = "debug", xintercept = 50) }
# generate artificial data set.seed(4321) x <- -50:50 y <- rnorm(length(x), mean = 0) my.data <- data.frame(x, y) # using automatically generated text labels, default origin at (0, 0) ggplot(my.data, aes(x, y)) + geom_point() + geom_quadrant_lines() + stat_quadrant_counts() ggplot(my.data, aes(x, y)) + geom_point() + geom_quadrant_lines() + stat_quadrant_counts(aes(label = after_stat(pc.label))) ggplot(my.data, aes(x, y)) + geom_point() + geom_quadrant_lines() + stat_quadrant_counts(aes(label = after_stat(fr.label))) ggplot(my.data, aes(x, y)) + geom_point() + geom_quadrant_lines() + stat_quadrant_counts(aes(label = after_stat(dec.label))) ggplot(my.data, aes(x, y)) + geom_point() + geom_quadrant_lines() + stat_quadrant_counts(aes(label = sprintf("%i observations", after_stat(count)))) + scale_y_continuous(expand = expansion(c(0.05, 0.15))) # reserve space # user specified origin ggplot(my.data, aes(x, y)) + geom_quadrant_lines(colour = "blue", xintercept = 10, yintercept = -1) + stat_quadrant_counts(colour = "blue", xintercept = 10, yintercept = -1) + geom_point() + scale_y_continuous(expand = expansion(mult = 0.15)) ggplot(my.data, aes(x, y)) + geom_quadrant_lines(colour = "blue", xintercept = 10, yintercept = -1) + stat_quadrant_counts(aes(label = after_stat(pc.label)), colour = "blue", xintercept = 10, yintercept = -1) + geom_point() + scale_y_continuous(expand = expansion(mult = 0.15)) # more digits in labels ggplot(my.data, aes(x, y)) + geom_quadrant_lines(colour = "blue", xintercept = 10, yintercept = -1) + stat_quadrant_counts(aes(label = after_stat(pc.label)), digits = 3, colour = "blue", xintercept = 10, yintercept = -1) + geom_point() + scale_y_continuous(expand = expansion(mult = 0.15)) ggplot(my.data, aes(x, y)) + geom_quadrant_lines(colour = "blue", xintercept = 10, yintercept = -1) + stat_quadrant_counts(aes(label = after_stat(fr.label)), colour = "blue", xintercept = 10, yintercept = -1) + geom_point() + scale_y_continuous(expand = expansion(mult = 0.15)) # grouped quadrants ggplot(my.data, aes(x, y)) + geom_quadrant_lines(colour = "blue", pool.along = "x") + stat_quadrant_counts(colour = "blue", label.x = "right", pool.along = "x") + geom_point() + scale_y_continuous(expand = expansion(mult = 0.15)) # whole panel ggplot(my.data, aes(x, y)) + geom_point() + stat_quadrant_counts(quadrants = 0, label.x = "left", label.y = "bottom") + scale_y_continuous(expand = expansion(mult = c(0.15, 0.05))) # use a different geometry ggplot(my.data, aes(x, y)) + geom_point() + stat_quadrant_counts(geom = "text") # use geom_text() # Numeric values can be used to build labels with alternative formats # Here with sprintf(), but paste() and format() also work. ggplot(my.data, aes(x, y)) + geom_quadrant_lines(colour = "blue") + stat_quadrant_counts(aes(label = sprintf("%i of %i genes", after_stat(count), after_stat(total))), colour = "blue") + geom_point() + scale_y_continuous(expand = expansion(mult = 0.15)) # We use geom_debug() to see the computed values gginnards.installed <- requireNamespace("gginnards", quietly = TRUE) if (gginnards.installed) { library(gginnards) ggplot(my.data, aes(x, y)) + geom_point() + stat_quadrant_counts(geom = "debug") ggplot(my.data, aes(x, y)) + geom_point() + stat_quadrant_counts(geom = "debug", xintercept = 50) }
This functions tries to convert any R object into a data.frame object.
If x
is already a data.frame, it is returned as is. If it is
a list or a vector it is converted by means of as.data.frame()
.
If of any other type, a conversion into an object of class xts
is
attempted by means of try.xts()
and if successful the xts
object is converted into a data frame with a variable time
containing times as POSIXct
and the remaining data columns with
the time series data. In this conversion row names are stripped.
try_data_frame( x, time.resolution = "month", as.numeric = FALSE, col.names = NULL ) try_tibble(x, time.resolution = "month", as.numeric = FALSE, col.names = NULL)
try_data_frame( x, time.resolution = "month", as.numeric = FALSE, col.names = NULL ) try_tibble(x, time.resolution = "month", as.numeric = FALSE, col.names = NULL)
x |
An R object |
time.resolution |
character The time unit to which the returned time values will be rounded. |
as.numeric |
logical If TRUE convert time to numeric, expressed as fractional calendar years. |
col.names |
character vector |
A tibble::tibble
object, derived from data.frame
.
The time zone was set to "UTC" by try.xts() in the test
cases I used. Setting TZ to "UTC" can cause some trouble as several
frequently used functions have as default the local or system TZ and will
apply a conversion before printing or plotting time data, which in addition
is affected by summer/winter time transitions. This should be taken into
account as even for yearly data when conversion is to POSIXct a day (1st of
January) will be set, but then shifted some hours if printed on a TZ
different from "UTC". I recommend reading the documentation of package
lubridate-package
where the irregularities of time
data and the difficulties they cause are very well described. In many cases
when working with time series with yearly observations it is best to work
with numeric values for years.
This function can be used to easily convert time series data into a
format that can be easily plotted with package ggplot2
.
try_tibble
is another name for try_data_frame
which tracks
the separation and re-naming of data_frame
into
tibble::tibble
in the imported packages.
class(lynx) try_tibble(lynx) try_tibble(lynx, as.numeric = TRUE) try_tibble(lynx, "year") class(austres) try_tibble(austres) try_tibble(austres, as.numeric = TRUE) try_tibble(austres, "quarter") class(cars) try_tibble(cars)
class(lynx) try_tibble(lynx) try_tibble(lynx, as.numeric = TRUE) try_tibble(lynx, "year") class(austres) try_tibble(austres) try_tibble(austres, as.numeric = TRUE) try_tibble(austres, "quarter") class(cars) try_tibble(cars)
Additional theme constructors for use with geom_table
.
ttheme_gtdefault( base_size = 10, base_colour = "black", base_family = "", parse = FALSE, padding = unit(c(0.8, 0.6), "char"), ... ) ttheme_gtminimal( base_size = 10, base_colour = "black", base_family = "", parse = FALSE, padding = unit(c(0.5, 0.4), "char"), ... ) ttheme_gtbw( base_size = 10, base_colour = "black", base_family = "", parse = FALSE, padding = unit(c(1, 0.6), "char"), ... ) ttheme_gtplain( base_size = 10, base_colour = "black", base_family = "", parse = FALSE, padding = unit(c(0.8, 0.6), "char"), ... ) ttheme_gtdark( base_size = 10, base_colour = "grey90", base_family = "", parse = FALSE, padding = unit(c(0.8, 0.6), "char"), ... ) ttheme_gtlight( base_size = 10, base_colour = "grey10", base_family = "", parse = FALSE, padding = unit(c(0.8, 0.6), "char"), ... ) ttheme_gtsimple( base_size = 10, base_colour = "grey10", base_family = "", parse = FALSE, padding = unit(c(0.5, 0.4), "char"), ... ) ttheme_gtstripes( base_size = 10, base_colour = "grey10", base_family = "", parse = FALSE, padding = unit(c(0.8, 0.6), "char"), ... )
ttheme_gtdefault( base_size = 10, base_colour = "black", base_family = "", parse = FALSE, padding = unit(c(0.8, 0.6), "char"), ... ) ttheme_gtminimal( base_size = 10, base_colour = "black", base_family = "", parse = FALSE, padding = unit(c(0.5, 0.4), "char"), ... ) ttheme_gtbw( base_size = 10, base_colour = "black", base_family = "", parse = FALSE, padding = unit(c(1, 0.6), "char"), ... ) ttheme_gtplain( base_size = 10, base_colour = "black", base_family = "", parse = FALSE, padding = unit(c(0.8, 0.6), "char"), ... ) ttheme_gtdark( base_size = 10, base_colour = "grey90", base_family = "", parse = FALSE, padding = unit(c(0.8, 0.6), "char"), ... ) ttheme_gtlight( base_size = 10, base_colour = "grey10", base_family = "", parse = FALSE, padding = unit(c(0.8, 0.6), "char"), ... ) ttheme_gtsimple( base_size = 10, base_colour = "grey10", base_family = "", parse = FALSE, padding = unit(c(0.5, 0.4), "char"), ... ) ttheme_gtstripes( base_size = 10, base_colour = "grey10", base_family = "", parse = FALSE, padding = unit(c(0.8, 0.6), "char"), ... )
base_size |
numeric, default font size. |
base_colour |
default font colour. |
base_family |
default font family. |
parse |
logical, default behaviour for parsing text as plotmath. |
padding |
length-2 unit vector specifying the horizontal and vertical padding of text within each cell. |
... |
further arguments to control the gtable. |
Depending on the theme, the base_colour, which is
mapped to the colour
aesthetic if present, is applied to only the
text elements, or to the text elements and rules. The difference is
exemplified below.
A list
object that can be used as ttheme
in the
construction of tables with functions from package 'gridExtra'.
These theme constructors are wrappers on
gridExtra::ttheme_default()
and gridExtra::ttheme_minimal()
.
They can also be used with grid.table
if desired.
library(dplyr) library(tibble) mtcars %>% group_by(cyl) %>% summarize(wt = mean(wt), mpg = mean(mpg)) %>% ungroup() %>% mutate(wt = sprintf("%.2f", wt), mpg = sprintf("%.1f", mpg)) -> tb df <- tibble(x = 5.45, y = 34, tb = list(tb)) # Same as the default theme constructor ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtdefault) + theme_classic() # Minimal theme constructor ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtminimal) + theme_classic() # A theme with white background ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtbw) + theme_bw() # Default colour of theme superceded by aesthetic constant ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtbw, colour = "darkblue") + theme_bw() # A theme with dark background ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtdark) + theme_dark() # Default colour of theme superceded by aesthetic constant ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtdark, colour = "yellow") + theme_dark() # A theme with light background ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtlight) # Default colour of theme superceded by aesthetic constant ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtlight, colour = "darkred") # Default colour of theme superceded by aesthetic constant ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtsimple) # Default colour of theme superceded by aesthetic constant ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtstripes) + theme_dark()
library(dplyr) library(tibble) mtcars %>% group_by(cyl) %>% summarize(wt = mean(wt), mpg = mean(mpg)) %>% ungroup() %>% mutate(wt = sprintf("%.2f", wt), mpg = sprintf("%.1f", mpg)) -> tb df <- tibble(x = 5.45, y = 34, tb = list(tb)) # Same as the default theme constructor ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtdefault) + theme_classic() # Minimal theme constructor ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtminimal) + theme_classic() # A theme with white background ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtbw) + theme_bw() # Default colour of theme superceded by aesthetic constant ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtbw, colour = "darkblue") + theme_bw() # A theme with dark background ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtdark) + theme_dark() # Default colour of theme superceded by aesthetic constant ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtdark, colour = "yellow") + theme_dark() # A theme with light background ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtlight) # Default colour of theme superceded by aesthetic constant ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtlight, colour = "darkred") # Default colour of theme superceded by aesthetic constant ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtsimple) # Default colour of theme superceded by aesthetic constant ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb), table.theme = ttheme_gtstripes) + theme_dark()
Set R option to the theme to use as current default. This function is
implemented differently but is used in the same way as
ggplot2::theme_set()
but affects the default table-theme instead
of the plot theme.
ttheme_set(table.theme = NULL)
ttheme_set(table.theme = NULL)
table.theme |
NULL, list or function A gridExtra ttheme defintion, or a constructor for a ttheme or NULL for default. |
A named list with the previous value of the option.
The ttheme is set when a plot object is constructed, and consequently the option setting does not affect rendering of ready built plot objects.
library(dplyr) library(tibble) mtcars %>% group_by(cyl) %>% summarize(wt = mean(wt), mpg = mean(mpg)) %>% ungroup() %>% mutate(wt = sprintf("%.2f", wt), mpg = sprintf("%.1f", mpg)) -> tb df <- tibble(x = 5.45, y = 34, tb = list(tb)) # Same as the default theme constructor ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb)) # set a new default old_ttheme <- ttheme_set(ttheme_gtstripes) ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb)) # restore previous setting ttheme_set(old_ttheme)
library(dplyr) library(tibble) mtcars %>% group_by(cyl) %>% summarize(wt = mean(wt), mpg = mean(mpg)) %>% ungroup() %>% mutate(wt = sprintf("%.2f", wt), mpg = sprintf("%.1f", mpg)) -> tb df <- tibble(x = 5.45, y = 34, tb = list(tb)) # Same as the default theme constructor ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb)) # set a new default old_ttheme <- ttheme_set(ttheme_gtstripes) ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) + geom_point() + geom_table(data = df, aes(x = x, y = y, label = tb)) # restore previous setting ttheme_set(old_ttheme)
A dataset containing reshaped and simplified output from an analysis of data from RNAseq done with package edgeR. Original data from gene expression in the plant species Arabidopsis thaliana.
volcano_example.df
volcano_example.df
A data.frame
object with 1218 rows and 5 variables
Rai, Neha; O'Hara, Andrew; Farkas, Daniel; Safronov, Omid; Ratanasopa, Khuanpiroon; Wang, Fang; Lindfors, Anders V.; Jenkins, Gareth I.; Lehto, Tarja; Salojärvi, Jarkko; Brosché, Mikael; Strid. Åke; Aphalo, Pedro José; Morales, Luis Orlando (2020) The photoreceptor UVR8 mediates the perception of both UV-B and UV-A wavelengths up to 350 nm of sunlight with responsivity moderated by cryptochromes. Plant, Cell & Environment, 43:1513-1527.
Other Transcriptomics data:
quadrant_example.df
colnames(volcano_example.df) head(volcano_example.df)
colnames(volcano_example.df) head(volcano_example.df)
A data set containing weather data measured in Viikki, Helsinki, Finland. Values for all variables are means of 12 readings at 5 seconds intervals. Sun angles were computed with R package 'photobiology'.
weather_18_june_2019.df
weather_18_june_2019.df
A tibble with 18 columns and 1440 rows.
The variables are as follows:
time (yyyy-mm-dd hh:mm:ss)
PAR_umol (umol m-2 s-1)
PAR_diff_fr (/1)
global_watt (W m-2)
day_of_year
month_of_year
month_name
calendar_year
solar_time (h)
sun_elevation (degrees above horizon)
sun_azimuth (degrees)
was_sunny (T/F)
wind_speed (m s-1)
wind_direction (degrees)
air_temperature_C (C)
air_RH (
air_DP (C)
air_pressure
P. J. Aphalo, unpublished data.
names(weather_18_june_2019.df) head(weather_18_june_2019.df) nrow(weather_18_june_2019.df)
names(weather_18_june_2019.df) head(weather_18_june_2019.df) nrow(weather_18_june_2019.df)
Wrap the members of a character vector to a given maximum width by inserting new line characters at word boundaries.
wrap_labels(x, width = 20, indent = 0, new.line = "\n")
wrap_labels(x, width = 20, indent = 0, new.line = "\n")
x |
character vector, or an object which can be converted to a character
vector by |
width |
a positive integer giving the target column for wrapping lines in the output. |
indent |
a positive or negative integer giving the indentation of the first line in a member character string. |
new.line |
character sting; use |
Function wrap_labels()
is a wrapper on link{strwrap}
that returns a vector of character strings instead of a list of vectors. In
addition to wrapping, indentation is supported. Wrapping is always at white
space, so width = 0
wraps word by word.
Because the returned value is a character vector of the same length as the
input, this function can be used within a call to aes()
when mapping a
character vector to the label
aesthetic, as long as the character
strings will not be parsed into R expressions. It can be also used to wrap
the strings in a variable stored in a data frame.
A character vector of the same length as x
, with new line
characters inserted to wrap text lines longer than width
. Names in
x
are preserved in the returned value, no names are added if none
are present in x
.
my.text <- c(A = "This is the first string", B = "This is the second string, which is longer") wrap_labels(my.text, width = 20) wrap_labels(unname(my.text), width = 20) cat(wrap_labels(my.text, width = 20), sep = "\n--\n") cat(wrap_labels(my.text, width = 20, indent = 2), sep = "\n--\n") cat(wrap_labels(my.text, width = 20, indent = -2), sep = "\n--\n")
my.text <- c(A = "This is the first string", B = "This is the second string, which is longer") wrap_labels(my.text, width = 20) wrap_labels(unname(my.text), width = 20) cat(wrap_labels(my.text, width = 20), sep = "\n--\n") cat(wrap_labels(my.text, width = 20, indent = 2), sep = "\n--\n") cat(wrap_labels(my.text, width = 20, indent = -2), sep = "\n--\n")