| Title: | A Grammar of Graphics on the 'vellum' Backend |
|---|---|
| Description: | A declarative, pipe-first grammar of graphics that compiles an inspectable plot specification into a 'vellum' scene and renders it. A plot is built up as a serializable spec (data, layers, scales) and nothing is drawn until it is compiled: encodings are resolved, scales are trained, a panel layout is measured, and guides and marks are emitted as 'vellum' grobs. |
| Authors: | David Schoch [aut, cre] |
| Maintainer: | David Schoch <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.9.0.9000 |
| Built: | 2026-10-04 10:13:01 UTC |
| Source: | https://github.com/r-vellum/vellumplot |
add_marginal() draws a distribution of the panel's x variable along the
top edge and/or of its y variable along the right edge, each sharing the
main panel's axis so it lines up with the scatter (the vellumplot analogue of
ggExtra::ggMarginal()). It is a plot-level modifier, like facet_wrap() or
coord_flip(): it takes no encoding of its own and instead reads x, y
(and, with group = TRUE, color) from the first layer that maps a numeric
x and y (typically your mark_point()).
add_marginal( plot, type = c("density", "histogram"), sides = "tr", size = 0.15, adjust = 1, bins = 30, group = FALSE )add_marginal( plot, type = c("density", "histogram"), sides = "tr", size = 0.15, adjust = 1, bins = 30, group = FALSE )
plot |
|
type |
The marginal distribution: |
sides |
Which edges to draw, as a string of |
size |
The marginal size as a fraction of the panel, in |
adjust |
Bandwidth multiplier for |
bins |
Number of bins for |
group |
When |
The marginals are drawn without their own axes or background. This version
supports a single panel only: combining it with facet_wrap() /
facet_grid(), a non-Cartesian coordinate system (coord_flip(),
coord_polar(), coord_fixed(), coord_sf()), or a locked aspect ratio is
an error.
The modified PlotSpec.
mark_density(), mark_histogram(), facet_wrap()
vplot(faithful) |> mark_point(x = eruptions, y = waiting) |> add_marginal() vplot(faithful) |> mark_point(x = eruptions, y = waiting) |> add_marginal(type = "histogram", sides = "t")vplot(faithful) |> mark_point(x = eruptions, y = waiting) |> add_marginal() vplot(faithful) |> mark_point(x = eruptions, y = waiting) |> add_marginal(type = "histogram", sides = "t")
Attach a SelectionSpec (from the free-standing form of select_point() /
select_interval()) to a plot, marking that the selection's gesture is active
on this plot's marks. Use it when a selection is defined once and shared across
views in a composition (define + add_selection() on one plot, filter_by()
on another).
add_selection(plot, selection)add_selection(plot, selection)
plot |
A PlotSpec. |
selection |
A |
The PlotSpec, with the selection registered.
Used inside a mark_*() encoding to reference a variable produced by the
layer's statistical transform rather than a raw data column, e.g.
y = after_stat(count) or y = after_stat(density).
after_stat(x)after_stat(x)
x |
An expression in terms of the stat's computed variables. |
Its argument (the marker is interpreted at compile time).
anim_save() renders a vellum_animation (from animate()) to an animated
image, tweening the frames between keyframes and encoding them in one parallel,
streaming pass in vellum's Rust backend. The format follows the file extension:
anim_save(filename, animation)anim_save(filename, animation)
filename |
Output path; |
animation |
A |
.gif — a looping GIF (universal compatibility).
.png — an animated PNG (APNG; lossless, alpha).
.svg — a single animated SVG: every frame is emitted as vector markup
and shown in turn by a CSS step animation. It is resolution-independent (crisp
at any size, in print and on retina) and honours prefers-reduced-motion
(a reader who has asked their system not to animate gets the first frame, held).
filename, invisibly.
Pick by scene complexity, not preference. An animated SVG emits every frame in
full, so its size grows with the number of marks times the number of frames;
a raster format (GIF/APNG) does not. So SVG wins clearly on line art — a few
moving marks, the common explanatory case — and loses on a dense scatter, where
a raster format is the right answer. anim_save() says so when a .svg scene
is dense enough that a raster format would likely be smaller.
## Not run: a <- vplot(mtcars) |> mark_point(x = wt, y = mpg) |> transition_states(cyl) |> animate() anim_save("cyl.gif", a) anim_save("cyl.svg", a) # resolution-independent ## End(Not run)## Not run: a <- vplot(mtcars) |> mark_point(x = wt, y = mpg) |> transition_states(cyl) |> animate() anim_save("cyl.gif", a) anim_save("cyl.svg", a) # resolution-independent ## End(Not run)
animate() compiles a plot carrying a transition_states() into one keyframe
scene per state, training the scales once over all states and freezing them,
and returns a vellum_animation. Write it with anim_save(); printing it
shows the first keyframe as a preview.
animate(plot, nframes = 50, fps = 25)animate(plot, nframes = 50, fps = 25)
plot |
A PlotSpec with a |
nframes |
Total number of frames to render. |
fps |
Frames per second (the playback rate written into the file). |
Per-state statistics (e.g. a smooth) are recomputed per keyframe, but no scale domain retrains — the frozen scales are the observable proof the animation stayed non-reactive (axis breaks do not move between frames).
A vellum_animation.
transition_states(), ease_aes(), anim_save()
## Not run: vplot(mtcars) |> mark_point(x = wt, y = mpg) |> transition_states(cyl) |> animate(nframes = 50, fps = 25) ## End(Not run)## Not run: vplot(mtcars) |> mark_point(x = wt, y = mpg) |> transition_states(cyl) |> animate(nframes = 50, fps = 25) ## End(Not run)
Draw a single mark (or a short vector of them) from values supplied directly,
rather than mapping a data column. The values become a small inline layer
data frame, so annotations are independent of the plot data (and repeat on
every facet panel). Supported geoms: "text", "label", "point",
"segment", "rect", "grob", and "sparkline".
annotate( plot, geom, x = NULL, y = NULL, xend = NULL, yend = NULL, xmin = NULL, xmax = NULL, ymin = NULL, ymax = NULL, label = NULL, ... )annotate( plot, geom, x = NULL, y = NULL, xend = NULL, yend = NULL, xmin = NULL, xmax = NULL, ymin = NULL, ymax = NULL, label = NULL, ... )
plot |
A PlotSpec. |
geom |
The annotation geometry: one of |
x, y
|
Position (text/label/point/grob/sparkline; segment start). |
xend, yend
|
Segment end. |
xmin, xmax, ymin, ymax
|
Rectangle extent. |
label |
Text to draw (text/label). |
... |
Constant aesthetics passed to the mark (e.g. |
"grob" places an arbitrary vellum grob (or a PlotSpec, e.g. a
vsparkline()) at data coordinate(s), in a box of physical size — a general
"glyph / chart in a panel" seam. "sparkline" is the convenience for the
common case: pass values = and it builds and places a vsparkline().
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg) |> annotate("text", x = 4, y = 30, label = "note") |> annotate("rect", xmin = 3, xmax = 4, ymin = 15, ymax = 20, alpha = 0.2) ## Not run: vplot(mtcars) |> mark_point(x = wt, y = mpg) |> annotate("sparkline", x = 4, y = 30, values = cumsum(rnorm(30))) ## End(Not run)vplot(mtcars) |> mark_point(x = wt, y = mpg) |> annotate("text", x = 4, y = 30, label = "note") |> annotate("rect", xmin = 3, xmax = 4, ymin = 15, ymax = 20, alpha = 0.2) ## Not run: vplot(mtcars) |> mark_point(x = wt, y = mpg) |> annotate("sparkline", x = 4, y = 30, values = cumsum(rnorm(30))) ## End(Not run)
design =
An area() is a rectangular block of grid cells (1-based, inclusive) that a
sub-plot occupies. Pass a list of area()s (one per plot, in order) as
concat(..., design = ) to place plots on an explicit, possibly spanning,
grid.
area(t, l, b = t, r = l)area(t, l, b = t, r = l)
t, l, b, r
|
Top, left, bottom, right cell indices (1-based, inclusive). |
An area spec.
a <- vplot(mtcars) |> mark_point(x = wt, y = mpg) b <- vplot(mtcars) |> mark_point(x = hp, y = mpg) concat(a, b, design = list(area(1, 1, 1, 2), area(2, 1, 2, 1)))a <- vplot(mtcars) |> mark_point(x = wt, y = mpg) b <- vplot(mtcars) |> mark_point(x = hp, y = mpg) concat(a, b, design = list(area(1, 1, 1, 2), area(2, 1, 2, 1)))
as_spec() turns a PlotSpec into a plain, nested, serializable R list
(data, layers, encodings, scales, coordinates, facets, labels, page size);
from_spec() rebuilds a PlotSpec from that list. Together with
spec_to_json() / spec_from_json() this makes a vellumplot plot a portable
document — the substrate for the LLM / agent tooling (spec_fields(),
vplot_from_spec()) and the Vega-Lite bridge (spec_to_vegalite()).
as_spec(plot) from_spec(spec, data = NULL, env = globalenv())as_spec(plot) from_spec(spec, data = NULL, env = globalenv())
plot |
A PlotSpec. |
spec |
A spec list from |
data |
Optional data frame to render the spec against. Required when the
spec stores its data by reference; for a spec that inlines its data (or has
no data block), a supplied |
env |
The environment channel expressions are re-quoted in (default the global environment). |
The spec is a subset of the full grammar — the encoding-level state that a
portable document can carry faithfully. State that a JSON document cannot
represent (custom transform functions, paint/pattern fills, hand-drawn
sketch() geometry, secondary axes, sf CRS objects, per-layer data) is
refused with a classed vellumplot_unserializable error naming the exact
slot — it is never silently dropped. The single exception is theme element
customisation, which is styling orthogonal to the data spec: the theme
preset name and its scalar settings round-trip, but custom element_*()
overrides are dropped with a warning.
Channel expressions are stored as text (a column name, or an expression like
log(x)); the quosure's captured environment is dropped, so an encoding that
closes over a local variable will not round-trip.
Data is inlined when small (at most a few thousand cells and all-atomic
columns) and otherwise stored by reference (name + content hash + column
schema); a by-reference spec needs from_spec(spec, data = ) to recompile.
as_spec() returns a named list; from_spec() returns a PlotSpec.
spec_to_json(), spec_to_vegalite(), vplot_from_spec()
p <- vplot(mtcars) |> mark_point(x = wt, y = mpg, color = cyl) spec <- as_spec(p) spec$layers[[1]]$mark p2 <- from_spec(spec)p <- vplot(mtcars) |> mark_point(x = wt, y = mpg, color = cyl) spec <- as_spec(p) spec$layers[[1]]$mark p2 <- from_spec(spec)
Make the aes view of this plot's panel follow an interval
selection defined on another (overview) plot: dragging the
overview brush pans and zooms this (detail) panel to the selected range. This
is a display-tier view change (pan/zoom), not a scale retrain.
bind_scale(plot, selection, aes = c("x", "y"))bind_scale(plot, selection, aes = c("x", "y"))
plot |
A PlotSpec (the detail view). |
selection |
A |
aes |
The axis to bind, |
The PlotSpec, with the bind registered.
Restrict where a plot's marks show, by a shape rather than the panel
rectangle. clip_to() is a hard clip: only marks inside region are
drawn (or, with invert = TRUE, only those outside) – the way to fill a
raster / hexbin / tile heatmap into a country outline (a textured
choropleth). set_mask() is a soft mask: a radial luminance ramp that
fades the panel out towards its edges (a vignette / spotlight).
clip_to(plot, region, invert = FALSE) clip_layer(plot, region, invert = FALSE) set_mask(plot, region = NULL, type = c("luminance", "alpha"), feather = 0.35)clip_to(plot, region, invert = FALSE) clip_layer(plot, region, invert = FALSE) set_mask(plot, region = NULL, type = c("luminance", "alpha"), feather = 0.35)
plot |
A PlotSpec. |
region |
The clip geometry: an |
invert |
For |
type |
For |
feather |
For |
clip_to() / set_mask() mask the whole panel; clip_layer() masks only
the most-recently-added layer (the one just piped in), so one raster layer
can be clipped to a shape while the axes and other layers stay full-bleed.
All three attach to the plot and resolve at render into an isolated masked
layer (vellum::as_mask()), so the static output is unchanged when none is
set. Cartesian coordinates only (not polar or a nonlinear coord_trans()).
A smooth feathered edge on an arbitrary polygon needs a blur the renderer
does not provide yet, so clip_to() is hard-edged; use set_mask() for a
soft (radial) fade.
The modified PlotSpec.
## Not run: # clip a raster heatmap to a country outline vplot(grid) |> mark_raster(x = x, y = y, fill = z) |> clip_to(country_sf) # a vignette vplot(mtcars) |> mark_point(x = wt, y = mpg) |> set_mask(feather = 0.5) ## End(Not run)## Not run: # clip a raster heatmap to a country outline vplot(grid) |> mark_raster(x = x, y = y, fill = z) |> clip_to(country_sf) # a vignette vplot(mtcars) |> mark_point(x = wt, y = mpg) |> set_mask(feather = 0.5) ## End(Not run)
Add figure-level text (a title, subtitle, caption) spanning the whole
composition, and/or auto-tag the sub-plots (A, B, C, …). Because every
PlotComposition carries its own annotation, this works at any nesting level
(unlike patchwork, where annotation is top-level only).
compose_annotation( plot, title = NULL, subtitle = NULL, caption = NULL, tag_levels = NULL, tag_prefix = "", tag_suffix = "" )compose_annotation( plot, title = NULL, subtitle = NULL, caption = NULL, tag_levels = NULL, tag_prefix = "", tag_suffix = "" )
plot |
|
title, subtitle, caption
|
Figure-level text (or |
tag_levels |
Auto-tag style: |
tag_prefix, tag_suffix
|
Strings wrapped around each tag. |
The modified PlotComposition.
theme(), which also accepts a composition to set the figure-level
chrome (title bands, collected legend, panel spacing, tags).
a <- vplot(mtcars) |> mark_point(x = wt, y = mpg) b <- vplot(mtcars) |> mark_point(x = hp, y = mpg) hconcat(a, b) |> compose_annotation(title = "Fuel economy", tag_levels = "A")a <- vplot(mtcars) |> mark_point(x = wt, y = mpg) b <- vplot(mtcars) |> mark_point(x = hp, y = mpg) hconcat(a, b) |> compose_annotation(title = "Fuel economy", tag_levels = "A")
Compose several independent plots into one image. hconcat() lays them in a
row, vconcat() in a column, and concat() on a grid of ncol/nrow cells.
Each sub-plot keeps its own scales, axes, and legend (this is view
composition, not faceting).
concat( ..., ncol = NULL, nrow = NULL, byrow = TRUE, widths = NULL, heights = NULL, guides = c("collect", "keep"), design = NULL, width = NULL, height = NULL, dpi = NULL ) wrap_plots( plots, ncol = NULL, nrow = NULL, byrow = TRUE, widths = NULL, heights = NULL, guides = c("collect", "keep"), design = NULL, width = NULL, height = NULL, dpi = NULL ) hconcat(..., guides = c("collect", "keep"), height = NULL) vconcat(..., guides = c("collect", "keep"), width = NULL)concat( ..., ncol = NULL, nrow = NULL, byrow = TRUE, widths = NULL, heights = NULL, guides = c("collect", "keep"), design = NULL, width = NULL, height = NULL, dpi = NULL ) wrap_plots( plots, ncol = NULL, nrow = NULL, byrow = TRUE, widths = NULL, heights = NULL, guides = c("collect", "keep"), design = NULL, width = NULL, height = NULL, dpi = NULL ) hconcat(..., guides = c("collect", "keep"), height = NULL) vconcat(..., guides = c("collect", "keep"), width = NULL)
... |
PlotSpecs or |
ncol, nrow
|
Grid dimensions for |
byrow |
Fill the grid by row (default) or by column. |
widths, heights
|
Relative panel sizes per column / row (recycled numeric
vector), or |
guides |
|
design |
An explicit layout: a list of |
width, height
|
Output size in inches (defaults scale with the grid). |
dpi |
Output resolution in dots per inch. |
plots |
A list of PlotSpecs / |
Sub-plot panels are aligned across the grid (a shared track grid lines up
panel edges even when axis labels differ), and identical legends are
collected into one shared legend by default (guides = "collect"). Pass
PlotCompositions in ... to nest a sub-grid. Annotate the whole figure with
compose_annotation().
A PlotComposition (renders via render_plot() / vellum::render()).
a <- vplot(mtcars) |> mark_point(x = wt, y = mpg) b <- vplot(mtcars) |> mark_histogram(x = mpg, bins = 10) hconcat(a, b)a <- vplot(mtcars) |> mark_point(x = wt, y = mpg) b <- vplot(mtcars) |> mark_histogram(x = mpg, bins = 10) hconcat(a, b)
Use condition() as the value of a mark aesthetic to make that aesthetic
depend on whether an element is in a selection: members get
if_true, non-members get if_false. This is the general form of
highlight-on-interaction.
condition(selection, if_true, if_false, empty = TRUE)condition(selection, if_true, if_false, empty = TRUE)
selection |
The selection name (a string) that drives the condition. |
if_true |
The aesthetic value for selection members — a column expression (data-masked) or a constant. |
if_false |
The value for non-members — a constant, or omitted to use the theme's dim appearance. |
empty |
Whether an empty selection matches all elements ( |
condition() is recognised where it appears in a mark_*() encoding; calling
it directly is an error. The if_true branch is drawn on a static render and
trains scales exactly as the equivalent plain encoding, so
color = condition("s", g, "grey80") produces the same colour scale and legend
as color = g. With empty = TRUE (the default) an empty selection matches
everything, so a static / initial render shows if_true for all elements and
interaction dims non-members to if_false.
Used only inside a mark_*() encoding; not called directly.
coord_cartesian() is the default Cartesian system; pass xlim/ylim to
zoom the view (out-of-range marks are clipped, not dropped — unlike a
scale_*(limits=), which here behaves the same but is the data-scale's job).
coord_flip() swaps the x and y axes, e.g. for horizontal bars.
coord_fixed() / coord_equal() lock the aspect ratio so one data unit on
the y axis occupies ratio times the physical length of one unit on x (the
panel shrinks to fit and is centred). Coordinate limits take precedence over
scale limits.
coord_cartesian(plot, xlim = NULL, ylim = NULL) coord_flip(plot, xlim = NULL, ylim = NULL) coord_fixed(plot, ratio = 1, xlim = NULL, ylim = NULL) coord_equal(plot, ratio = 1, xlim = NULL, ylim = NULL)coord_cartesian(plot, xlim = NULL, ylim = NULL) coord_flip(plot, xlim = NULL, ylim = NULL) coord_fixed(plot, ratio = 1, xlim = NULL, ylim = NULL) coord_equal(plot, ratio = 1, xlim = NULL, ylim = NULL)
plot |
A PlotSpec. |
xlim, ylim
|
Length-2 view-window limits, or |
ratio |
Aspect ratio for |
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg) |> coord_cartesian(xlim = c(2, 4)) vplot(mtcars) |> mark_bar(x = factor(cyl)) |> coord_flip() vplot(mtcars) |> mark_point(x = wt, y = mpg) |> coord_fixed()vplot(mtcars) |> mark_point(x = wt, y = mpg) |> coord_cartesian(xlim = c(2, 4)) vplot(mtcars) |> mark_bar(x = factor(cyl)) |> coord_flip() vplot(mtcars) |> mark_point(x = wt, y = mpg) |> coord_fixed()
coord_polar() projects the panel into polar space: one position aesthetic
becomes the angle and the other the radius. With theta = "x" (the default)
the x aesthetic maps to angle and y to radius — a categorical bar chart
becomes a wind-rose / coxcomb, a line becomes a radar/spider trace, a point
cloud is positioned by (angle, radius). With theta = "y" a stacked bar
becomes a pie (see also the mark_pie() / mark_donut() shortcuts). The
panel is locked to a square. Lines, areas, and ribbons are interpolated into
smooth arcs.
coord_radial() is a fuller polar system (ggplot2 3.5's name): besides
theta/start/direction it takes end to sweep only a partial arc
(e.g. a half-circle gauge) and inner_radius to open a donut hole. With
end = NULL and inner_radius = 0 it is identical to coord_polar().
coord_polar(plot, theta = "x", start = 0, direction = 1) coord_radial( plot, theta = "x", start = 0, end = NULL, direction = 1, inner_radius = 0 )coord_polar(plot, theta = "x", start = 0, direction = 1) coord_radial( plot, theta = "x", start = 0, end = NULL, direction = 1, inner_radius = 0 )
plot |
A PlotSpec. |
theta |
Which position aesthetic drives the angle: |
start |
Angular offset of the zero position, in radians ( |
direction |
Winding direction: |
end |
Arc end angle in radians; |
inner_radius |
Radius of the central hole as a fraction of the outer
radius ( |
The modified PlotSpec.
vplot(mtcars) |> mark_bar(x = factor(cyl)) |> coord_polar(theta = "x") vplot(mtcars) |> mark_bar(x = factor(cyl)) |> coord_radial(theta = "x", inner_radius = 0.3)vplot(mtcars) |> mark_bar(x = factor(cyl)) |> coord_polar(theta = "x") vplot(mtcars) |> mark_bar(x = factor(cyl)) |> coord_radial(theta = "x", inner_radius = 0.3)
coord_sf() is the coordinate system for mark_sf() maps. Before scale
training it reprojects every sf layer to a common CRS (via
sf::st_transform()), so the renderer only ever sees projected Cartesian
coordinates, and it locks the panel aspect ratio so the map is not stretched:
1 for a projected CRS, and the equirectangular correction
1/cos(mean_latitude) for unprojected longitude/latitude data.
coord_sf( plot, crs = NULL, xlim = NULL, ylim = NULL, graticule = FALSE, graticule_labels = TRUE )coord_sf( plot, crs = NULL, xlim = NULL, ylim = NULL, graticule = FALSE, graticule_labels = TRUE )
plot |
A PlotSpec. |
crs |
Target coordinate reference system to project all layers into
(anything |
xlim, ylim
|
Length-2 view-window limits in the target CRS, or |
graticule |
Draw meridians and parallels behind the map. |
graticule_labels |
Label the graticule lines with their degree values
(default |
sf is an optional dependency (in Suggests); coord_sf() errors with an
install hint if it is not available at render time.
The modified PlotSpec.
mark_sf(), mark_scalebar(), mark_compass()
## Not run: nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) vplot(nc) |> mark_sf(fill = BIR74) |> coord_sf(crs = "OGC:CRS84") vplot(nc) |> mark_sf(fill = BIR74) |> coord_sf(crs = 3857, graticule = TRUE) ## End(Not run)## Not run: nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) vplot(nc) |> mark_sf(fill = BIR74) |> coord_sf(crs = "OGC:CRS84") vplot(nc) |> mark_sf(fill = BIR74) |> coord_sf(crs = 3857, graticule = TRUE) ## End(Not run)
coord_trans() applies a nonlinear transform to the display of one or both
position axes, after the scale has trained. This differs from a
scale_*(trans=): a scale transform rescales the data and picks its breaks in
the transformed space (so a log scale is labelled 1, 10, 100), whereas
coord_trans() keeps the trained breaks at their original data values and only
warps where they are drawn — so the axis is still labelled with the raw
values, the gridlines bunch up, and straight lines curve. Use it to show data
on, say, a log display without relabelling the axis in powers of ten.
coord_trans(plot, x = "identity", y = "identity")coord_trans(plot, x = "identity", y = "identity")
plot |
A PlotSpec. |
x, y
|
Display transform for that axis (default |
The transform is separable per axis. Each of x/y is a transform name
("identity", "log10", "sqrt") or a scales::transform_*() object. It is
intended for continuous position axes; "reverse" is better expressed as
scale_*(trans = "reverse").
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg) |> coord_trans(y = "log10")vplot(mtcars) |> mark_point(x = wt, y = mpg) |> coord_trans(y = "log10")
ease_aes() chooses the easing function that shapes how the interpolation
fraction moves through each transition — e.g. "cubic-in-out" starts and ends
gently. By default it applies to every interpolated aesthetic; the
position/color/size/alpha arguments override it for one class each, so
marks can glide into place on a cubic curve while their colour crossfades
evenly.
ease_aes( plot, ease = "linear", position = NULL, color = NULL, size = NULL, alpha = NULL, colour = NULL )ease_aes( plot, ease = "linear", position = NULL, color = NULL, size = NULL, alpha = NULL, colour = NULL )
plot |
A PlotSpec carrying a |
ease |
An easing name: |
position, color, size, alpha
|
Optional per-class easings, named the same way
as
|
colour |
An alias for |
The modified PlotSpec.
transition_states(), animate()
vplot(mtcars) |> mark_point(x = wt, y = mpg) |> transition_states(cyl) |> ease_aes("cubic-in-out") # Marks settle into place gently, but the colour crossfade stays even. vplot(mtcars) |> mark_point(x = wt, y = mpg, color = factor(gear)) |> transition_states(cyl) |> ease_aes("cubic-in-out", color = "linear")vplot(mtcars) |> mark_point(x = wt, y = mpg) |> transition_states(cyl) |> ease_aes("cubic-in-out") # Marks settle into place gently, but the colour crossfade stays even. vplot(mtcars) |> mark_point(x = wt, y = mpg, color = factor(gear)) |> transition_states(cyl) |> ease_aes("cubic-in-out", color = "linear")
Typed building blocks for theme(). Each describes how a family of theme
slots is drawn; any property left NULL is inherited from the slot's parent
in the theme tree. element_blank() draws nothing.
element_text( family = NULL, face = NULL, colour = NULL, color = NULL, size = NULL, cex = NULL, hjust = NULL, vjust = NULL, angle = NULL, lineheight = NULL, margin = NULL ) element_line( colour = NULL, color = NULL, linewidth = NULL, linetype = NULL, lineend = NULL, sketch = NULL ) element_rect( fill = NULL, colour = NULL, color = NULL, linewidth = NULL, linetype = NULL, sketch = NULL ) element_blank()element_text( family = NULL, face = NULL, colour = NULL, color = NULL, size = NULL, cex = NULL, hjust = NULL, vjust = NULL, angle = NULL, lineheight = NULL, margin = NULL ) element_line( colour = NULL, color = NULL, linewidth = NULL, linetype = NULL, lineend = NULL, sketch = NULL ) element_rect( fill = NULL, colour = NULL, color = NULL, linewidth = NULL, linetype = NULL, sketch = NULL ) element_blank()
family, face, size, cex, colour, color, hjust, vjust, angle, lineheight, margin
|
Text properties. |
linewidth, linetype, lineend
|
Line properties. |
sketch |
For |
fill |
Fill colour (rectangles). |
An element object for use in theme().
vplot(mtcars) |> mark_point(x = wt, y = mpg) |> theme(plot.title = element_text(size = 16), panel.grid.minor = element_blank())vplot(mtcars) |> mark_point(x = wt, y = mpg) |> theme(plot.title = element_text(size = 16), panel.grid.minor = element_blank())
facet_wrap() lays panels out in a ribbon wrapped into ncol/nrow;
facet_grid() arranges them on a 2-D grid defined by a rows ~ cols
formula. Position scales are shared across panels by default (so axes align);
pass scales = "free_x", "free_y", or "free" to train them per panel.
Colour and size scales (and their legends) are always shared in this version.
facet_wrap( plot, facets, ncol = NULL, nrow = NULL, scales = c("fixed", "free_x", "free_y", "free") ) facet_grid(plot, facets, scales = c("fixed", "free_x", "free_y", "free"))facet_wrap( plot, facets, ncol = NULL, nrow = NULL, scales = c("fixed", "free_x", "free_y", "free") ) facet_grid(plot, facets, scales = c("fixed", "free_x", "free_y", "free"))
plot |
A PlotSpec. |
facets |
A faceting formula. For |
ncol, nrow
|
Number of columns/rows for |
scales |
One of |
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg) |> facet_wrap(~cyl) vplot(mtcars) |> mark_point(x = wt, y = mpg) |> facet_grid(am ~ cyl)vplot(mtcars) |> mark_point(x = wt, y = mpg) |> facet_wrap(~cyl) vplot(mtcars) |> mark_point(x = wt, y = mpg) |> facet_grid(am ~ cyl)
Show only the rows in selection, hiding the rest (a display-tier hide, not a
re-aggregation). Point a second view's filter_by() at a selection whose
gesture lives in a first view and you get cross-filtering: brush one panel,
a linked panel redraws to just those rows.
filter_by(plot, selection)filter_by(plot, selection)
plot |
A PlotSpec. |
selection |
A |
The PlotSpec, with the filter registered.
select_interval(), add_selection()
A render effect for stroked, point, and text marks, in the spirit of
mplcyberpunk: a widened copy of the
mark is drawn beneath the crisp original and softened with a real Gaussian
blur (vellum's vl_viewport(blur=)), composited additively (a "screen"
blend) into a soft neon halo. Pass it to a mark's effects argument, e.g.
mark_line(..., effects = list(glow())). Pairs naturally with
theme_cyberpunk().
glow(size = 6, layers = 6L, alpha = 0.12, blend = "screen", color = NULL)glow(size = 6, layers = 6L, alpha = 0.12, blend = "screen", color = NULL)
size |
Halo spread in millimetres: the blur radius (and, for stroked/point marks, how much the copy is widened before blurring). |
layers, blend
|
Retained for compatibility and the neon look: |
alpha |
Base halo opacity (scaled by |
color |
Halo colour, or |
The glow is applied per style group, so a colour-mapped multi-series line
glows each series in its own hue. It applies to mark_point(), mark_line(),
mark_step(), mark_rule(), mark_segment(), mark_edges(), mark_nodes(),
mark_edge_bundle(), mark_flow_map(), and text marks (mark_text() /
mark_label()); other marks reject it.
A GlowSpec object for a mark's effects list.
outline(), shadow(), theme_cyberpunk()
df <- data.frame(x = 1:20, y = cumsum(rnorm(20))) vplot(df) |> mark_line(x = x, y = y, color = "#00e5ff", effects = list(glow())) |> theme_cyberpunk()df <- data.frame(x = 1:20, y = cumsum(rnorm(20))) vplot(df) |> mark_line(x = x, y = y, color = "#00e5ff", effects = list(glow())) |> theme_cyberpunk()
Thin re-exports of vellum::linear_gradient() and vellum::radial_gradient().
A gradient is an unscaled value for the fill aesthetic: pass it directly,
e.g. mark_area(x = t, y = y, fill = linear_gradient(c("#00e5ff", "#00e5ff00"))),
and the filled region (area / ribbon / bar) is painted with the paint as a
single grob. Use "transparent" (or an "#RRGGBB00" colour) as a stop to fade
out — the "glow fade under a line" look. The gradient's x1/y1/x2/y2
(in units, "npc" by default) set its direction. A gradient cannot be
mapped to a data column (it is one paint per region).
linear_gradient(colours, stops = NULL, ...) radial_gradient(colours, stops = NULL, ...)linear_gradient(colours, stops = NULL, ...) radial_gradient(colours, stops = NULL, ...)
colours, stops
|
|
... |
Further gradient arguments passed to the vellum constructor:
|
A vellum_gradient object usable as a fill value.
df <- data.frame(x = 1:20, y = cumsum(abs(rnorm(20)))) vplot(df) |> mark_area(x = x, y = y, fill = linear_gradient(c("#00e5ff", "#00e5ff00"), x1 = 0, y1 = 1, x2 = 0, y2 = 0))df <- data.frame(x = 1:20, y = cumsum(abs(rnorm(20)))) vplot(df) |> mark_area(x = x, y = y, fill = linear_gradient(c("#00e5ff", "#00e5ff00"), x1 = 0, y1 = 1, x2 = 0, y2 = 0))
gt tablegt_vsparkline() renders a list-column of numeric vectors as a per-row
vsparkline(), embedded as inline SVG in a gt::gt() table — so a gt table
(with all of gt's formatting and theming) gains a vellum sparkline column.
Needs the gt package, and HTML output (inline SVG is not embedded by gt's
LaTeX / Word backends).
gt_vsparkline( gt_object, column, type = "line", ..., width = 30, height = 8, units = "mm" )gt_vsparkline( gt_object, column, type = "line", ..., width = 30, height = 8, units = "mm" )
gt_object |
A |
column |
The list-column to render (bare name or string). |
type |
Sparkline type: |
... |
Further |
width, height, units
|
Sparkline size (default |
The vectors are recovered from the gt object's data in its current row order;
apply gt_vsparkline() before any gt row reordering / grouping.
The modified gt object.
vsparkline(), vtable(), plot_svg()
## Not run: df <- data.frame(metric = c("A", "B")) df$trend <- list(cumsum(rnorm(20)), cumsum(rnorm(20))) gt::gt(df) |> gt_vsparkline(trend, type = "line") ## End(Not run)## Not run: df <- data.frame(metric = c("A", "B")) df$trend <- list(cumsum(rnorm(20)), cumsum(rnorm(20))) gt::gt(df) |> gt_vsparkline(trend, type = "line") ## End(Not run)
guides() overrides the legend (guide) for one or more aesthetics without
respelling the whole scale_*(). Pass "none" (or guide_none()) to hide a
legend, guide_legend() to tweak a keyed legend (reverse the key order,
override the title, restyle the keys with override.aes), guide_colourbar()
to size, tick and style a continuous colour bar, or guide_coloursteps() to draw a
binned colour scale as a segmented bar instead of swatches. Applies to the
non-position legends (color/fill, size, shape, alpha, linetype);
position axes are unaffected.
guides(plot, ...) guide_none() guide_legend( title = NULL, reverse = FALSE, override.aes = NULL, nested = FALSE ) guide_colourbar( title = NULL, barwidth = NULL, barheight = NULL, ticks = TRUE, ticks.colour = "white", label.position = NULL, n.breaks = NULL, reverse = FALSE ) guide_colorbar( title = NULL, barwidth = NULL, barheight = NULL, ticks = TRUE, ticks.colour = "white", label.position = NULL, n.breaks = NULL, reverse = FALSE ) guide_coloursteps( title = NULL, barwidth = NULL, barheight = NULL, ticks = FALSE, ticks.colour = "white", label.position = NULL, reverse = FALSE ) guide_colorsteps( title = NULL, barwidth = NULL, barheight = NULL, ticks = FALSE, ticks.colour = "white", label.position = NULL, reverse = FALSE )guides(plot, ...) guide_none() guide_legend( title = NULL, reverse = FALSE, override.aes = NULL, nested = FALSE ) guide_colourbar( title = NULL, barwidth = NULL, barheight = NULL, ticks = TRUE, ticks.colour = "white", label.position = NULL, n.breaks = NULL, reverse = FALSE ) guide_colorbar( title = NULL, barwidth = NULL, barheight = NULL, ticks = TRUE, ticks.colour = "white", label.position = NULL, n.breaks = NULL, reverse = FALSE ) guide_coloursteps( title = NULL, barwidth = NULL, barheight = NULL, ticks = FALSE, ticks.colour = "white", label.position = NULL, reverse = FALSE ) guide_colorsteps( title = NULL, barwidth = NULL, barheight = NULL, ticks = FALSE, ticks.colour = "white", label.position = NULL, reverse = FALSE )
plot |
A PlotSpec. |
... |
Named by aesthetic, e.g. |
title |
An axis/legend title override, or |
reverse |
Reverse the order of the legend keys / the colour bar. |
override.aes |
A named list of aesthetics to force on the legend keys,
independent of the plotted data — the classic "make faint, small points
legible in the key" fix. Recognised names: |
nested |
For a size legend, draw the keys as concentric,
bottom-aligned circles (a proportional-symbol / "bubble" legend) with a
leader from each circle to its label, instead of stacked rows. Best with a
wide size range (e.g. |
barwidth, barheight
|
The colour bar's own width and height, in millimetres
( |
ticks |
Draw the break ticks on the colour bar? (Default |
ticks.colour |
Colour of the break ticks (default |
label.position |
Which side of a vertical colour bar the labels sit,
|
n.breaks |
Roughly how many ticks (and labels) to put on a continuous
colour bar — a target, not a promise: the break algorithm prefers round
numbers over the bar's range and returns whatever count reads best near the
one asked for, so There is deliberately no |
guides(): the modified PlotSpec. guide_none() / guide_legend():
a guide specification for use inside guides().
vplot(mtcars) |> mark_point(x = wt, y = mpg, color = factor(cyl)) |> guides(color = "none") vplot(mtcars) |> mark_point(x = wt, y = mpg, color = factor(cyl)) |> guides(color = guide_legend(reverse = TRUE)) # legible keys over faint, tiny points vplot(mtcars) |> mark_point(x = wt, y = mpg, color = factor(cyl), alpha = 0.15, size = 0.6) |> guides(color = guide_legend(override.aes = list(size = 5, alpha = 1))) # a taller, wider colour bar with left-side labels and no ticks vplot(mtcars) |> mark_point(x = wt, y = mpg, color = hp) |> guides(color = guide_colourbar( barwidth = 8, barheight = 60, ticks = FALSE, label.position = "left" )) # about four ticks on the bar instead of the automatic count vplot(mtcars) |> mark_point(x = wt, y = mpg, color = hp) |> guides(color = guide_colourbar(n.breaks = 4)) # a binned colour scale as a segmented bar vplot(mtcars) |> mark_point(x = wt, y = mpg, color = hp) |> scale_color_binned() |> guides(color = guide_coloursteps()) # a proportional-symbol (nested-circle) size legend vplot(mtcars) |> mark_point(x = wt, y = mpg, size = hp) |> scale_size(range = c(2, 12)) |> guides(size = guide_legend(nested = TRUE))vplot(mtcars) |> mark_point(x = wt, y = mpg, color = factor(cyl)) |> guides(color = "none") vplot(mtcars) |> mark_point(x = wt, y = mpg, color = factor(cyl)) |> guides(color = guide_legend(reverse = TRUE)) # legible keys over faint, tiny points vplot(mtcars) |> mark_point(x = wt, y = mpg, color = factor(cyl), alpha = 0.15, size = 0.6) |> guides(color = guide_legend(override.aes = list(size = 5, alpha = 1))) # a taller, wider colour bar with left-side labels and no ticks vplot(mtcars) |> mark_point(x = wt, y = mpg, color = hp) |> guides(color = guide_colourbar( barwidth = 8, barheight = 60, ticks = FALSE, label.position = "left" )) # about four ticks on the bar instead of the automatic count vplot(mtcars) |> mark_point(x = wt, y = mpg, color = hp) |> guides(color = guide_colourbar(n.breaks = 4)) # a binned colour scale as a segmented bar vplot(mtcars) |> mark_point(x = wt, y = mpg, color = hp) |> scale_color_binned() |> guides(color = guide_coloursteps()) # a proportional-symbol (nested-circle) size legend vplot(mtcars) |> mark_point(x = wt, y = mpg, size = hp) |> scale_size(range = c(2, 12)) |> guides(size = guide_legend(nested = TRUE))
Place plot as an inset over base, positioned by fractional coordinates
(0–1) of the chosen reference box. Returns a 1-cell PlotComposition carrying
the inset (compose it further or render directly).
inset( base, plot, left = 0.6, bottom = 0.6, right = 0.98, top = 0.98, align_to = c("panel", "plot", "full"), on_top = TRUE )inset( base, plot, left = 0.6, bottom = 0.6, right = 0.98, top = 0.98, align_to = c("panel", "plot", "full"), on_top = TRUE )
base |
A PlotSpec or |
plot |
The PlotSpec to overlay. |
left, bottom, right, top
|
Inset position as fractions (0–1). |
align_to |
Reference box: |
on_top |
Draw the inset above ( |
A PlotComposition.
a <- vplot(mtcars) |> mark_point(x = wt, y = mpg) b <- vplot(mtcars) |> mark_histogram(x = mpg, bins = 8) inset(a, b, left = 0.55, bottom = 0.55, right = 0.98, top = 0.98)a <- vplot(mtcars) |> mark_point(x = wt, y = mpg) b <- vplot(mtcars) |> mark_histogram(x = mpg, bins = 8) inset(a, b, left = 0.55, bottom = 0.55, right = 0.98, top = 0.98)
Declare that a host should surface the source data rows behind an element
when the user clicks (or hovers) it — the "click-to-source" affordance. It is
inert on a static render; a host (vellumwidget::as_widget()) reads the
compiled scene's provenance (provenance_join() / provenance_payload()) to
answer the gesture, and under Shiny reports the clicked element's rows to
input$<id>_source.
inspect_source(plot, on = c("click", "hover"), values = FALSE)inspect_source(plot, on = c("click", "hover"), values = FALSE)
plot |
A PlotSpec. |
on |
The gesture that reveals the source, |
values |
If |
This is opt-in because the row mapping adds to the widget payload; declaring it on the plot (rather than as a host flag) keeps interactivity a property of the spec.
The PlotSpec, with source inspection registered.
provenance_payload(), select_point()
vplot(mtcars) |> mark_point(x = wt, y = mpg) |> inspect_source()vplot(mtcars) |> mark_point(x = wt, y = mpg) |> inspect_source()
Returns the serialisable declaration block a host needs to enact a plot's
declarative interactivity (selections, conditional encodings, filters, and
scale-domain binds), or NULL when the plot declares none. This is the
plot-level companion to the per-element metadata carried on the compiled scene;
vellumwidget::as_widget() reads it to wire gestures to reactions.
interaction_model(x)interaction_model(x)
x |
A PlotSpec or a plot composition. |
A named list (selections, conditions, filters, binds, and
source when inspect_source() is declared), or NULL if there is no
declared interactivity.
Add plot-level text — a title, subtitle, caption, and tag — and
override the titles of individual axes and legends (x, y, color, size).
The title, subtitle, and tag are drawn in a band above the panels; the caption
in a band below. Repeated labs() calls merge, with later values winning.
labs( plot, title = NULL, subtitle = NULL, caption = NULL, tag = NULL, x = NULL, y = NULL, color = NULL, colour = NULL, fill = NULL, size = NULL, alt = NULL, ... )labs( plot, title = NULL, subtitle = NULL, caption = NULL, tag = NULL, x = NULL, y = NULL, color = NULL, colour = NULL, fill = NULL, size = NULL, alt = NULL, ... )
plot |
A PlotSpec. |
title, subtitle, caption, tag
|
Plot-level text (or |
x, y, size
|
Axis / legend title overrides for those aesthetics. |
color, colour, fill
|
Colour-scale title override; |
alt |
A text alternative (alt text) describing the plot for screen
readers and other assistive technology. Overrides the description vellumplot
generates automatically; see |
... |
Reserved; passing anything here is an error. |
Axis/legend overrides set here are used unless a matching scale_*(name = )
is also given, which takes precedence. With neither, the title is derived from
the mapping.
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg) |> labs(title = "Fuel economy", x = "Weight", y = "MPG")vplot(mtcars) |> mark_point(x = wt, y = mpg) |> labs(title = "Fuel economy", x = "Weight", y = "MPG")
Convenience wrappers that declare a scale carrying only its limits, instead of
spelling out a full scale_*(). xlim() / ylim() set the position range;
lims() sets limits for any named aesthetic. They are shortcuts for
scale_*(limits = ...): like there, an explicit range sets the trained
(view) window and marks outside it are clipped.
lims(plot, ...) xlim(plot, ...) ylim(plot, ...)lims(plot, ...) xlim(plot, ...) ylim(plot, ...)
plot |
A PlotSpec. |
... |
For |
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg) |> xlim(0, 6) vplot(mtcars) |> mark_point(x = wt, y = mpg) |> lims(x = c(0, 6), y = c(10, 35))vplot(mtcars) |> mark_point(x = wt, y = mpg) |> xlim(0, 6) vplot(mtcars) |> mark_point(x = wt, y = mpg) |> lims(x = c(0, 6), y = c(10, 35))
Cartographic furniture for coord_sf() maps. mark_scalebar() draws a
segmented distance bar; mark_compass() draws a north arrow. Both are
fixed-position decorations pinned to a panel corner (they take no data
aesthetics). Graticule lines (meridians and parallels) are added through
coord_sf()'s graticule argument, not a mark, so they render behind the
map.
mark_scalebar( plot, distance = NULL, unit = "km", position = "bottomleft", segments = 4L, height = 2.5, pad = 4, text_size = 7, color = "black", fill = "white", data = NULL ) mark_compass( plot, position = "topright", size = 10, pad = 4, rotation = 0, color = "black", fill = "black", text = TRUE, data = NULL )mark_scalebar( plot, distance = NULL, unit = "km", position = "bottomleft", segments = 4L, height = 2.5, pad = 4, text_size = 7, color = "black", fill = "white", data = NULL ) mark_compass( plot, position = "topright", size = 10, pad = 4, rotation = 0, color = "black", fill = "black", text = TRUE, data = NULL )
plot |
A PlotSpec. |
distance |
Bar length in |
unit |
Distance unit for the label and |
position |
Panel corner to anchor the decoration:
|
segments |
Number of alternating segments in the bar (default |
height |
Bar thickness, in millimetres. |
pad |
Inset from the panel edge, in millimetres. |
text_size |
Label font size (points). |
color, fill
|
Stroke and fill colours. For the scale bar the segments
alternate |
data |
Optional layer data (rarely needed – decorations are not data-driven). |
size |
Glyph height, in millimetres. |
rotation |
Extra clockwise rotation of the arrow, in degrees (e.g. to point at grid north on a rotated layout). |
text |
Draw the |
The modified PlotSpec.
## Not run: nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) vplot(nc) |> mark_sf(fill = BIR74) |> coord_sf(crs = 3857, graticule = TRUE) |> mark_scalebar() |> mark_compass() ## End(Not run)## Not run: nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) vplot(nc) |> mark_sf(fill = BIR74) |> coord_sf(crs = 3857, graticule = TRUE) |> mark_scalebar() |> mark_compass() ## End(Not run)
mark_abline() draws a sloped reference line y = slope * x + intercept
across the panel (the diagonal cousin of mark_rule()'s horizontal/vertical
lines). mark_function() draws a curve y = fun(x) sampled over the panel's
x range — e.g. a theoretical density over a histogram, or a reference curve
over a scatter. Both take no data encodings; they reuse the panel's existing
x/y scales, so add them on top of a data layer. Both assume linear axes.
mark_abline( plot, ..., slope = 1, intercept = 0, blend = NULL, sketch = NULL, data = NULL ) mark_function( plot, ..., fun, n = 101, args = list(), blend = NULL, sketch = NULL, data = NULL )mark_abline( plot, ..., slope = 1, intercept = 0, blend = NULL, sketch = NULL, data = NULL ) mark_function( plot, ..., fun, n = 101, args = list(), blend = NULL, sketch = NULL, data = NULL )
plot |
A PlotSpec. |
... |
For |
slope, intercept
|
For |
blend, sketch, data
|
See |
fun |
For |
n |
For |
args |
For |
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg) |> mark_abline(slope = -5, intercept = 37) vplot(data.frame(x = rnorm(200))) |> mark_histogram(x = x, y = after_stat(density)) |> mark_function(fun = dnorm)vplot(mtcars) |> mark_point(x = wt, y = mpg) |> mark_abline(slope = -5, intercept = 37) vplot(data.frame(x = rnorm(200))) |> mark_histogram(x = x, y = after_stat(density)) |> mark_function(fun = dnorm)
mark_area() fills the region between a y line and the zero baseline;
mark_ribbon() fills between ymin and ymax; mark_step() draws a
staircase line. All connect points in x order.
mark_area( plot, ..., position = "stack", blend = NULL, sketch = NULL, data = NULL ) mark_ribbon(plot, ..., blend = NULL, sketch = NULL, data = NULL) mark_step( plot, ..., direction = "hv", auto = FALSE, blend = NULL, effects = list(), sketch = NULL, data = NULL )mark_area( plot, ..., position = "stack", blend = NULL, sketch = NULL, data = NULL ) mark_ribbon(plot, ..., blend = NULL, sketch = NULL, data = NULL) mark_step( plot, ..., direction = "hv", auto = FALSE, blend = NULL, effects = list(), sketch = NULL, data = NULL )
plot |
|
... |
Encodings (tidy-eval): |
position |
For |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
sketch |
A |
data |
Optional layer data frame; overrides the plot data for this layer. |
direction |
For |
auto |
For |
effects |
A list of layer render effects applied to the mark at draw
time — |
The modified PlotSpec.
vplot(pressure) |> mark_area(x = temperature, y = pressure)vplot(pressure) |> mark_area(x = temperature, y = pressure)
mark_boxplot() draws a box-and-whisker per x category from the raw y
values (box = Q1-Q3, median line, 1.5*IQR whiskers, outlier points).
mark_errorbar() draws vertical bars from ymin to ymax with horizontal
caps; mark_linerange() omits the caps. mark_summary() aggregates y per
x with fun (default mean) and draws the result as points.
mark_boxplot(plot, ..., blend = NULL, sketch = NULL, data = NULL) mark_errorbar(plot, ..., width = 0.5, blend = NULL, sketch = NULL, data = NULL) mark_linerange(plot, ..., blend = NULL, sketch = NULL, data = NULL) mark_summary(plot, ..., fun = mean, blend = NULL, sketch = NULL, data = NULL) mark_pointrange(plot, ..., blend = NULL, sketch = NULL, data = NULL) mark_crossbar(plot, ..., width = 0.5, blend = NULL, sketch = NULL, data = NULL)mark_boxplot(plot, ..., blend = NULL, sketch = NULL, data = NULL) mark_errorbar(plot, ..., width = 0.5, blend = NULL, sketch = NULL, data = NULL) mark_linerange(plot, ..., blend = NULL, sketch = NULL, data = NULL) mark_summary(plot, ..., fun = mean, blend = NULL, sketch = NULL, data = NULL) mark_pointrange(plot, ..., blend = NULL, sketch = NULL, data = NULL) mark_crossbar(plot, ..., width = 0.5, blend = NULL, sketch = NULL, data = NULL)
plot |
|
... |
Encodings (tidy-eval): |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
sketch |
A |
data |
Optional layer data frame; overrides the plot data for this layer. |
width |
For |
fun |
For |
mark_pointrange() draws a point at (x, y) with a vertical line from ymin
to ymax (an identity mark — supply the summary values yourself, e.g. from a
model). mark_crossbar() draws a box spanning ymin..ymax with a
horizontal line at y. Both are the identity counterparts of the aggregating
mark_interval().
The modified PlotSpec.
vplot(mtcars) |> mark_boxplot(x = factor(cyl), y = mpg)vplot(mtcars) |> mark_boxplot(x = factor(cyl), y = mpg)
mark_contour() draws iso-density contour lines of a 2-D point cloud
(x, y); mark_contour_filled() fills the bands between them. By default the
field is a kernel density estimate (needs the MASS package); map a z
aesthetic to instead contour a supplied surface over a regular x/y grid.
Contours are coloured by level automatically — mark_contour() maps
color = after_stat(level), mark_contour_filled() maps fill. Contour
tracing is done by the engine (vellum::vl_contour()), so no extra package is
needed for the lines; a density field additionally needs MASS.
mark_contour( plot, ..., bins = 10, binwidth = NULL, breaks = NULL, n = 100, blend = NULL, sketch = NULL, data = NULL ) mark_contour_filled( plot, ..., bins = 10, binwidth = NULL, breaks = NULL, n = 100, blend = NULL, sketch = NULL, data = NULL )mark_contour( plot, ..., bins = 10, binwidth = NULL, breaks = NULL, n = 100, blend = NULL, sketch = NULL, data = NULL ) mark_contour_filled( plot, ..., bins = 10, binwidth = NULL, breaks = NULL, n = 100, blend = NULL, sketch = NULL, data = NULL )
plot |
|
... |
Encodings (tidy-eval): |
bins |
Target number of contour levels (when neither |
binwidth |
Spacing between contour levels, or |
breaks |
Explicit contour levels, or |
n |
Density-estimate grid resolution per axis (KDE mode only). |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
sketch |
A |
data |
Optional layer data frame; overrides the plot data for this layer. |
The modified PlotSpec.
vplot(faithful) |> mark_point(x = eruptions, y = waiting) |> mark_contour(x = eruptions, y = waiting) vplot(faithful) |> mark_contour_filled(x = eruptions, y = waiting)vplot(faithful) |> mark_point(x = eruptions, y = waiting) |> mark_contour(x = eruptions, y = waiting) vplot(faithful) |> mark_contour_filled(x = eruptions, y = waiting)
mark_count() collapses coincident (x, y) observations to one point sized
by how many fall there (ggplot2's geom_count() / stat_sum()) — the honest
way to show overplotting on a discrete or rounded grid. size defaults to
after_stat(n) (the overlap count); map it to after_stat(prop) for the
proportion instead.
mark_count(plot, ..., blend = NULL, sketch = NULL, data = NULL)mark_count(plot, ..., blend = NULL, sketch = NULL, data = NULL)
plot |
|
... |
Encodings (tidy-eval): |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
sketch |
A |
data |
Optional layer data frame; overrides the plot data for this layer. |
The modified PlotSpec.
vplot(mpg <- data.frame(cyl = mtcars$cyl, gear = mtcars$gear)) |> mark_count(x = cyl, y = gear)vplot(mpg <- data.frame(cyl = mtcars$cyl, gear = mtcars$gear)) |> mark_count(x = cyl, y = gear)
For data too dense to draw one marker each (overplotted, up to millions of
points), mark_datashade() bins the points into a canvas-sized grid in one
pass and colours each cell by density (via vellum::datashade()), drawing a
single raster that fills the panel. Cost is decoupled from point count and
overplotting.
mark_datashade( plot, ..., width = 400, height = 300, colors = NULL, how = "eq_hist", span = NULL, clip = NULL, spread = NULL, blend = NULL, data = NULL )mark_datashade( plot, ..., width = 400, height = 300, colors = NULL, how = "eq_hist", span = NULL, clip = NULL, spread = NULL, blend = NULL, data = NULL )
plot |
|
... |
Encodings; |
width, height
|
Aggregation grid size in cells (output raster pixels). |
colors |
Two or more colours forming the low-to-high density ramp (plain
density shading only; ignored when a |
how |
Density-to-colour mapping (and, categorically, per-cell opacity):
|
span, clip
|
Optional density-range clamping passed to |
spread |
Optional post-aggregation spreading to keep sparse output
visible (passed to |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
data |
Optional layer data frame; overrides the plot data for this layer. |
Map a discrete color (or fill) aesthetic to shade categorically
(datashader's count_cat): each category is aggregated separately and every
cell is coloured by the count-weighted average of the category hues it holds,
with opacity from its total density — so you see which category dominates
where, and where they mix, with a colour legend. The category hues come from
the usual discrete colour scale (so scale_color_manual() etc. apply). Without
a mapped colour, cell colour encodes plain density via the colors ramp.
The modified PlotSpec.
n <- 1e5 d <- data.frame(x = rnorm(n), y = rnorm(n), g = sample(c("a", "b"), n, TRUE)) vplot(d) |> mark_datashade(x = x, y = y) # categorical: colour by group vplot(d) |> mark_datashade(x = x, y = y, color = g)n <- 1e5 d <- data.frame(x = rnorm(n), y = rnorm(n), g = sample(c("a", "b"), n, TRUE)) vplot(d) |> mark_datashade(x = x, y = y) # categorical: colour by group vplot(d) |> mark_datashade(x = x, y = y, color = g)
Marks that summarise the distribution of a variable.
mark_ecdf() draws the empirical cumulative distribution of x as a step;
mark_rug() draws marginal ticks at each datum; mark_qq() draws a
quantile-quantile plot of a sample against a theoretical distribution, with
mark_qq_line() adding the reference line. All respect a mapped color/fill
grouping.
mark_ecdf(plot, ..., blend = NULL, sketch = NULL, data = NULL) mark_rug(plot, ..., sides = "bl", length = 0.03, blend = NULL, data = NULL) mark_qq( plot, ..., distribution = "qnorm", blend = NULL, sketch = NULL, data = NULL ) mark_qq_line( plot, ..., distribution = "qnorm", blend = NULL, sketch = NULL, data = NULL )mark_ecdf(plot, ..., blend = NULL, sketch = NULL, data = NULL) mark_rug(plot, ..., sides = "bl", length = 0.03, blend = NULL, data = NULL) mark_qq( plot, ..., distribution = "qnorm", blend = NULL, sketch = NULL, data = NULL ) mark_qq_line( plot, ..., distribution = "qnorm", blend = NULL, sketch = NULL, data = NULL )
plot |
A PlotSpec. |
... |
Encodings. |
blend, sketch, data
|
Standard layer arguments (see |
sides |
Which edges |
length |
Rug tick length as a fraction of the panel (default |
distribution |
Quantile function of the reference distribution for
|
The modified PlotSpec.
vplot(mtcars) |> mark_ecdf(x = mpg) vplot(mtcars) |> mark_point(x = wt, y = mpg) |> mark_rug() vplot(mtcars) |> mark_qq(sample = mpg) |> mark_qq_line(sample = mpg)vplot(mtcars) |> mark_ecdf(x = mpg) vplot(mtcars) |> mark_point(x = wt, y = mpg) |> mark_rug() vplot(mtcars) |> mark_qq(sample = mpg) |> mark_qq_line(sample = mpg)
Marks that summarise a set of (x, y) points (per group, when a color or
fill is mapped) as a single enclosing region drawn over the raw points.
mark_ellipse( plot, ..., type = "t", level = 0.95, segments = 51L, blend = NULL, sketch = NULL, data = NULL ) mark_hull(plot, ..., expand = 0, blend = NULL, sketch = NULL, data = NULL)mark_ellipse( plot, ..., type = "t", level = 0.95, segments = 51L, blend = NULL, sketch = NULL, data = NULL ) mark_hull(plot, ..., expand = 0, blend = NULL, sketch = NULL, data = NULL)
plot |
|
... |
Encodings (tidy-eval): |
type |
Ellipse type: |
level |
Confidence level ( |
segments |
Number of line segments approximating the ellipse. |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
sketch |
A |
data |
Optional layer data frame; overrides the plot data for this layer. |
expand |
For |
mark_ellipse() draws a covariance ellipse: a t distribution
(type = "t", the default, robustly estimated via MASS), a
multivariate normal ("norm"), or a Euclidean circle of radius level
("euclid"). The algorithm follows ggplot2's stat_ellipse().
mark_hull() draws the convex hull of the points.
Both are unfilled by default (a boundary), matching ggplot2; map or set a
fill to shade the region. A region needs at least 3 points per group;
smaller groups are skipped with a warning.
The modified PlotSpec.
vplot(iris) |> mark_point(x = Sepal.Length, y = Sepal.Width, color = Species) |> mark_ellipse(x = Sepal.Length, y = Sepal.Width, color = Species) vplot(iris) |> mark_point(x = Sepal.Length, y = Sepal.Width, color = Species) |> mark_hull(x = Sepal.Length, y = Sepal.Width, color = Species)vplot(iris) |> mark_point(x = Sepal.Length, y = Sepal.Width, color = Species) |> mark_ellipse(x = Sepal.Length, y = Sepal.Width, color = Species) vplot(iris) |> mark_point(x = Sepal.Length, y = Sepal.Width, color = Species) |> mark_hull(x = Sepal.Length, y = Sepal.Width, color = Species)
Draw a node-link diagram on a PlotSpec from vgraph(). mark_edges() draws
the edges (straight lines, batched), mark_nodes() the vertices (points),
mark_node_text() the vertex labels, and mark_edge_text() labels on the
edges. Draw order is fixed regardless of the order you pipe them: edges under
edge labels under nodes under node labels. Edges (and edge labels) default to
the edge table (vgraph()'s edge_data), nodes and node labels to the node
table; the x/y/xend/yend/label/name columns those tables carry are
mapped automatically, so bare mark_edges() |> mark_nodes() just works.
mark_edges( plot, ..., color = NULL, linewidth = NULL, alpha = NULL, linetype = NULL, arrow = FALSE, routing = c("straight", "elbow"), elbow_at = c("mid", "start", "end"), elbow_axis = c("auto", "v", "h"), gradient = FALSE, auto = FALSE, blend = NULL, effects = list(), sketch = NULL, data = NULL ) mark_edge_bundle( plot, ..., type = c("force", "divided", "stub", "path", "hammer", "mingle"), color = NULL, linewidth = NULL, alpha = NULL, linetype = NULL, params = list(), blend = NULL, effects = list(), sketch = NULL, data = NULL ) mark_flow_map( plot, ..., root, type = c("spiral", "steiner"), weight = NULL, width_range = c(0.3, 3), color = NULL, alpha = NULL, params = list(), blend = NULL, effects = list(), sketch = NULL, data = NULL ) mark_nodes( plot, ..., size = NULL, shape = NULL, fill = NULL, color = NULL, alpha = NULL, blend = NULL, effects = list(), sketch = NULL, data = NULL ) mark_node_text( plot, ..., label = NULL, color = NULL, size = NULL, alpha = NULL, dist = 0, top_n = NULL, by = NULL, repel = FALSE, box_padding = 1, point_padding = 1, min_segment_length = 2, seed = NULL, effects = list(), blend = NULL, data = NULL ) mark_edge_text( plot, ..., label = NULL, color = NULL, size = NULL, alpha = NULL, angle = NULL, effects = list(), blend = NULL, data = NULL ) mark_node_hull( plot, ..., fill = NULL, color = NULL, alpha = 0.25, expand = 0.08, data = NULL ) mark_node_pie( plot, cols, ..., size = 4, inner = 0, fill = NULL, color = "white", linewidth = 0.5, alpha = NA, data = NULL )mark_edges( plot, ..., color = NULL, linewidth = NULL, alpha = NULL, linetype = NULL, arrow = FALSE, routing = c("straight", "elbow"), elbow_at = c("mid", "start", "end"), elbow_axis = c("auto", "v", "h"), gradient = FALSE, auto = FALSE, blend = NULL, effects = list(), sketch = NULL, data = NULL ) mark_edge_bundle( plot, ..., type = c("force", "divided", "stub", "path", "hammer", "mingle"), color = NULL, linewidth = NULL, alpha = NULL, linetype = NULL, params = list(), blend = NULL, effects = list(), sketch = NULL, data = NULL ) mark_flow_map( plot, ..., root, type = c("spiral", "steiner"), weight = NULL, width_range = c(0.3, 3), color = NULL, alpha = NULL, params = list(), blend = NULL, effects = list(), sketch = NULL, data = NULL ) mark_nodes( plot, ..., size = NULL, shape = NULL, fill = NULL, color = NULL, alpha = NULL, blend = NULL, effects = list(), sketch = NULL, data = NULL ) mark_node_text( plot, ..., label = NULL, color = NULL, size = NULL, alpha = NULL, dist = 0, top_n = NULL, by = NULL, repel = FALSE, box_padding = 1, point_padding = 1, min_segment_length = 2, seed = NULL, effects = list(), blend = NULL, data = NULL ) mark_edge_text( plot, ..., label = NULL, color = NULL, size = NULL, alpha = NULL, angle = NULL, effects = list(), blend = NULL, data = NULL ) mark_node_hull( plot, ..., fill = NULL, color = NULL, alpha = 0.25, expand = 0.08, data = NULL ) mark_node_pie( plot, cols, ..., size = 4, inner = 0, fill = NULL, color = "white", linewidth = 0.5, alpha = NA, data = NULL )
plot |
|
... |
Encodings mapping node/edge attributes to aesthetics. Nodes: |
linewidth |
For |
linetype |
For |
arrow |
For |
routing |
For |
elbow_at, elbow_axis
|
For |
gradient |
For |
auto |
For |
blend |
Optional blend mode (see |
effects |
A list of layer render effects ( |
sketch |
A |
data |
Optional layer data; overrides the default table. |
type |
For |
params |
For |
root |
For |
weight |
For |
width_range |
For |
size, shape
|
For |
fill, color, alpha
|
Convenience aesthetics; a constant or a mapped
expression. For nodes, |
label |
For |
dist |
For |
top_n, by
|
For |
repel |
For |
box_padding, point_padding, min_segment_length, seed
|
Repel
tuning for |
angle |
For |
expand |
For |
cols |
For |
inner |
For |
Edge colour, opacity, and line type train on their own scales
(scale_edge_color(), scale_edge_alpha(), scale_edge_linetype(), plus
scale_edge_width()), independent of the node colour/alpha/linetype scales –
so a plot can map node fill to a discrete community and edge colour to a
continuous weight without the two legends colliding.
mark_node_text() has the label-legibility tools a dense graph needs:
repel = TRUE nudges overlapping labels apart with leader lines, dist pushes
labels radially clear of the node markers, top_n/by label only the hubs,
and effects = list(shadow()) drops a shadow behind each label so it stays
readable over edges. mark_edge_text() takes the same effects. (Only
shadow() applies to text; a glyph outline / glow is not available yet.)
Two more decorations: mark_node_hull() shades communities with a convex hull
behind the graph (grouped by a mapped fill, drawn under the edges), and
mark_node_pie() replaces node markers with pie / donut glyphs whose wedges
come from a set of compositional columns.
mark_edge_bundle() is a drop-in alternative to mark_edges() that routes the
edges as bundled curves instead of straight lines, so a hairball collapses
into a few legible trunks. It delegates the geometry to the edgebundle
package (install it) and draws the returned paths with the edge aesthetics –
type picks the algorithm ("force", "divided", "stub", "path",
"hammer", "mingle") and params passes tuning through. Bundled edges are
faint by default (alpha = 0.3) so overlapping trunks read as density.
mark_flow_map() draws a flow map: a single root fans out to many
destinations along smooth, merging branches whose width tracks the flow volume
(the Minard / migration-map idiom). It expects a one-to-many (star) graph
rooted at root, laid out at fixed coordinates; edge weight drives the flow.
type = "spiral" (default, an angle-restricted spiral tree) needs only
edgebundle; type = "steiner" (an approximate Steiner tree) additionally
needs interp. Branch width is mapped from the computed flow into
width_range, and each branch is drawn as one tapering ribbon: where
tributaries merge and the flow changes along a branch, the width varies
continuously rather than stepping. (That only arises for type = "steiner",
whose flow is per-vertex; a spiral tree's flow is constant along each branch.)
A sketch = flow map falls back to one uniform stroke per branch, since a
hand-drawn ribbon would jitter its outline rather than the pen.
These are thin over the point / segment / text marks; igraph need not be
installed to use them (only vgraph() needs it). mark_edge_bundle() and
mark_flow_map() also need the edgebundle package.
The modified PlotSpec.
vgraph(), scale_edge_width(), scale_edge_color()
## Not run: g <- igraph::make_graph("Zachary") vgraph(g) |> mark_edges(alpha = 0.5) |> mark_nodes(size = 4, fill = "steelblue") ## End(Not run)## Not run: g <- igraph::make_graph("Zachary") vgraph(g) |> mark_edges(alpha = 0.5) |> mark_nodes(size = 4, fill = "steelblue") ## End(Not run)
Marks for visualising a distribution's shape and its summary intervals
together, in the style of the ggdist package — a natural fit for
posterior draws or bootstrap samples (one row per draw, grouped by a
categorical x).
mark_halfeye( plot, ..., .width = c(0.66, 0.95), point = "median", adjust = 1, scale = 0.9, blend = NULL, sketch = NULL, data = NULL ) mark_interval( plot, ..., .width = c(0.66, 0.95), point = "median", blend = NULL, data = NULL )mark_halfeye( plot, ..., .width = c(0.66, 0.95), point = "median", adjust = 1, scale = 0.9, blend = NULL, sketch = NULL, data = NULL ) mark_interval( plot, ..., .width = c(0.66, 0.95), point = "median", blend = NULL, data = NULL )
plot |
|
... |
Encodings (tidy-eval): a categorical |
.width |
Interval probabilities, widest last (default
|
point |
Central summary: |
adjust |
|
scale |
Slab width as a fraction of the category band ( |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
sketch |
A |
data |
Optional layer data frame; overrides the plot data for this layer. |
mark_halfeye() draws, per x category, a one-sided density "slab" (a half
violin) with a point-interval at its base: the median (or mean) as a
point, a thick bar for the inner interval and a thin bar for the outer one.
mark_interval() draws the point-interval alone (no slab).
Intervals are equal-tailed quantile intervals at the .width probabilities
(widest drawn thinnest). Supply many draws per x (e.g. posterior samples).
The modified PlotSpec.
set.seed(1) draws <- data.frame( grp = rep(c("a", "b", "c"), each = 400), val = rnorm(1200, rep(c(0, 1, 2), each = 400)) ) vplot(draws) |> mark_halfeye(x = grp, y = val) vplot(draws) |> mark_interval(x = grp, y = val)set.seed(1) draws <- data.frame( grp = rep(c("a", "b", "c"), each = 400), val = rnorm(1200, rep(c(0, 1, 2), each = 400)) ) vplot(draws) |> mark_halfeye(x = grp, y = val) vplot(draws) |> mark_interval(x = grp, y = val)
Marks that apply a statistical transform before drawing. mark_histogram()
bins a continuous x and draws the per-bin counts as bars. mark_smooth()
fits a model of y on x (per group) and draws the fitted line, with a
confidence ribbon when se = TRUE.
mark_histogram( plot, ..., bins = 30, position = "stack", blend = NULL, sketch = NULL, data = NULL ) mark_smooth( plot, ..., method = "auto", formula = NULL, span = 0.75, se = TRUE, level = 0.95, method.args = list(), blend = NULL, sketch = NULL, data = NULL )mark_histogram( plot, ..., bins = 30, position = "stack", blend = NULL, sketch = NULL, data = NULL ) mark_smooth( plot, ..., method = "auto", formula = NULL, span = 0.75, se = TRUE, level = 0.95, method.args = list(), blend = NULL, sketch = NULL, data = NULL )
plot |
|
... |
Encodings (tidy-eval), e.g. |
bins |
Number of histogram bins. |
position |
Position adjustment for the histogram bars ( |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
sketch |
A |
data |
Optional layer data frame; overrides the plot data for this layer. |
method |
Smoothing method: one of |
formula |
Model formula in terms of |
span |
|
se |
Draw a confidence ribbon around the smooth? Ignored for |
level |
Confidence level for the ribbon. |
method.args |
Extra arguments to the fitting function, e.g.
|
mark_smooth() supports several methods:
"auto" (default) picks "loess" for small groups (< 1000 points) and
"gam" for large ones.
"lm" / "glm" — linear and generalised linear fits (glm takes a
family via method.args, e.g. binomial() for logistic).
"loess" — local regression, controlled by span.
"gam" — a generalised additive model with a smooth term (default
y ~ s(x)); needs the mgcv package.
"rq" — quantile regression at a single method.args$tau (default the
median); needs the quantreg package and draws the fitted line only
(no confidence ribbon). For several quantiles, add one layer per tau.
The modified PlotSpec.
vplot(mtcars) |> mark_histogram(x = mpg, bins = 10) vplot(mtcars) |> mark_point(x = wt, y = mpg) |> mark_smooth(x = wt, y = mpg) # local regression with a wider neighbourhood vplot(mtcars) |> mark_point(x = wt, y = mpg) |> mark_smooth(x = wt, y = mpg, method = "loess", span = 0.9)vplot(mtcars) |> mark_histogram(x = mpg, bins = 10) vplot(mtcars) |> mark_point(x = wt, y = mpg) |> mark_smooth(x = wt, y = mpg) # local regression with a wider neighbourhood vplot(mtcars) |> mark_point(x = wt, y = mpg) |> mark_smooth(x = wt, y = mpg, method = "loess", span = 0.9)
mark_image() draws a bitmap image (e.g. a flag or logo) at each (x, y),
replacing the usual point marker. src is a column of local image file paths
(per datum) or a single constant path (the same image at every point). Images
are sized by size (height in millimetres); each image's native aspect ratio
is preserved.
mark_image( plot, ..., src = NULL, size = 5, nudge_x = 0, nudge_y = 0, interpolate = TRUE, blend = NULL, data = NULL )mark_image( plot, ..., src = NULL, size = 5, nudge_x = 0, nudge_y = 0, interpolate = TRUE, blend = NULL, data = NULL )
plot |
|
... |
Encodings (tidy-eval): |
src |
Image source: a column of file paths (mapped, one per datum) or a single constant path (the same image at every point). |
size |
Image height in millimetres (constant or mapped); the width
follows the image's own aspect ratio. Default |
nudge_x, nudge_y
|
Shift each image by an exact absolute distance in
millimetres ( |
interpolate |
Smoothly interpolate when scaling (default |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
data |
Optional layer data frame; overrides the plot data for this layer. |
Reading image files requires the suggested
magick package (which decodes PNG, JPEG,
SVG, GIF and more); mark_image() errors with an install hint if it is not
available.
The modified PlotSpec.
## Not run: d <- data.frame(x = 1:3, y = c(2, 1, 3), flag = c("de.png", "fr.png", "it.png")) vplot(d) |> mark_image(x = x, y = y, src = flag, size = 8) ## End(Not run)## Not run: d <- data.frame(x = 1:3, y = c(2, 1, 3), flag = c("de.png", "fr.png", "it.png")) vplot(d) |> mark_image(x = x, y = y, src = flag, size = 8) ## End(Not run)
mark_outlier_label() labels only the outlying points — the extremes,
where the story usually is — instead of every datum. It keeps the rows whose
y is an outlier (per colour/fill group) and labels just those, repelled
apart with the same solver as mark_text(). Layer it over the raw points.
mark_outlier_label( plot, ..., method = c("iqr", "sd"), k = 1.5, size = NULL, repel = TRUE, box_padding = 1, min_segment_length = 2, blend = NULL, data = NULL )mark_outlier_label( plot, ..., method = c("iqr", "sd"), k = 1.5, size = NULL, repel = TRUE, box_padding = 1, min_segment_length = 2, blend = NULL, data = NULL )
plot |
|
... |
Encodings (tidy-eval): |
method |
Outlier rule: |
k |
Threshold multiplier — IQR whisker length (default |
size |
Font size in points. |
repel |
Move overlapping labels apart (force-directed, ggrepel-style), with leader lines to the points? Single cartesian panel only. |
box_padding |
Extra space (mm) kept around each label box during repulsion. |
min_segment_length |
Shortest leader line (mm) worth drawing; a label that barely moved gets none. |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
data |
Optional layer data frame; overrides the plot data for this layer. |
The default method = "iqr" flags y outside [Q1 - k*IQR, Q3 + k*IQR] (the
boxplot whisker rule); method = "sd" flags |y - mean| > k * sd. Map a
label to name each outlier; with none mapped, the outlier's y value is the
label.
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg) |> mark_outlier_label(x = wt, y = mpg, label = rownames(mtcars))vplot(mtcars) |> mark_point(x = wt, y = mpg) |> mark_outlier_label(x = wt, y = mpg, label = rownames(mtcars))
Convenience marks for part-of-whole charts. mark_pie() draws a pie: each
value becomes a wedge whose angle is its share of the total, coloured by
fill. mark_donut() is a pie with a hollow centre (inner_radius, a
fraction of the radius). Both are shorthand for a stacked bar projected through
coord_polar() with theta = "y", which they set on the plot; they error if
the plot already carries a non-polar coordinate.
mark_pie( plot, value, fill = NULL, ..., blend = NULL, sketch = NULL, data = NULL ) mark_donut( plot, value, fill = NULL, inner_radius = 0.5, ..., blend = NULL, sketch = NULL, data = NULL )mark_pie( plot, value, fill = NULL, ..., blend = NULL, sketch = NULL, data = NULL ) mark_donut( plot, value, fill = NULL, inner_radius = 0.5, ..., blend = NULL, sketch = NULL, data = NULL )
plot |
A PlotSpec. |
value |
Encoding (tidy-eval) for each slice's magnitude. |
fill |
Encoding (tidy-eval) for the slice colour. Omit for a single slice. |
... |
Further constant aesthetics (e.g. |
blend |
Optional blend mode for compositing the layer (see |
sketch |
A |
data |
Optional per-layer data frame. |
inner_radius |
For |
The modified PlotSpec.
df <- data.frame(part = c("a", "b", "c"), n = c(3, 5, 2)) vplot(df) |> mark_pie(value = n, fill = part) vplot(df) |> mark_donut(value = n, fill = part, inner_radius = 0.6)df <- data.frame(part = c("a", "b", "c"), n = c(3, 5, 2)) vplot(df) |> mark_pie(value = n, fill = part) vplot(df) |> mark_donut(value = n, fill = part, inner_radius = 0.6)
Each mark_*() appends a drawing layer to a PlotSpec. Encodings are bare
column names (or expressions) captured with tidy evaluation, e.g.
x = wt, y = mpg, color = hp. Scalar values (e.g. size = 3,
color = "red") are treated as constant aesthetics rather than data
mappings.
mark_point( plot, ..., size = NULL, shape = NULL, position = "identity", auto = FALSE, seed = NULL, blend = NULL, effects = list(), sketch = NULL, data = NULL ) mark_line( plot, ..., window = NULL, auto = FALSE, blend = NULL, effects = list(), sketch = NULL, data = NULL ) mark_rule( plot, ..., blend = NULL, effects = list(), sketch = NULL, data = NULL ) mark_bar( plot, ..., position = "stack", blend = NULL, sketch = NULL, data = NULL )mark_point( plot, ..., size = NULL, shape = NULL, position = "identity", auto = FALSE, seed = NULL, blend = NULL, effects = list(), sketch = NULL, data = NULL ) mark_line( plot, ..., window = NULL, auto = FALSE, blend = NULL, effects = list(), sketch = NULL, data = NULL ) mark_rule( plot, ..., blend = NULL, effects = list(), sketch = NULL, data = NULL ) mark_bar( plot, ..., position = "stack", blend = NULL, sketch = NULL, data = NULL )
plot |
|
... |
Encodings: named channel expressions such as |
size, shape
|
Convenience arguments for the point size (in mm) / shape;
may be a constant or a mapped expression. A shape is a built-in marker
( |
position |
Position adjustment: a string — |
auto |
For |
seed |
For |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
effects |
A list of layer render effects applied to the mark at draw
time — |
sketch |
A |
data |
Optional layer data frame; overrides the plot data for this layer. |
window |
For |
mark_bar() draws bars from a zero baseline. With an explicit y it uses the
y values as heights; with no y it counts rows per category (the "count"
stat). When color/fill is mapped, grouped bars are stacked by default; use
position = "dodge" for side-by-side bars or "fill" to normalise to 1.
The modified PlotSpec.
Any mark accepts reserved, per-row arguments (captured like encodings, via tidy evaluation) that make its elements addressable — and stylable — by an interactive host without changing what a static render draws:
data_id — a per-element data key (e.g. data_id = model). Emitted by
the SVG backend as data-key on each element and returned by
vellum::scene_model(); it is the join key a host uses to map a hover/click
back to a datum, and to link the same datum across views.
tooltip — per-element tooltip text (a column expression or a constant),
surfaced in scene_model() metadata.
hover_group — a field grouping elements for linked emphasis (consumed by a
host in a later phase).
hover_color, selected_color — per-element outline colours applied by the
host when the element is hovered / selected (a constant, or mapped from a
column so different marks highlight differently). They override the widget-wide
theme set by vellumwidget::as_widget(hover_color=, selected_color=).
These are inert for PNG/PDF and for an SVG opened without a JS host: a plot
with none of them compiles and renders exactly as before. Declaring any of them
without data_id defaults the key to the row index, so the element is still
addressable. They currently apply to stat = "identity" marks (points, bars,
tiles, segments, edges, hexbins, sf features, …); aggregating stats
(histogram/count/density) drop them, since rows no longer map 1:1 to elements.
How these flow into the vellum scene (the scene_model() element table, the
SVG data-key / data-vellum-* attributes, and the reserved meta key
vocabulary) is described in vellum's "The scene contract" vignette
(vignette("scene-contract", package = "vellum")).
vplot(mtcars) |> mark_point(x = wt, y = mpg, color = hp) # Declare interactivity (inert on a static render): df <- data.frame(wt = mtcars$wt, mpg = mtcars$mpg, model = rownames(mtcars)) vplot(df) |> mark_point(x = wt, y = mpg, tooltip = model, data_id = model)vplot(mtcars) |> mark_point(x = wt, y = mpg, color = hp) # Declare interactivity (inert on a static render): df <- data.frame(wt = mtcars$wt, mpg = mtcars$mpg, model = rownames(mtcars)) vplot(df) |> mark_point(x = wt, y = mpg, tooltip = model, data_id = model)
mark_raincloud() is a convenience that composes a raincloud: a one-sided
density "cloud" (mark_halfeye()) with the raw observations as "rain" below
it (mark_point() with sina spread). It is exactly
plot |> mark_halfeye(...) |> mark_point(..., position = position_sina()),
so any color/fill mapping in ... flows to both layers.
mark_raincloud(plot, x, y, ..., width = 0.4, alpha = 0.5)mark_raincloud(plot, x, y, ..., width = 0.4, alpha = 0.5)
plot |
A PlotSpec. |
x, y
|
The categorical |
... |
Further shared encodings (e.g. |
width |
Sina spread of the rain, as a fraction of the band (default
|
alpha |
Point opacity for the rain (default |
The modified PlotSpec.
mark_halfeye(), position_sina()
set.seed(1) d <- data.frame(g = rep(c("a", "b", "c"), each = 100), y = rnorm(300, rep(c(0, 1, 2), each = 100))) vplot(d) |> mark_raincloud(x = g, y = y)set.seed(1) d <- data.frame(g = rep(c("a", "b", "c"), each = 100), y = rnorm(300, rep(c(0, 1, 2), each = 100))) vplot(d) |> mark_raincloud(x = g, y = y)
mark_segment() draws a straight line from (x, y) to (xend, yend) per row.
mark_segment( plot, ..., auto = FALSE, blend = NULL, effects = list(), sketch = NULL, data = NULL )mark_segment( plot, ..., auto = FALSE, blend = NULL, effects = list(), sketch = NULL, data = NULL )
plot |
|
... |
Encodings (tidy-eval): |
auto |
For |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
effects |
A list of layer render effects applied to the mark at draw
time — |
sketch |
A |
data |
Optional layer data frame; overrides the plot data for this layer. |
The modified PlotSpec.
d <- data.frame(x = 1, y = 1, xend = 5, yend = 4) vplot(d) |> mark_segment(x = x, y = y, xend = xend, yend = yend)d <- data.frame(x = 1, y = 1, xend = 5, yend = 4) vplot(d) |> mark_segment(x = x, y = y, xend = xend, yend = yend)
mark_series_label() labels each colour/fill series at its end (the point
with the largest x) with the series name — a legend-free alternative that
reads faster on a multi-line chart. Labels are pushed apart with the same
repel solver as mark_text(). Map the same x/y/color as the lines; the
label text and colour come from the series automatically.
mark_series_label( plot, ..., size = NULL, nudge_x = 2, repel = TRUE, box_padding = 1, min_segment_length = 2, blend = NULL, data = NULL )mark_series_label( plot, ..., size = NULL, nudge_x = 2, repel = TRUE, box_padding = 1, min_segment_length = 2, blend = NULL, data = NULL )
plot |
|
... |
Encodings (tidy-eval): the same |
size |
Font size in points. |
nudge_x |
Rightward offset (mm) so a label clears its line end (default
|
repel |
Move overlapping labels apart (force-directed, ggrepel-style), with leader lines to the points? Single cartesian panel only. |
box_padding |
Extra space (mm) kept around each label box during repulsion. |
min_segment_length |
Shortest leader line (mm) worth drawing; a label that barely moved gets none. |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
data |
Optional layer data frame; overrides the plot data for this layer. |
The modified PlotSpec.
d <- data.frame( t = rep(1:10, 3), v = c(1:10, (1:10) * 1.5, 10:1), s = rep(c("a", "b", "c"), each = 10) ) # Give the panel a little x-room and drop the now-redundant colour legend. vplot(d) |> mark_line(x = t, y = v, color = s) |> mark_series_label(x = t, y = v, color = s) |> xlim(1, 12) |> guides(color = "none")d <- data.frame( t = rep(1:10, 3), v = c(1:10, (1:10) * 1.5, 10:1), s = rep(c("a", "b", "c"), each = 10) ) # Give the panel a little x-room and drop the now-redundant colour legend. vplot(d) |> mark_line(x = t, y = v, color = s) |> mark_series_label(x = t, y = v, color = s) |> xlim(1, 12) |> guides(color = "none")
mark_sf() draws the geometry column of an sf object as a map layer:
POINT/MULTIPOINT render as points, LINESTRING/MULTILINESTRING as
polylines, and POLYGON/MULTIPOLYGON as filled paths (holes cut with the
even-odd rule, so ring winding need not be canonical). Coordinates come from
the geometry, so there are no x/y encodings; other aesthetics map feature
attributes as usual, e.g. fill = AREA for a choropleth. Pair with
coord_sf() to reproject and lock the map aspect ratio.
mark_sf( plot, ..., fill = NULL, color = NULL, alpha = NULL, linewidth = NULL, size = NULL, na_value = "grey80", merge = FALSE, blend = NULL, sketch = NULL, data = NULL )mark_sf( plot, ..., fill = NULL, color = NULL, alpha = NULL, linewidth = NULL, size = NULL, na_value = "grey80", merge = FALSE, blend = NULL, sketch = NULL, data = NULL )
plot |
|
... |
Encodings mapping feature attributes to aesthetics: |
fill, color, alpha, linewidth, size
|
Convenience aesthetic arguments; a constant or a mapped expression. |
na_value |
Fill colour for features whose mapped |
merge |
Dissolve adjacent features that share a fill into one region, so
the internal borders between same-valued features disappear and each region
is a single crisp path (no seam artefacts, and exact in PDF). The union is
real boolean geometry via |
blend |
Optional blend mode (see |
sketch |
A |
data |
Optional layer data (an |
sf is an optional dependency (in Suggests); mark_sf() errors with an
install hint if it is not available.
The modified PlotSpec.
coord_sf(), scale_fill_binned()
## Not run: nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) vplot(nc) |> mark_sf(fill = BIR74) |> coord_sf() ## End(Not run)## Not run: nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) vplot(nc) |> mark_sf(fill = BIR74) |> coord_sf() ## End(Not run)
mark_sf_label() draws one text label per sf feature, placed at the
feature's interior point (sf::st_point_on_surface(), guaranteed to fall
inside each polygon — unlike a centroid, which can land in a bay or a hole).
The label points are reprojected through the same coord_sf CRS as
mark_sf(), so they always land where the geometry is drawn. Layer it over a
mark_sf() choropleth to name the regions; repel = TRUE (the default) pushes
crowded labels apart.
mark_sf_label( plot, ..., size = NULL, repel = TRUE, box_padding = 1, min_segment_length = 2, blend = NULL, data = NULL )mark_sf_label( plot, ..., size = NULL, repel = TRUE, box_padding = 1, min_segment_length = 2, blend = NULL, data = NULL )
plot |
|
... |
Encodings (tidy-eval): the |
size |
Font size in points. |
repel |
Move overlapping labels apart (force-directed, ggrepel-style), with leader lines to the points? Single cartesian panel only. |
box_padding |
Extra space (mm) kept around each label box during repulsion. |
min_segment_length |
Shortest leader line (mm) worth drawing; a label that barely moved gets none. |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
data |
An |
The modified PlotSpec.
if (requireNamespace("sf", quietly = TRUE)) { nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) vplot(nc) |> mark_sf(fill = AREA) |> mark_sf_label(label = NAME, size = 5) }if (requireNamespace("sf", quietly = TRUE)) { nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) vplot(nc) |> mark_sf(fill = AREA) |> mark_sf_label(label = NAME, size = 5) }
mark_signif() runs a pairwise test between x groups and draws a
significance bracket over each comparison with its p-value (or stars) —
the ggsignif / ggpubr idiom. Add it on top of a mark_boxplot() /
mark_violin(); the brackets stack above the data and the y-axis expands to
fit them.
mark_signif( plot, ..., comparisons = NULL, method = c("wilcox.test", "t.test"), label = c("p", "stars"), step = 0.12, tip_length = 0.03, blend = NULL, sketch = NULL, data = NULL )mark_signif( plot, ..., comparisons = NULL, method = c("wilcox.test", "t.test"), label = c("p", "stars"), step = 0.12, tip_length = 0.03, blend = NULL, sketch = NULL, data = NULL )
plot |
|
... |
Encodings (tidy-eval): a categorical |
comparisons |
A list of length-2 character vectors naming the group
pairs to test, e.g. |
method |
The two-sample test: |
label |
|
step |
Vertical gap between stacked brackets, as a fraction of the data's
y range (default |
tip_length |
Bracket down-tick length, as a fraction of the y range
(default |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
sketch |
A |
data |
Optional layer data frame; overrides the plot data for this layer. |
The modified PlotSpec.
set.seed(1) d <- data.frame(g = rep(c("a", "b", "c"), each = 30), y = c(rnorm(30), rnorm(30, 1), rnorm(30, 0.4))) vplot(d) |> mark_boxplot(x = g, y = y) |> mark_signif(x = g, y = y, comparisons = list(c("a", "b"), c("a", "c")))set.seed(1) d <- data.frame(g = rep(c("a", "b", "c"), each = 30), y = c(rnorm(30), rnorm(30, 1), rnorm(30, 0.4))) vplot(d) |> mark_boxplot(x = g, y = y) |> mark_signif(x = g, y = y, comparisons = list(c("a", "b"), c("a", "c")))
mark_text() draws the label aesthetic as text at each (x, y);
mark_label() adds a filled rounded background behind each label. size is
the font size in points; angle (degrees) may be mapped or constant.
mark_text( plot, ..., size = NULL, family = NULL, fontface = NULL, hjust = "centre", vjust = "centre", angle = NULL, nudge_x = 0, nudge_y = 0, repel = FALSE, box_padding = 1, point_padding = 1, min_segment_length = 2, seed = NULL, effects = list(), blend = NULL, data = NULL ) mark_label( plot, ..., size = NULL, family = NULL, fontface = NULL, hjust = "centre", vjust = "centre", angle = NULL, nudge_x = 0, nudge_y = 0, fill = "white", repel = FALSE, box_padding = 1, point_padding = 1, min_segment_length = 2, seed = NULL, effects = list(), blend = NULL, sketch = NULL, data = NULL )mark_text( plot, ..., size = NULL, family = NULL, fontface = NULL, hjust = "centre", vjust = "centre", angle = NULL, nudge_x = 0, nudge_y = 0, repel = FALSE, box_padding = 1, point_padding = 1, min_segment_length = 2, seed = NULL, effects = list(), blend = NULL, data = NULL ) mark_label( plot, ..., size = NULL, family = NULL, fontface = NULL, hjust = "centre", vjust = "centre", angle = NULL, nudge_x = 0, nudge_y = 0, fill = "white", repel = FALSE, box_padding = 1, point_padding = 1, min_segment_length = 2, seed = NULL, effects = list(), blend = NULL, sketch = NULL, data = NULL )
plot |
|
... |
Encodings (tidy-eval): |
size |
Font size in points. |
family, fontface
|
Font family / face ( |
hjust, vjust
|
Horizontal / vertical justification (constant; |
angle |
Text rotation in degrees. |
nudge_x, nudge_y
|
Shift each label by an exact absolute distance in
millimetres ( |
repel |
Move overlapping labels apart (force-directed, ggrepel-style), with leader lines to the points? Single cartesian panel only. |
box_padding |
Extra space (mm) kept around each label box during repulsion. |
point_padding |
Retained for back-compatibility and currently ignored: the repulsion solver is deterministic and pads uniformly. |
min_segment_length |
Shortest leader line (mm) worth drawing; a label that barely moved gets none. |
seed |
Retained for back-compatibility and currently a no-op: the repel layout is deterministic, so there is nothing for a seed to vary. |
effects |
A list of layer render effects applied to the mark at draw
time — |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
data |
Optional layer data frame; overrides the plot data for this layer. |
fill |
For |
sketch |
A |
The label for mark_text() may be plain text (embedded newlines \n wrap
onto stacked lines) or rich vellum::md() labels — map label = md(<expr>)
for a per-datum styled label (bold/italic/super-/subscript/colour). (Rich
labels are not yet supported by mark_label()'s background box.)
Set repel = TRUE to move overlapping labels apart with a force-directed
layout (like ggrepel), drawing a thin leader line back to each label's point.
Repulsion is resolved exactly against the true rendered panel size, so it does
not depend on the data scale. It is currently limited to a single cartesian
panel (no facets / composition / polar).
The modified PlotSpec.
vplot(mtcars) |> mark_text(x = wt, y = mpg, label = rownames(mtcars)) vplot(mtcars) |> mark_point(x = wt, y = mpg) |> mark_text(x = wt, y = mpg, label = rownames(mtcars), nudge_y = 2)vplot(mtcars) |> mark_text(x = wt, y = mpg, label = rownames(mtcars)) vplot(mtcars) |> mark_point(x = wt, y = mpg) |> mark_text(x = wt, y = mpg, label = rownames(mtcars), nudge_y = 2)
mark_text_path() draws a label that follows a curve — one string per
group, its glyphs placed along the group's x/y points (in data order) and
rotated to the local tangent. Use it for a label riding a contour, an arc, or
a trend line (a direct-labelling alternative to a legend), where
mark_text()'s point-anchored, axis-aligned labels do not fit.
mark_text_path( plot, ..., size = NULL, family = NULL, fontface = NULL, hjust = "centre", vjust = "centre", offset = 0, blend = NULL, data = NULL )mark_text_path( plot, ..., size = NULL, family = NULL, fontface = NULL, hjust = "centre", vjust = "centre", offset = 0, blend = NULL, data = NULL )
plot |
|
... |
Encodings (tidy-eval): |
size |
Font size in points. |
family, fontface
|
Font family and face ( |
hjust |
Where the run sits along the path: |
vjust |
Vertical placement of the glyphs against the baseline. |
offset |
Perpendicular standoff from the path, in points (positive is to the left of travel), for a label riding just above or below its curve. |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
data |
Optional layer data frame; overrides the plot data for this layer. |
One label is drawn per group. Split groups the usual way — a discrete color
(or a distinct label) starts a new run — and the label is taken from the
group's first row (it is constant along the path). The points are used in the
order they appear in the data: pre-sort if the curve should be traversed in a
particular direction. Because glyphs follow the tangent (like SVG textPath),
a label on the underside of a closed curve reads upside-down; reverse the path
to flip it.
The modified PlotSpec.
# Traverse the arc left-to-right so the glyphs read upright (a path walked # right-to-left would set the label upside-down). t <- seq(pi, 0, length.out = 40) d <- data.frame(x = cos(t), y = sin(t), lab = "along the arc") vplot(d) |> mark_text_path(x = x, y = y, label = lab)# Traverse the arc left-to-right so the glyphs read upright (a path walked # right-to-left would set the label upside-down). t <- seq(pi, 0, length.out = 40) d <- data.frame(x = cos(t), y = sin(t), lab = "along the arc") vplot(d) |> mark_text_path(x = x, y = y, label = lab)
mark_tile() draws a rectangular tile at each (x, y) coloured by fill;
mark_raster() draws the same as one raster image (a fast path requiring a
complete regular grid). mark_bin2d() bins continuous x/y into a grid and
colours each cell by count. mark_density() draws a 1-D kernel density of x
as a filled curve.
mark_tile(plot, ..., blend = NULL, sketch = NULL, data = NULL) mark_raster(plot, ..., blend = NULL, data = NULL) mark_bin2d(plot, ..., bins = 30, blend = NULL, data = NULL) mark_density(plot, ..., adjust = 1, blend = NULL, sketch = NULL, data = NULL) mark_hex(plot, ..., bins = 30, blend = NULL, data = NULL)mark_tile(plot, ..., blend = NULL, sketch = NULL, data = NULL) mark_raster(plot, ..., blend = NULL, data = NULL) mark_bin2d(plot, ..., bins = 30, blend = NULL, data = NULL) mark_density(plot, ..., adjust = 1, blend = NULL, sketch = NULL, data = NULL) mark_hex(plot, ..., bins = 30, blend = NULL, data = NULL)
plot |
|
... |
Encodings (tidy-eval): |
blend |
Optional blend mode for compositing this layer against what is
already drawn beneath it (the panel and earlier layers), one of the CSS
|
sketch |
A |
data |
Optional layer data frame; overrides the plot data for this layer. |
bins |
Number of bins per axis for |
adjust |
Bandwidth multiplier for |
The modified PlotSpec.
d <- expand.grid(x = 1:5, y = 1:5) d$z <- d$x * d$y vplot(d) |> mark_tile(x = x, y = y, fill = z)d <- expand.grid(x = 1:5, y = 1:5) d$z <- d$x * d$y vplot(d) |> mark_tile(x = x, y = y, fill = z)
Marks that draw a variable's distribution as a filled shape.
mark_violin() draws a mirrored kernel density of y per categorical x
(like a boxplot's footprint); mark_ridgeline() draws a kernel density of x
per categorical y as overlapping ridges. mark_dotplot() bins x and
stacks one dot per observation.
mark_violin(plot, ..., adjust = 1, blend = NULL, sketch = NULL, data = NULL) mark_ridgeline( plot, ..., adjust = 1, height = 1.4, blend = NULL, sketch = NULL, data = NULL ) mark_dotplot( plot, ..., binwidth = NULL, blend = NULL, sketch = NULL, data = NULL )mark_violin(plot, ..., adjust = 1, blend = NULL, sketch = NULL, data = NULL) mark_ridgeline( plot, ..., adjust = 1, height = 1.4, blend = NULL, sketch = NULL, data = NULL ) mark_dotplot( plot, ..., binwidth = NULL, blend = NULL, sketch = NULL, data = NULL )
plot |
A PlotSpec. |
... |
Encodings. |
adjust |
Kernel-density bandwidth multiplier (violin/ridgeline). |
blend, sketch, data
|
Standard layer arguments (see |
height |
Ridge height as a multiple of the row band (ridgeline; default
|
binwidth |
Dot-plot bin width, or |
The modified PlotSpec.
df <- data.frame(g = rep(letters[1:3], each = 50), v = rnorm(150)) vplot(df) |> mark_violin(x = g, y = v) vplot(df) |> mark_ridgeline(x = v, y = g) vplot(df) |> mark_dotplot(x = v)df <- data.frame(g = rep(letters[1:3], each = 50), v = rnorm(150)) vplot(df) |> mark_violin(x = g, y = v) vplot(df) |> mark_ridgeline(x = v, y = g) vplot(df) |> mark_dotplot(x = v)
Starts a Model Context Protocol server on stdio so an agent can generate
validated vellumplot specs. It exposes three tools — get_schema,
list_fields, and render_spec — that delegate to spec_schema(),
spec_fields(), and spec_diagnose() + render_plot(). A render_spec
failure returns structured diagnostics (unknown field, compile error) so the
agent can repair and retry, rather than a traceback.
mcp_serve(input = "stdin", output = stdout())mcp_serve(input = "stdin", output = stdout())
input, output
|
Connections to read requests from / write responses to (defaults: standard input / output). |
The server is pure R (newline-delimited JSON-RPC 2.0 over stdio) and needs no
Node or SDK. Point an MCP client at it with:
Rscript -e 'vellumplot::mcp_serve()', or the bundled launcher
system.file("mcp/server.R", package = "vellumplot").
Invisibly NULL, when the input stream closes.
spec_schema(), spec_fields(), vplot_from_spec()
A thin wrapper around vellum::md() that builds a rich-text label from a
markdown subset: **bold**, *italic* / _italic_, ^superscript^,
~subscript~, and a colour span [text]{#c00}. The result can be used
anywhere vellumplot draws a title: labs() (title / subtitle /
caption / tag / x / y / color) and scale_*(name = ). Per-element
rich labels (in mark_text()) are not yet supported.
md(text)md(text)
text |
A length-one markdown string. |
A vellum_md_label object accepted by vellum::text_grob().
vplot(mtcars) |> mark_point(x = wt, y = mpg) |> labs(title = md("**Fuel** economy"), y = md("Efficiency (mi gal^-1^)"))vplot(mtcars) |> mark_point(x = wt, y = mpg) |> labs(title = md("**Fuel** economy"), y = md("Efficiency (mi gal^-1^)"))
Draw a fading trail of a stroked or point mark: n copies marching off along
a direction (x, y), each further out and fainter than the last, composited
beneath the crisp original — a speed-blur or animation-still look. motion()
defaults to many close, low-opacity copies (a smooth blur streak); echo()
defaults to a few wider-spaced, more-opaque copies (discrete ghost repeats).
Both build the same effect, differing only in defaults, and apply to the same
marks as glow().
motion( x = 3, y = 0, n = 8L, alpha = 0.15, decay = 1, spread = 0, blend = "normal", color = NULL ) echo( x = 4, y = 0, n = 3L, alpha = 0.45, decay = 1, spread = 0, blend = "normal", color = NULL )motion( x = 3, y = 0, n = 8L, alpha = 0.15, decay = 1, spread = 0, blend = "normal", color = NULL ) echo( x = 4, y = 0, n = 3L, alpha = 0.45, decay = 1, spread = 0, blend = "normal", color = NULL )
x, y
|
Trail direction and length in millimetres ( |
n |
Number of trail copies. |
alpha |
Opacity of the nearest (strongest) copy; copies fade toward the tail. |
decay |
Fade exponent shaping the opacity ramp along the trail (higher =
faster fade toward the tail; |
spread |
Optional widening, in millimetres, applied progressively toward
the tail ( |
blend |
Blend mode compositing the trail copies (any CSS
|
color |
Trail colour, or |
The direction is an absolute distance in millimetres (+x right, +y
up), resolved device-side via vellum's compound npc + mm unit, so the
trail keeps the same physical length and stays isotropic regardless of the
panel's size or aspect (as shadow()'s offset does).
A MotionSpec object for a mark's effects list.
df <- data.frame(x = 1:20, y = cumsum(rnorm(20))) vplot(df) |> mark_line(x = x, y = y, effects = list(motion(x = 4))) vplot(mtcars) |> mark_point(x = wt, y = mpg, size = 4, effects = list(echo(x = 5)))df <- data.frame(x = 1:20, y = cumsum(rnorm(20))) vplot(df) |> mark_line(x = x, y = y, effects = list(motion(x = 4))) vplot(mtcars) |> mark_point(x = wt, y = mpg, size = 4, effects = list(echo(x = 5)))
Draws one opaque, wider copy of a stroked or point mark beneath the crisp
original in a contrasting colour, so the mark stays legible over a busy or
dark backdrop (the "sticker" look). Applies to the same marks as glow().
outline(size = 1, color = "white", alpha = 1)outline(size = 1, color = "white", alpha = 1)
size |
Halo width per side, in millimetres. |
color |
Outline colour. |
alpha |
Outline opacity. |
An OutlineSpec object for a mark's effects list.
vplot(mtcars) |> mark_point(x = wt, y = mpg, color = factor(cyl), size = 3, effects = list(outline()))vplot(mtcars) |> mark_point(x = wt, y = mpg, color = factor(cyl), size = 3, effects = list(outline()))
pattern_hatch() is the vector companion of the tile patterns above:
evenly spaced parallel lines produced as real geometry via vellum::vl_hatch()
rather than a rasterised tile. Because it is vector, it stays crisp at any
magnification and in PDF (no embedded image), which makes it the better
redundant, non-colour encoding for accessible and print output — the "fix it"
step alongside plot_lint() and render_plot(cvd = ).
pattern_hatch( color = "grey20", bg = NA, angle = 45, spacing = 3, linewidth = 0.75 )pattern_hatch( color = "grey20", bg = NA, angle = 45, spacing = 3, linewidth = 0.75 )
color |
Line colour (any R colour). Default |
bg |
Background fill painted behind the lines, or |
angle |
Line orientation in degrees. Any angle is allowed (unlike the
tile patterns, vector hatch has no seamless-tiling restriction). Default
|
spacing |
Distance between lines, in millimetres. Default |
linewidth |
Line width. Default |
Use it exactly like the other pattern constructors: as a constant fill on a
filled mark, or as one of the values of scale_pattern() to map a discrete
variable to hatch textures.
A vellum_hatch object, usable as a fill value.
patterns, scale_pattern(), plot_lint(), vellum::vl_hatch()
df <- data.frame(g = c("a", "b", "c"), n = c(3, 5, 2)) vplot(df) |> mark_bar(x = g, y = n, fill = pattern_hatch(angle = 30))df <- data.frame(g = c("a", "b", "c"), n = c(3, 5, 2)) vplot(df) |> mark_bar(x = g, y = n, fill = pattern_hatch(angle = 30))
Build a tiling pattern to use as a constant fill value on a filled mark,
the texture counterpart of linear_gradient(). Distinguishing regions by
texture (not only hue) keeps a plot legible in greyscale print and under
colour-vision deficiency. Each constructor assembles a small tile and returns a
vellum_pattern (via vellum::vl_pattern()); pass it straight to fill:
pattern_stripe( color = "grey20", bg = NA, angle = 45, spacing = 4, linewidth = 1, units = "mm" ) pattern_crosshatch( color = "grey20", bg = NA, angle = 45, spacing = 4, linewidth = 1, units = "mm" ) pattern_grid( color = "grey20", bg = NA, spacing = 4, linewidth = 1, units = "mm" ) pattern_dot(color = "grey20", bg = NA, spacing = 4, size = 1.5, units = "mm") pattern_checker(color = "grey20", bg = NA, size = 4, units = "mm")pattern_stripe( color = "grey20", bg = NA, angle = 45, spacing = 4, linewidth = 1, units = "mm" ) pattern_crosshatch( color = "grey20", bg = NA, angle = 45, spacing = 4, linewidth = 1, units = "mm" ) pattern_grid( color = "grey20", bg = NA, spacing = 4, linewidth = 1, units = "mm" ) pattern_dot(color = "grey20", bg = NA, spacing = 4, size = 1.5, units = "mm") pattern_checker(color = "grey20", bg = NA, size = 4, units = "mm")
color |
Line/dot colour (any R colour). Default |
bg |
Background fill painted behind the motif, or |
angle |
Stripe orientation in degrees, restricted to |
spacing |
Distance between repeats, in |
linewidth |
Stripe / grid line width (as elsewhere in the package).
Default |
units |
Length unit for |
size |
For |
vplot(df) |> mark_bar(x = g, y = n, fill = pattern_stripe(angle = 45))
A pattern is an unscaled value, not a data-mapped channel (like a gradient).
It applies to any filled mark: bars, areas, ribbons, rects, tiles, boxplots,
violins, ridgelines, half-eyes, hulls/ellipses, and sf polygons. To vary the
texture by a variable, map the pattern aesthetic instead (a discrete scale).
Patterns render on every backend (PNG, SVG, and — since the tile embeds as an image — PDF). The tile is rasterised at the scene resolution, so at extreme magnification it can soften; at ordinary sizes it is crisp.
A vellum_pattern object, usable as a fill value.
linear_gradient(), vellum::vl_pattern()
df <- data.frame(g = c("a", "b", "c"), n = c(3, 5, 2)) vplot(df) |> mark_bar(x = g, y = n, fill = pattern_crosshatch())df <- data.frame(g = c("a", "b", "c"), n = c(3, 5, 2)) vplot(df) |> mark_bar(x = g, y = n, fill = pattern_crosshatch())
pdf_pages() writes several plots into one PDF, one plot per page — a report,
a slide deck, or one page per facet. It is the multi-page companion of
render_plot() (which writes a single page). Pages may differ in size (each
plot keeps its own width/height), and the per-page accessibility tags
(structure tree + Alt, see the Accessibility article) are written for
every page.
pdf_pages(x, path)pdf_pages(x, path)
x |
Either a list of plots (each a PlotSpec, composition, or table)
— one page each — or a single faceted |
path |
Output |
path, invisibly.
p1 <- vplot(mtcars) |> mark_point(x = wt, y = mpg) p2 <- vplot(mtcars) |> mark_histogram(x = mpg, bins = 8) f <- tempfile(fileext = ".pdf") pdf_pages(list(p1, p2), f) # one page per facet cell: faceted <- vplot(mtcars) |> mark_point(x = wt, y = mpg) |> facet_wrap(~cyl) pdf_pages(faceted, tempfile(fileext = ".pdf"))p1 <- vplot(mtcars) |> mark_point(x = wt, y = mpg) p2 <- vplot(mtcars) |> mark_histogram(x = mpg, bins = 8) f <- tempfile(fileext = ".pdf") pdf_pages(list(p1, p2), f) # one page per facet cell: faceted <- vplot(mtcars) |> mark_point(x = wt, y = mpg) |> facet_wrap(~cyl) pdf_pages(faceted, tempfile(fileext = ".pdf"))
Returns the description used as the plot's text alternative for assistive
technology. If labs() set an explicit alt, that string is returned
verbatim; otherwise vellumplot generates a prose summary from the specification —
the chart type, what each axis / colour / size encodes, the number of
observations, and any faceting.
plot_alt(x)plot_alt(x)
x |
A PlotSpec or a plot composition. |
render_plot() (and any compile through vellum::as_vellum_scene()) passes
this text to the scene's description, so the exported SVG carries it in
<desc> (with role="img") and the exported PDF tags the chart as a
Figure whose Alt is this text. The plot title (from labs(title=))
becomes the accessible name. See the Accessibility article.
A single string.
p <- vplot(mtcars) |> mark_point(x = wt, y = mpg, color = hp) plot_alt(p) plot_alt(labs(p, alt = "Heavier cars get fewer miles per gallon."))p <- vplot(mtcars) |> mark_point(x = wt, y = mpg, color = hp) plot_alt(p) plot_alt(labs(p, alt = "Heavier cars get fewer miles per gallon."))
plot_data_uri() renders a plot to a self-contained data: URI string —
the bytes of the image inlined as base64 — ready to drop into an HTML <img src>, a Markdown image, an email, or anywhere a URL is expected without a
separate file. "svg" (default) inlines the crisp vector SVG; "png" inlines
a raster render.
plot_data_uri( plot, format = c("svg", "png"), width = NULL, height = NULL, dpi = NULL, ... )plot_data_uri( plot, format = c("svg", "png"), width = NULL, height = NULL, dpi = NULL, ... )
plot |
A PlotSpec (or any object |
format |
|
width, height
|
Optional size override in inches. |
dpi |
For |
... |
Passed to |
A length-1 character data: URI.
uri <- vplot(mtcars) |> mark_point(x = wt, y = mpg) |> plot_data_uri() substr(uri, 1, 30)uri <- vplot(mtcars) |> mark_point(x = wt, y = mpg) |> plot_data_uri() substr(uri, 1, 30)
plot_lint() compiles a plot and reports the design problems a static render
hides from a green test suite: text too small to read, colour contrast below
the WCAG threshold, two palette colours a colour-blind reader cannot tell
apart, labels that overlap or fall off the panel, and grammar-level mistakes
such as an encoding with a single level or a legend too long to read. It is
the "flag it" step of the accessibility workflow — pair it with
render_plot(cvd = ) to see a failing palette and scale_pattern() /
pattern_hatch() to fix it with a redundant non-colour encoding.
plot_lint(x, ..., min_text_px = 7, min_contrast = 3)plot_lint(x, ..., min_text_px = 7, min_contrast = 3)
x |
A PlotSpec (or anything |
... |
Passed to |
min_text_px |
Minimum legible text height in pixels (default |
min_contrast |
Minimum acceptable contrast ratio between a mark and its
background (default |
The geometric rules come from the engine's vellum::vl_lint(), which judges
them in resolved device pixels. The grammar rules are registered into the same
registry by vellumplot, so they are not special: vellum::vl_lint_rules()
lists them, rules = selects them, and vellum::vl_lint() on a compiled plot
reports them too. Findings are returned most-severe first.
Because every finding carries the box it refers to,
vellum::vl_lint_overlay() can draw the report onto the plot, and
vellum::vl_lint_assert() can fail a test on it.
A composition or table has no single set of trained scales, so it reports the geometric findings only — lint the cells individually for the grammar ones (vellumplot#147).
A data frame (class vellum_lint) with one row per finding: rule,
severity ("warning"/"note"), node, a human message, and the
device-px box x0/y0/x1/y1 — NA for a grammar finding, which is
about a scale and so has no box. Zero rows when the plot is clean.
render_plot() (cvd =), scale_pattern(), pattern_hatch(),
vellum::vl_lint(), vellum::vl_lint_overlay(), vellum::vl_lint_assert()
# a tiny-text, single-level-scale plot trips the linter p <- vplot(transform(mtcars, grp = "one group")) |> mark_point(x = wt, y = mpg, color = grp) |> theme(axis.text = element_text(size = 2)) plot_lint(p) # the engine's arguments come through, so a project can accept a finding plot_lint(p, exclude = "scale:color")# a tiny-text, single-level-scale plot trips the linter p <- vplot(transform(mtcars, grp = "one group")) |> mark_point(x = wt, y = mpg, color = grp) |> theme(axis.text = element_text(size = 2)) plot_lint(p) # the engine's arguments come through, so a project can accept a finding plot_lint(p, exclude = "scale:color")
plot_manifest() returns a small, serializable fingerprint of a plot: a hash
of its input data (order- and column-sensitive), the data's shape and column
names, a structural hash of the spec, and the number of emitted elements. It
is what plot_svg() can embed (with manifest = TRUE) so a figure carries
its own provenance, and what plot_verify() recomputes to confirm a figure
still matches its data.
plot_manifest(x)plot_manifest(x)
x |
A PlotSpec. |
A named list: version, data (a hash/nrow/columns record),
spec_hash, n_elements, and fonts (the faces the plot resolved to, via
vellum::font_pin(), each a path/index/glyphs record). The fonts are
what lets plot_verify() tell a font-stack difference apart from a data
change — the same pixels are only guaranteed when the same fonts are
present.
plot_verify(), plot_svg(), provenance_join()
plot_manifest(vplot(mtcars) |> mark_point(x = wt, y = mpg))$data$hashplot_manifest(vplot(mtcars) |> mark_point(x = wt, y = mpg))$data$hash
Compiles x and returns its provenance table: one record per emitted mark
grob, tying each low-level primitive back to the data rows and trained scales
that produced it. Each record's id matches the grob's data-vellum-id in
the SVG output (and the id column of vellum::scene_model()), so it is a
stable join key between the rendered scene and the grammar — the substrate for
interactivity, linked views, and accessibility.
plot_provenance(x)plot_provenance(x)
x |
A PlotSpec or plot composition. |
Each record is a plain, serializable list:
idstable node id, equal to grob@id / SVG data-vellum-id (join key).
layer1-based layer index within the (sub-)plot spec.
markmark type ("point", "line", …).
kind"mark" (the core layer) or "effect" (a decorative underlay).
panelfacet panel key ("panel-r-c"), or NA for a single panel.
channelsaesthetic → trained-scale reference (scale, type, domain).
rowsthe original input-data row indices this grob draws.
The rows field is refined per element for marks that map rows one-to-one to
drawn elements (points, bars, tiles, segments, lines, areas, ribbons, steps,
text, boxplots, sf features, edges); for aggregating marks (histogram,
density, smooth, datashade, …) it is the whole layer, since rows no longer map
to single elements.
A list of provenance records (see Details). Empty for a plot that emits no mark grobs.
vellum::scene_model() and the scene-contract vignette in vellum.
df <- data.frame(wt = mtcars$wt, mpg = mtcars$mpg, model = rownames(mtcars)) p <- vplot(df) |> mark_point(x = wt, y = mpg, data_id = model) prov <- plot_provenance(p) prov[[1]]$iddf <- data.frame(wt = mtcars$wt, mpg = mtcars$mpg, model = rownames(mtcars)) p <- vplot(df) |> mark_point(x = wt, y = mpg, data_id = model) prov <- plot_provenance(p) prov[[1]]$id
Use inside concat() / wrap_plots() (or a design) to leave a gap.
plot_spacer()plot_spacer()
A spacer placeholder.
a <- vplot(mtcars) |> mark_point(x = wt, y = mpg) concat(a, plot_spacer(), a, plot_spacer(), ncol = 2)a <- vplot(mtcars) |> mark_point(x = wt, y = mpg) concat(a, plot_spacer(), a, plot_spacer(), ncol = 2)
plot_svg() compiles any vellumplot object (a PlotSpec, vtable(), or a
composition) to a stand-alone <svg> string rather than a file — the way
to embed a chart inline in HTML: a vsparkline() in a gt / reactable /
DT cell, a chart in a Quarto callout, or an inline glyph in a report. The
string carries a viewBox, so it scales.
plot_svg( plot, width = NULL, height = NULL, scaling = c("fixed", "fit"), inline = FALSE, recolor = NULL, text = "native", manifest = FALSE )plot_svg( plot, width = NULL, height = NULL, scaling = c("fixed", "fit"), inline = FALSE, recolor = NULL, text = "native", manifest = FALSE )
plot |
|
width, height
|
Optional page-size override in inches (defaults to the object's own size). |
scaling |
|
inline |
|
recolor |
Optional named character vector mapping a source colour to a
replacement written verbatim into the SVG — e.g.
|
text |
How glyphs are emitted: |
manifest |
If |
A length-1 character SVG string.
vsparkline(), gt_vsparkline(), render_plot(), plot_manifest()
svg <- plot_svg(vsparkline(cumsum(rnorm(20)))) substr(svg, 1, 40) # a transparent, prolog-free, dark-mode-adaptive inline sparkline: plot_svg(vsparkline(1:9, color = "grey30"), inline = TRUE, recolor = c(grey30 = "currentColor") )svg <- plot_svg(vsparkline(cumsum(rnorm(20)))) substr(svg, 1, 40) # a transparent, prolog-free, dark-mode-adaptive inline sparkline: plot_svg(vsparkline(1:9, color = "grey30"), inline = TRUE, recolor = c(grey30 = "currentColor") )
plot_verify() extracts the manifest embedded in an SVG written with
plot_svg()(manifest = TRUE) and recomputes the data fingerprint from
data, reporting whether the figure still matches the data it was drawn from
— a lightweight, self-contained reproducibility check.
plot_verify(svg, data)plot_verify(svg, data)
svg |
An SVG string (from |
data |
The data frame to check the figure against. |
A font mismatch is reported as a distinct outcome from a data mismatch:
data_ok is whether the data still hashes the same, fonts_ok whether every
font the figure was drawn with is still present on this machine, and ok
their conjunction. A pixel difference with data_ok = TRUE but
fonts_ok = FALSE is the font stack, not your data — a different cause with a
different fix (install/register the font) than a data change.
A list with ok (data and fonts match), data_ok, expected /
actual (the embedded vs recomputed data hash), fonts_ok, and
fonts_missing (the recorded font paths absent on this machine). Errors if
the SVG carries no manifest.
svg <- plot_svg(vplot(mtcars) |> mark_point(x = wt, y = mpg), manifest = TRUE) plot_verify(svg, mtcars)$oksvg <- plot_svg(vplot(mtcars) |> mark_point(x = wt, y = mpg), manifest = TRUE) plot_verify(svg, mtcars)$ok
PlotSpec is the S7 class that vplot() creates and the mark_*() /
scale_*() functions extend. It is a plain, inspectable, serializable data
object: data, a list of layers, a list of scale overrides, and the page size.
Nothing is drawn until it is compiled with vellum::as_vellum_scene() (e.g.
via render_plot()). Printing it draws the plot; inspect its structure with
base::summary().
PlotSpec( data = NULL, edge_data = NULL, layers = list(), scales = list(), facet = NULL, coord = NULL, resolve = list(), width = 6, height = 4, dpi = 96, theme = NULL, labels = list(), marginal = NULL, selections = list(), filters = list(), binds = list(), clip = NULL, transition = NULL, ease = NULL, source = NULL )PlotSpec( data = NULL, edge_data = NULL, layers = list(), scales = list(), facet = NULL, coord = NULL, resolve = list(), width = 6, height = 4, dpi = 96, theme = NULL, labels = list(), marginal = NULL, selections = list(), filters = list(), binds = list(), clip = NULL, transition = NULL, ease = NULL, source = NULL )
data |
The data frame. |
edge_data |
For a graph plot (from |
layers |
A list of layer specifications (one per |
scales |
A list of declared scale overrides. |
facet |
A faceting specification (from |
coord |
A coordinate specification (from |
resolve |
A named list mapping an aesthetic to |
width, height
|
Page size in inches. |
dpi |
Output resolution in dots per inch (pixels per inch). The exported
PNG's pixel dimensions are |
theme |
A theme (a named list of resolved element/setting overrides, from
|
labels |
A named list of plot/axis/legend label overrides (see |
marginal |
A marginal-distribution specification (from |
selections |
A list of interactive selection declarations (from
|
filters |
A list of filter declarations (from |
binds |
A list of scale-domain bind declarations (from |
clip |
A |
transition |
A keyframe-animation transition (from |
ease |
An animation easing (from |
source |
A source-inspection declaration (from |
A PlotSpec.
vplot(), mark_point(), scale_x_continuous()
Fine-grained control over how a mark's overlapping elements are placed. Pass
the result to a mark's position argument (e.g.
mark_point(position = position_jitter(width = 0.2))). A bare string
(position = "dodge") still works and uses the defaults.
position_nudge(x = 0, y = 0) position_jitter(width = NULL, height = NULL, seed = NULL) position_dodge(width = NULL) position_dodge2(padding = 0.1) position_sina(width = 0.8, seed = NULL) position_jitterdodge( jitter.width = NULL, jitter.height = 0, dodge.width = 0.75, seed = NULL )position_nudge(x = 0, y = 0) position_jitter(width = NULL, height = NULL, seed = NULL) position_dodge(width = NULL) position_dodge2(padding = 0.1) position_sina(width = 0.8, seed = NULL) position_jitterdodge( jitter.width = NULL, jitter.height = 0, dodge.width = 0.75, seed = NULL )
x, y
|
|
width, height
|
Maximum jitter (data units); |
seed |
Optional integer seed for the random jitter. |
padding |
|
dodge.width, jitter.width, jitter.height
|
|
position_nudge() shifts every element by a constant amount in data
units (for continuous axes) — handy for offsetting labels from points.
position_jitter() adds uniform random noise; width/height are the
maximum shift in data units (default: 40% of the resolution), seed makes
it reproducible.
position_dodge() places grouped elements side by side; width is the
total data-space width shared by the group (default: the category band).
position_dodge2() dodges by the groups actually present at each x and
splits the band between them with a padding gap — so ragged groupings
stay centred and evenly spaced.
position_jitterdodge() dodges grouped elements, then jitters within each
dodged slot (points over dodged boxes).
position_sina() spreads each category's points along x by a quasirandom
offset scaled to the local y-density, so the cloud traces the distribution's
shape (ggforce's sina). width is the maximum spread as a fraction of the
category band (default 0.8).
A vellumplot_position object for a mark's position argument.
vplot(mtcars) |> mark_point(x = factor(cyl), y = mpg, position = position_jitter(width = 0.15))vplot(mtcars) |> mark_point(x = factor(cyl), y = mpg, position = position_jitter(width = 0.15))
provenance_join() compiles x once and returns a tidy table with one row
per emitted mark element, tying each drawn primitive to both the source
data rows that produced it (rows, a list column) and its device-pixel
geometry (x0, y0, x1, y1, x, y, w, h) from
vellum::scene_model(). It is the consumer of the provenance table that
plot_provenance() emits — the substrate for click-to-source interactivity,
auditing "which rows made this element?", and linked views.
provenance_join(x)provenance_join(x)
x |
A PlotSpec or composition. |
A data frame: id, layer, mark, kind, panel, the pixel bbox
(x0, y0, x1, y1, x, y, w, h), n_rows, and rows (a list
column of integer source-row indices). Empty for a plot with no mark grobs.
plot_provenance(), vellum::scene_model()
df <- data.frame(wt = mtcars$wt, mpg = mtcars$mpg, cyl = factor(mtcars$cyl)) p <- vplot(df) |> mark_point(x = wt, y = mpg, color = cyl) pj <- provenance_join(p) pj[, c("id", "mark", "n_rows")]df <- data.frame(wt = mtcars$wt, mpg = mtcars$mpg, cyl = factor(mtcars$cyl)) p <- vplot(df) |> mark_point(x = wt, y = mpg, color = cyl) pj <- provenance_join(p) pj[, c("id", "mark", "n_rows")]
provenance_payload() returns a JSON-serializable structure mapping each
rendered element's stable id (data-vellum-id, the join key an SVG / widget
carries) to the source data rows that produced it — the enabler for a host
(e.g. vellumwidget) to answer "which rows made this element?" on click,
without re-running the grammar. With values = TRUE the referenced data rows
are inlined so the host can display them directly.
provenance_payload(x, values = FALSE)provenance_payload(x, values = FALSE)
x |
A PlotSpec or composition. |
values |
If |
A list with fields (column names), elements (a list of
list(id, rows) records), and — when values = TRUE — data (row-wise
records of the plot's data).
provenance_join(), plot_provenance()
p <- vplot(mtcars) |> mark_point(x = wt, y = mpg, color = factor(cyl)) pl <- provenance_payload(p) pl$elements[[1]]$idp <- vplot(mtcars) |> mark_point(x = wt, y = mpg, color = factor(cyl)) pl <- provenance_payload(p) pl$elements[[1]]$id
render_all() renders a list of independent plots to separate files across
CPU cores — small multiples, a batch export, one file per group. The work is
embarrassingly parallel (one whole plot per worker), and the result is
byte-identical to rendering them one by one. Parallelism uses process forks,
so it speeds things up on macOS/Linux and falls back to sequential on Windows;
it is only worth it for several substantial plots.
render_all(plots, paths, workers = NULL, ...)render_all(plots, paths, workers = NULL, ...)
plots |
A named or unnamed list of plots. |
paths |
Output paths, one per plot (the format of each comes from its
extension, as in |
workers |
Number of parallel workers; |
... |
Passed to each |
paths (the resolved file paths), invisibly.
render_plot(), pdf_pages(), repeat_()
plots <- list( wt = vplot(mtcars) |> mark_point(x = wt, y = mpg), hp = vplot(mtcars) |> mark_point(x = hp, y = mpg) ) render_all(plots, tempdir())plots <- list( wt = vplot(mtcars) |> mark_point(x = wt, y = mpg), hp = vplot(mtcars) |> mark_point(x = hp, y = mpg) ) render_all(plots, tempdir())
Compiles a PlotSpec into a vellum::vl_scene() and writes it. The output
format is taken from the file extension (.png, .svg, .pdf).
vellum::render() also works on a plot directly, dispatching through the
as_vellum_scene() seam.
render_plot(plot, path, text = "native", dpi = NULL, cvd = "none")render_plot(plot, path, text = "native", dpi = NULL, cvd = "none")
plot |
A PlotSpec. |
path |
Output file path. |
text |
For SVG output, how text is written (see |
dpi |
Output resolution in dots per inch. |
cvd |
Colour-vision-deficiency simulation for a |
path, invisibly.
p <- vplot(mtcars) |> mark_point(x = wt, y = mpg) f <- tempfile(fileext = ".png") render_plot(p, f) render_plot(p, f, dpi = 300) # denser raster, same physical size render_plot(p, f, cvd = "deuteranopia") # preview for red-green colour blindnessp <- vplot(mtcars) |> mark_point(x = wt, y = mpg) f <- tempfile(fileext = ".png") render_plot(p, f) render_plot(p, f, dpi = 300) # denser raster, same physical size render_plot(p, f, cvd = "deuteranopia") # preview for red-green colour blindness
Replicate a plot, re-pointing one or more encodings at a different data field
each time, and arrange the copies as a composition (like concat(), so each
sub-plot keeps its own scales and axes). Supply each aesthetic as a character
vector of column names; all vectors must be the same length N, and are
zipped to produce N sub-plots.
repeat_(plot, ..., ncol = NULL, nrow = NULL)repeat_(plot, ..., ncol = NULL, nrow = NULL)
plot |
A PlotSpec; the repeated aesthetic(s) are set on every layer
(added if not already mapped). In a multi-layer plot every layer therefore
receives the re-pointed field, so any layer carrying its own |
... |
Named aesthetics, each a character vector of field names, e.g.
|
ncol, nrow
|
Grid dimensions (passed to |
A PlotComposition.
repeat_(vplot(mtcars) |> mark_point(y = mpg), x = c("wt", "hp", "disp"))repeat_(vplot(mtcars) |> mark_point(y = mpg), x = c("wt", "hp", "disp"))
The scale-resolution lattice (after Vega-Lite): for each aesthetic, choose
whether faceted panels share one trained scale or train independent ones.
Position scales default to "shared"; facet_*(scales = "free_*") is sugar
for setting x/y to "independent".
resolve_scale(plot, ...)resolve_scale(plot, ...)
plot |
A PlotSpec. |
... |
Named arguments mapping an aesthetic ( |
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg) |> facet_wrap(~cyl) |> resolve_scale(y = "independent")vplot(mtcars) |> mark_point(x = wt, y = mpg) |> facet_wrap(~cyl) |> resolve_scale(y = "independent")
Declare the scale for a mapped alpha aesthetic: data values map to an
opacity range in [0, 1]. An alpha legend is drawn automatically.
scale_alpha(plot, range = NULL, limits = NULL, breaks = NULL, name = NULL) scale_alpha_continuous( plot, range = NULL, limits = NULL, breaks = NULL, name = NULL )scale_alpha(plot, range = NULL, limits = NULL, breaks = NULL, name = NULL) scale_alpha_continuous( plot, range = NULL, limits = NULL, breaks = NULL, name = NULL )
plot |
A PlotSpec. |
range |
Numeric length-2 output opacity range, or |
limits |
Numeric length-2 data domain, or |
breaks |
Explicit legend breaks, or |
name |
Legend title, or |
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg, alpha = hp) |> scale_alpha(range = c(0.2, 1))vplot(mtcars) |> mark_point(x = wt, y = mpg, alpha = hp) |> scale_alpha(range = c(0.2, 1))
Declare a colour scale for the color/fill channel. Continuous data get a
perceptual ramp; discrete data get a qualitative palette. scale_*_manual()
sets exact colours, scale_*_gradient() a two-point ramp, and
scale_*_gradient2() a diverging three-point ramp (low–mid–high)
centred on midpoint — for signed or anomaly data where a meaningful zero
should sit at the neutral colour. The fill variants are identical (colour and
fill share one scale). A legend is drawn automatically when colour is mapped.
scale_color_continuous( plot, palette = NULL, limits = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_color_discrete( plot, palette = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_color_manual(plot, values, name = NULL) scale_color_gradient(plot, low = "#132B43", high = "#56B1F7", name = NULL) scale_color_gradient2( plot, low = "#832424", mid = "#FFFFFF", high = "#3A3A98", midpoint = 0, name = NULL ) scale_fill_continuous( plot, palette = NULL, limits = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_color_gradientn(plot, colours, name = NULL) scale_fill_gradientn(plot, colours, name = NULL) scale_colour_gradientn(plot, colours, name = NULL) scale_fill_discrete( plot, palette = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_fill_manual(plot, values, name = NULL) scale_fill_gradient(plot, low = "#132B43", high = "#56B1F7", name = NULL) scale_fill_gradient2( plot, low = "#832424", mid = "#FFFFFF", high = "#3A3A98", midpoint = 0, name = NULL ) scale_colour_continuous( plot, palette = NULL, limits = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_colour_discrete( plot, palette = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_colour_manual(plot, values, name = NULL) scale_colour_gradient(plot, low = "#132B43", high = "#56B1F7", name = NULL) scale_colour_gradient2( plot, low = "#832424", mid = "#FFFFFF", high = "#3A3A98", midpoint = 0, name = NULL )scale_color_continuous( plot, palette = NULL, limits = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_color_discrete( plot, palette = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_color_manual(plot, values, name = NULL) scale_color_gradient(plot, low = "#132B43", high = "#56B1F7", name = NULL) scale_color_gradient2( plot, low = "#832424", mid = "#FFFFFF", high = "#3A3A98", midpoint = 0, name = NULL ) scale_fill_continuous( plot, palette = NULL, limits = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_color_gradientn(plot, colours, name = NULL) scale_fill_gradientn(plot, colours, name = NULL) scale_colour_gradientn(plot, colours, name = NULL) scale_fill_discrete( plot, palette = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_fill_manual(plot, values, name = NULL) scale_fill_gradient(plot, low = "#132B43", high = "#56B1F7", name = NULL) scale_fill_gradient2( plot, low = "#832424", mid = "#FFFFFF", high = "#3A3A98", midpoint = 0, name = NULL ) scale_colour_continuous( plot, palette = NULL, limits = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_colour_discrete( plot, palette = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_colour_manual(plot, values, name = NULL) scale_colour_gradient(plot, low = "#132B43", high = "#56B1F7", name = NULL) scale_colour_gradient2( plot, low = "#832424", mid = "#FFFFFF", high = "#3A3A98", midpoint = 0, name = NULL )
plot |
A PlotSpec. |
palette |
A vector of colours, or a single palette name passed to
|
limits |
For the continuous colour scales, a length-2 numeric
|
breaks, labels
|
Explicit legend breaks / labels, or |
name |
Legend title, or |
values |
For |
low, high
|
For |
mid |
For |
midpoint |
For |
colours |
For |
Continuous and binned ramps built from a plain colour vector are interpolated
in the perceptually-uniform Oklab space, so they avoid the muddy, over-dark
midtones and hue drift of sRGB blending. Designed perceptual palettes (the
default, and hcl.colors() names) are already uniform and unaffected. Set
options(vellumplot.color.interpolation = "srgb") (or "lab") to change the
blend space globally.
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg, color = hp) |> scale_color_continuous(palette = "Batlow")vplot(mtcars) |> mark_point(x = wt, y = mpg, color = hp) |> scale_color_continuous(palette = "Batlow")
Use the data values directly as the aesthetic — no training and no legend.
The mapped column must already contain valid aesthetic values: colours for
scale_color_identity() / scale_fill_identity(), sizes in mm for
scale_size_identity(), and shape names for scale_shape_identity(). Useful
when a column already holds the exact colours/sizes you want to draw.
scale_color_identity(plot) scale_fill_identity(plot) scale_colour_identity(plot) scale_size_identity(plot) scale_shape_identity(plot) scale_alpha_identity(plot) scale_linetype_identity(plot)scale_color_identity(plot) scale_fill_identity(plot) scale_colour_identity(plot) scale_size_identity(plot) scale_shape_identity(plot) scale_alpha_identity(plot) scale_linetype_identity(plot)
plot |
A PlotSpec. |
The modified PlotSpec.
df <- data.frame(x = 1:3, y = 1:3, col = c("red", "green", "blue")) vplot(df) |> mark_point(x = x, y = y, color = col) |> scale_color_identity()df <- data.frame(x = 1:3, y = 1:3, col = c("red", "green", "blue")) vplot(df) |> mark_point(x = x, y = y, color = col) |> scale_color_identity()
Declare the scale for a mapped edge aesthetic on a vgraph() plot – the
colour (mark_edges(color = )), opacity (alpha = ), or line type
(linetype = ) of the edges. These are the edge counterparts of
scale_color_continuous() / scale_alpha() / scale_linetype(): an edge
aesthetic is trained and legended independently of the node scales, so a
figure can map, say, node fill to a discrete community and edge colour to a
continuous weight without the two collapsing into one legend. Each draws its
own legend automatically.
scale_edge_color( plot, palette = NULL, breaks = NULL, labels = NULL, name = NULL, midpoint = NULL ) scale_edge_colour( plot, palette = NULL, breaks = NULL, labels = NULL, name = NULL, midpoint = NULL ) scale_edge_alpha(plot, range = NULL, limits = NULL, breaks = NULL, name = NULL) scale_edge_linetype(plot, values = NULL, name = NULL)scale_edge_color( plot, palette = NULL, breaks = NULL, labels = NULL, name = NULL, midpoint = NULL ) scale_edge_colour( plot, palette = NULL, breaks = NULL, labels = NULL, name = NULL, midpoint = NULL ) scale_edge_alpha(plot, range = NULL, limits = NULL, breaks = NULL, name = NULL) scale_edge_linetype(plot, values = NULL, name = NULL)
plot |
|
palette |
For |
name |
Legend title, or |
midpoint |
For |
range |
For |
limits, breaks, labels
|
Data limits, explicit legend breaks, and explicit
labels, or |
values |
For |
scale_edge_color() infers discrete vs continuous from the mapped data (a
factor/character trains a discrete swatch legend; a number a colour bar), the
same as the node colour scale. scale_edge_colour() is a British-spelling
alias.
The modified PlotSpec.
mark_edges(), scale_edge_width(), vgraph()
## Not run: g <- igraph::make_graph("Zachary") g <- igraph::set_edge_attr(g, "w", value = runif(igraph::ecount(g))) vgraph(g) |> mark_edges(color = w) |> mark_nodes(fill = factor(igraph::membership(igraph::cluster_louvain(g)))) |> scale_edge_color(palette = "Grays") ## End(Not run)## Not run: g <- igraph::make_graph("Zachary") g <- igraph::set_edge_attr(g, "w", value = runif(igraph::ecount(g))) vgraph(g) |> mark_edges(color = w) |> mark_nodes(fill = factor(igraph::membership(igraph::cluster_louvain(g)))) |> scale_edge_color(palette = "Grays") ## End(Not run)
Declare the scale for a mapped edge linewidth aesthetic (e.g.
mark_edges(linewidth = weight) on a vgraph() plot). The data range is
rescaled to a line-width range and an edge-width legend is drawn automatically.
scale_edge_width(plot, range = NULL, limits = NULL, breaks = NULL, name = NULL)scale_edge_width(plot, range = NULL, limits = NULL, breaks = NULL, name = NULL)
plot |
A PlotSpec. |
range |
Output line-width range |
limits |
Data limits |
breaks |
Explicit legend breaks, or |
name |
Legend title, or |
The modified PlotSpec.
## Not run: g <- igraph::sample_gnp(20, 0.2) g <- igraph::set_edge_attr(g, "w", value = runif(igraph::ecount(g))) vgraph(g) |> mark_edges(linewidth = w) |> mark_nodes() |> scale_edge_width(range = c(0.3, 4)) ## End(Not run)## Not run: g <- igraph::sample_gnp(20, 0.2) g <- igraph::set_edge_attr(g, "w", value = runif(igraph::ecount(g))) vgraph(g) |> mark_edges(linewidth = w) |> mark_nodes() |> scale_edge_width(range = c(0.3, 4)) ## End(Not run)
scale_fill_binned() / scale_color_binned() cut a continuous aesthetic into
classes and colour each class with one step of a sequential palette — the
standard choropleth scale. Class breaks are chosen by a classification
style. quantile, equal, and pretty need no extra packages; other
styles (e.g. "jenks", "fisher", "kmeans", "headtails") delegate to the
optional classInt package (in Suggests) and error if it is absent.
scale_fill_binned( plot, style = "quantile", n = 5, breaks = NULL, palette = NULL, labels = NULL, na_value = "grey80", name = NULL ) scale_color_binned( plot, style = "quantile", n = 5, breaks = NULL, palette = NULL, labels = NULL, na_value = "grey80", name = NULL ) scale_color_steps( plot, style = "quantile", n = 5, breaks = NULL, palette = NULL, labels = NULL, na_value = "grey80", name = NULL ) scale_colour_steps( plot, style = "quantile", n = 5, breaks = NULL, palette = NULL, labels = NULL, na_value = "grey80", name = NULL ) scale_fill_steps( plot, style = "quantile", n = 5, breaks = NULL, palette = NULL, labels = NULL, na_value = "grey80", name = NULL )scale_fill_binned( plot, style = "quantile", n = 5, breaks = NULL, palette = NULL, labels = NULL, na_value = "grey80", name = NULL ) scale_color_binned( plot, style = "quantile", n = 5, breaks = NULL, palette = NULL, labels = NULL, na_value = "grey80", name = NULL ) scale_color_steps( plot, style = "quantile", n = 5, breaks = NULL, palette = NULL, labels = NULL, na_value = "grey80", name = NULL ) scale_colour_steps( plot, style = "quantile", n = 5, breaks = NULL, palette = NULL, labels = NULL, na_value = "grey80", name = NULL ) scale_fill_steps( plot, style = "quantile", n = 5, breaks = NULL, palette = NULL, labels = NULL, na_value = "grey80", name = NULL )
plot |
A PlotSpec. |
style |
Classification style: one of |
n |
Number of classes (default |
breaks |
Explicit class boundaries (length = number of classes + 1),
overriding |
palette |
A sequential palette: |
labels |
Optional class labels (one per class); defaults to interval
ranges like |
na_value |
Fill colour for |
name |
Legend title, or |
scale_color_steps() / scale_fill_steps() are aliases of the binned colour
scales, for ggplot2 users who reach for the _steps name — a continuous
variable cut into steps with an interval-key legend.
The modified PlotSpec.
mark_sf(), scale_fill_continuous()
## Not run: nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) vplot(nc) |> mark_sf(fill = SID74) |> scale_fill_binned(style = "quantile", n = 5) |> coord_sf() ## End(Not run)## Not run: nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) vplot(nc) |> mark_sf(fill = SID74) |> scale_fill_binned(style = "quantile", n = 5) |> coord_sf() ## End(Not run)
Declare the scale for a mapped (discrete) linetype aesthetic. Levels cycle
through a default set of line types unless values is given. A line-type
legend is drawn automatically. Applies to line-like marks (mark_line(),
mark_step()).
scale_linetype(plot, values = NULL, name = NULL) scale_linetype_discrete(plot, values = NULL, name = NULL)scale_linetype(plot, values = NULL, name = NULL) scale_linetype_discrete(plot, values = NULL, name = NULL)
plot |
A PlotSpec. |
values |
Character vector of line types (each one of |
name |
Legend title, or |
The modified PlotSpec.
df <- data.frame(x = rep(1:10, 2), y = rnorm(20), g = rep(c("a", "b"), each = 10)) vplot(df) |> mark_line(x = x, y = y, linetype = g)df <- data.frame(x = rep(1:10, 2), y = rnorm(20), g = rep(c("a", "b"), each = 10)) vplot(df) |> mark_line(x = x, y = y, linetype = g)
Declare the scale for a mapped linewidth aesthetic on a stroked mark –
mark_line(), mark_step(), or mark_segment(). Data values are rescaled
linearly onto a line-width range (in lwd units, as everywhere else in the
package) and a line-width legend is drawn automatically.
scale_linewidth(plot, range = NULL, limits = NULL, breaks = NULL, name = NULL) scale_linewidth_continuous( plot, range = NULL, limits = NULL, breaks = NULL, name = NULL )scale_linewidth(plot, range = NULL, limits = NULL, breaks = NULL, name = NULL) scale_linewidth_continuous( plot, range = NULL, limits = NULL, breaks = NULL, name = NULL )
plot |
A PlotSpec. |
range |
Output line-width range |
limits |
Data limits |
breaks |
Explicit legend breaks, or |
name |
Legend title, or |
A mapped linewidth gives each segment one constant width, taken as the
mean of its two endpoint values. So the width changes in visible steps at each
vertex rather than tapering smoothly along the line, and the round joins do
not perfectly fill the corners of a sharp bend. That is inherent to
per-segment width; a constant linewidth = is unaffected and still draws the
line as a single stroke.
No backend can stroke the segments of one path at different widths in a single
call, so a mapped linewidth emits one path element per segment in SVG and
PDF. On a long, dense line that is a lot of elements – worth knowing before
mapping linewidth on tens of thousands of rows.
For edges on a vgraph() plot, use scale_edge_width() instead: an edge's
width is trained and legended independently of the line-width scale. That also
means guides(linewidth = ) and lims(linewidth = ) address this scale;
use guides(edge_width = ) / lims(edge_width = ) for a graph's edges.
A missing (NA) width takes its segment's width from whichever endpoint is
known, so one missing value thins the line rather than erasing the two
segments that meet at it. A segment missing a width at both ends is dropped.
The modified PlotSpec.
mark_line(), mark_step(), mark_segment(), scale_edge_width()
vplot(pressure) |> mark_line(x = temperature, y = pressure, linewidth = pressure) |> scale_linewidth(range = c(0.5, 5))vplot(pressure) |> mark_line(x = temperature, y = pressure, linewidth = pressure) |> scale_linewidth(range = c(0.5, 5))
Map a discrete variable to fill textures – the greyscale- and
colour-vision-safe companion of a fill palette – via a filled mark's pattern
aesthetic: mark_bar(x = g, y = n, pattern = series). Each level takes a
distinct pattern_stripe()-family texture. Applies to the filled marks (bar,
area, tile, rect, boxplot, violin, hull).
scale_pattern(plot, values = NULL, name = NULL)scale_pattern(plot, values = NULL, name = NULL)
plot |
A PlotSpec. |
values |
Optional textures, one per level: a character vector of builder
names ( |
name |
Optional legend title. |
The modified PlotSpec.
pattern_stripe(), scale_shape()
df <- data.frame(g = c("a", "b", "c"), n = c(3, 5, 2)) vplot(df) |> mark_bar(x = g, y = n, pattern = g) |> scale_pattern()df <- data.frame(g = c("a", "b", "c"), n = c(3, 5, 2)) vplot(df) |> mark_bar(x = g, y = n, pattern = g) |> scale_pattern()
Declare the scale for a mapped (discrete) shape aesthetic. Levels cycle
through a default set of marker shapes unless values is given. A shape legend
is drawn automatically.
scale_shape(plot, values = NULL, name = NULL)scale_shape(plot, values = NULL, name = NULL)
plot |
A PlotSpec. |
values |
Character vector of shapes, or |
name |
Legend title, or |
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg, shape = factor(cyl)) # SVG icon markers, one per level: star <- "M12 2l3 7h7l-5.5 4.5 2 7-6.5-4.5-6.5 4.5 2-7L2 9h7z" vplot(mtcars) |> mark_point(x = wt, y = mpg, shape = factor(cyl)) |> scale_shape(values = c(star, star, star))vplot(mtcars) |> mark_point(x = wt, y = mpg, shape = factor(cyl)) # SVG icon markers, one per level: star <- "M12 2l3 7h7l-5.5 4.5 2 7-6.5-4.5-6.5 4.5 2-7L2 9h7z" vplot(mtcars) |> mark_point(x = wt, y = mpg, shape = factor(cyl)) |> scale_shape(values = c(star, star, star))
Declare the scale for a mapped size aesthetic: data values map linearly to a
point-size range (in mm). A size legend is drawn automatically.
scale_size_area() maps the data value to the marker's area rather than
its radius, with value 0 at size 0 — the perceptually honest default for
bubble charts (a value twice as large looks twice as big in ink). max_size
is the size (mm) of the largest value.
scale_size(plot, range = NULL, limits = NULL, breaks = NULL, name = NULL) scale_size_area(plot, max_size = 6, limits = NULL, breaks = NULL, name = NULL)scale_size(plot, range = NULL, limits = NULL, breaks = NULL, name = NULL) scale_size_area(plot, max_size = 6, limits = NULL, breaks = NULL, name = NULL)
plot |
A PlotSpec. |
range |
Numeric length-2 output size range in mm, or |
limits |
Numeric length-2 data domain, or |
breaks |
Explicit legend breaks, or |
name |
Legend title, or |
max_size |
For |
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg, size = hp) |> scale_size(range = c(1, 8)) vplot(mtcars) |> mark_point(x = wt, y = mpg, size = hp) |> scale_size_area(max_size = 10)vplot(mtcars) |> mark_point(x = wt, y = mpg, size = hp) |> scale_size(range = c(1, 8)) vplot(mtcars) |> mark_point(x = wt, y = mpg, size = hp) |> scale_size_area(max_size = 10)
Named convenience constructors for popular palettes, easing migration from
ggplot2. They are thin wrappers over the palette = argument of
scale_color_continuous() / scale_color_discrete() (any
grDevices::hcl.colors() name works there directly).
scale_color_viridis_c( plot, option = "viridis", breaks = NULL, labels = NULL, name = NULL ) scale_color_viridis_d( plot, option = "viridis", breaks = NULL, labels = NULL, name = NULL ) scale_fill_viridis_c( plot, option = "viridis", breaks = NULL, labels = NULL, name = NULL ) scale_fill_viridis_d( plot, option = "viridis", breaks = NULL, labels = NULL, name = NULL ) scale_color_brewer( plot, palette = "Blues", breaks = NULL, labels = NULL, name = NULL ) scale_fill_brewer( plot, palette = "Blues", breaks = NULL, labels = NULL, name = NULL ) scale_color_distiller( plot, palette = "Blues", breaks = NULL, labels = NULL, name = NULL ) scale_fill_distiller( plot, palette = "Blues", breaks = NULL, labels = NULL, name = NULL ) scale_colour_viridis_c( plot, option = "viridis", breaks = NULL, labels = NULL, name = NULL ) scale_colour_viridis_d( plot, option = "viridis", breaks = NULL, labels = NULL, name = NULL ) scale_colour_brewer( plot, palette = "Blues", breaks = NULL, labels = NULL, name = NULL ) scale_colour_distiller( plot, palette = "Blues", breaks = NULL, labels = NULL, name = NULL )scale_color_viridis_c( plot, option = "viridis", breaks = NULL, labels = NULL, name = NULL ) scale_color_viridis_d( plot, option = "viridis", breaks = NULL, labels = NULL, name = NULL ) scale_fill_viridis_c( plot, option = "viridis", breaks = NULL, labels = NULL, name = NULL ) scale_fill_viridis_d( plot, option = "viridis", breaks = NULL, labels = NULL, name = NULL ) scale_color_brewer( plot, palette = "Blues", breaks = NULL, labels = NULL, name = NULL ) scale_fill_brewer( plot, palette = "Blues", breaks = NULL, labels = NULL, name = NULL ) scale_color_distiller( plot, palette = "Blues", breaks = NULL, labels = NULL, name = NULL ) scale_fill_distiller( plot, palette = "Blues", breaks = NULL, labels = NULL, name = NULL ) scale_colour_viridis_c( plot, option = "viridis", breaks = NULL, labels = NULL, name = NULL ) scale_colour_viridis_d( plot, option = "viridis", breaks = NULL, labels = NULL, name = NULL ) scale_colour_brewer( plot, palette = "Blues", breaks = NULL, labels = NULL, name = NULL ) scale_colour_distiller( plot, palette = "Blues", breaks = NULL, labels = NULL, name = NULL )
plot |
A PlotSpec. |
option |
Which viridis map (see above). |
name, breaks, labels
|
As for |
palette |
A |
scale_*_viridis_c() / scale_*_viridis_d() — the perceptually-uniform,
colour-vision-deficient-safe viridis maps, continuous (_c) or discrete
(_d). option picks the map: "viridis", "plasma", "inferno",
"cividis", "rocket", or "mako" (unknown options fall back to viridis).
scale_*_brewer() — a discrete ColorBrewer-style qualitative/sequential
palette; scale_*_distiller() — the same ramp interpolated for continuous
data. palette is any hcl.colors() name (e.g. "Blues", "Set 2").
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg, color = hp) |> scale_color_viridis_c() vplot(mtcars) |> mark_point(x = wt, y = mpg, color = factor(cyl)) |> scale_color_brewer(palette = "Set 2")vplot(mtcars) |> mark_point(x = wt, y = mpg, color = hp) |> scale_color_viridis_c() vplot(mtcars) |> mark_point(x = wt, y = mpg, color = factor(cyl)) |> scale_color_brewer(palette = "Set 2")
scale_x_binned() / scale_y_binned() cut a continuous position variable into
bins: axis ticks fall at the bin boundaries and each datum is drawn at its
bin centre. Breaks use the same classification as the binned colour scales
(style/n; classInt for jenks/fisher/… — a Suggest). Handy to summarise a
dense continuous axis, or to place mark_bar() on a binned continuous x.
scale_x_binned( plot, style = "pretty", n = 10, breaks = NULL, labels = NULL, name = NULL ) scale_y_binned( plot, style = "pretty", n = 10, breaks = NULL, labels = NULL, name = NULL )scale_x_binned( plot, style = "pretty", n = 10, breaks = NULL, labels = NULL, name = NULL ) scale_y_binned( plot, style = "pretty", n = 10, breaks = NULL, labels = NULL, name = NULL )
plot |
A PlotSpec. |
style |
Binning style: |
n |
Target number of bins. |
breaks |
Explicit bin boundaries (overrides |
labels |
Explicit boundary labels, or |
name |
Axis title, or |
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg) |> scale_x_binned(n = 6)vplot(mtcars) |> mark_point(x = wt, y = mpg) |> scale_x_binned(n = 6)
Declare a position scale to override the trained default. scale_x_continuous()
/ scale_y_continuous() handle numeric (and date/time) axes;
scale_x_discrete() / scale_y_discrete() handle categorical (band) axes and
let you set the level order via limits.
scale_x_continuous( plot, limits = NULL, trans = "identity", breaks = NULL, labels = NULL, name = NULL, expand = NULL, sec.axis = NULL ) scale_y_continuous( plot, limits = NULL, trans = "identity", breaks = NULL, labels = NULL, name = NULL, expand = NULL, sec.axis = NULL ) scale_x_discrete(plot, limits = NULL, name = NULL) scale_y_discrete(plot, limits = NULL, name = NULL)scale_x_continuous( plot, limits = NULL, trans = "identity", breaks = NULL, labels = NULL, name = NULL, expand = NULL, sec.axis = NULL ) scale_y_continuous( plot, limits = NULL, trans = "identity", breaks = NULL, labels = NULL, name = NULL, expand = NULL, sec.axis = NULL ) scale_x_discrete(plot, limits = NULL, name = NULL) scale_y_discrete(plot, limits = NULL, name = NULL)
plot |
A PlotSpec. |
limits |
For continuous scales a numeric length-2 domain |
trans |
Transformation: |
breaks, labels
|
Explicit break positions (data units) and their labels,
or |
name |
Axis title, or |
expand |
Axis padding beyond the data. |
sec.axis |
A secondary axis from |
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg) |> scale_x_continuous(limits = c(0, 6)) vplot(mtcars) |> mark_point(x = wt, y = mpg) |> scale_y_continuous(trans = "sqrt")vplot(mtcars) |> mark_point(x = wt, y = mpg) |> scale_x_continuous(limits = c(0, 6)) vplot(mtcars) |> mark_point(x = wt, y = mpg) |> scale_y_continuous(trans = "sqrt")
Position scales for Date (scale_*_date), date-time POSIXct
(scale_*_datetime), and time-of-day / difftime / hms
(scale_*_time) axes. A Date/POSIXct column already gets a sensible date
axis automatically; declare one of these to control the break interval or the
label format.
scale_x_date( plot, limits = NULL, date_breaks = NULL, date_labels = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_y_date( plot, limits = NULL, date_breaks = NULL, date_labels = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_x_datetime( plot, limits = NULL, date_breaks = NULL, date_labels = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_y_datetime( plot, limits = NULL, date_breaks = NULL, date_labels = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_x_time( plot, limits = NULL, date_breaks = NULL, date_labels = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_y_time( plot, limits = NULL, date_breaks = NULL, date_labels = NULL, breaks = NULL, labels = NULL, name = NULL )scale_x_date( plot, limits = NULL, date_breaks = NULL, date_labels = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_y_date( plot, limits = NULL, date_breaks = NULL, date_labels = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_x_datetime( plot, limits = NULL, date_breaks = NULL, date_labels = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_y_datetime( plot, limits = NULL, date_breaks = NULL, date_labels = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_x_time( plot, limits = NULL, date_breaks = NULL, date_labels = NULL, breaks = NULL, labels = NULL, name = NULL ) scale_y_time( plot, limits = NULL, date_breaks = NULL, date_labels = NULL, breaks = NULL, labels = NULL, name = NULL )
plot |
A PlotSpec. |
limits |
Length-2 vector giving the axis range (same class as the data),
or |
date_breaks |
A break interval string, e.g. |
date_labels |
A |
breaks, labels
|
Explicit break positions / labels (override
|
name |
Axis title, or |
The modified PlotSpec.
df <- data.frame(day = as.Date("2020-01-01") + 0:364, y = cumsum(rnorm(365))) vplot(df) |> mark_line(x = day, y = y) |> scale_x_date(date_breaks = "3 months", date_labels = "%b %Y")df <- data.frame(day = as.Date("2020-01-01") + 0:364, y = cumsum(rnorm(365))) vplot(df) |> mark_line(x = day, y = y) |> scale_x_date(date_breaks = "3 months", date_labels = "%b %Y")
Add a secondary axis to a continuous position scale: a second set of ticks and
labels on the opposite edge (top for x, right for y), computed as a 1:1
monotonic transform of the primary axis. Pass the result to the sec.axis
argument of scale_x_continuous() / scale_y_continuous(). This is a
labelling convenience (unit conversions, count/proportion dual readouts,
duplicating an axis on a wide plot) — not an independent second axis with
its own data.
sec_axis(transform = ~., name = NULL, breaks = NULL, labels = NULL) dup_axis(transform = ~., name = NULL, breaks = NULL, labels = NULL)sec_axis(transform = ~., name = NULL, breaks = NULL, labels = NULL) dup_axis(transform = ~., name = NULL, breaks = NULL, labels = NULL)
transform |
The primary-to-secondary mapping: a formula using |
name |
Secondary axis title, or |
breaks |
Break positions in secondary units, or |
labels |
A character vector of labels (one per break) or a labelling
function, or |
sec_axis() maps the primary axis through transform; dup_axis() is the
identity special case (a plain duplicate) with tidy defaults.
A SecAxisSpec to pass to sec.axis.
Secondary axes are supported only on continuous position scales under the
default Cartesian coordinate system, with shared scales across facets.
Combining sec.axis with coord_flip() / coord_polar() / coord_trans(),
with free facet scales, or with add_marginal() raises an error. In a plot
composition (| / /) the secondary axis is not drawn.
# Celsius with a Fahrenheit axis on top vplot(data.frame(t = 0:100, y = (0:100)^2)) |> mark_line(x = t, y = y) |> scale_x_continuous(name = "°C", sec.axis = sec_axis(~ . * 1.8 + 32, name = "°F")) # Duplicate the y axis on the right vplot(mtcars) |> mark_point(x = wt, y = mpg) |> scale_y_continuous(sec.axis = dup_axis())# Celsius with a Fahrenheit axis on top vplot(data.frame(t = 0:100, y = (0:100)^2)) |> mark_line(x = t, y = y) |> scale_x_continuous(name = "°C", sec.axis = sec_axis(~ . * 1.8 + 32, name = "°F")) # Duplicate the y axis on the right vplot(mtcars) |> mark_point(x = wt, y = mpg) |> scale_y_continuous(sec.axis = dup_axis())
A network-aware select_point() preset for vgraph() plots: pointing at (or
clicking) a node selects its neighbourhood — the node, its incident edges,
and its adjacent nodes — so a host spotlights them and dims the rest. Pointing
at an edge highlights the edge and its two endpoint nodes. It builds on the
node/edge identity vgraph() emits for an interactive plot (each node keyed by
its vertex name, each edge carrying its endpoint names); the host
reconstructs the adjacency and projects the gesture across it.
select_neighbours( plot, name = "neighbours", on = c("hover", "click"), degree = 1L, edges = TRUE, empty = TRUE )select_neighbours( plot, name = "neighbours", on = c("hover", "click"), degree = 1L, edges = TRUE, empty = TRUE )
plot |
A PlotSpec, normally from |
name |
The selection name. Defaults to |
on |
The gesture: |
degree |
How many hops out from the pointed node to include ( |
edges |
Whether to include the incident edges in the highlight
( |
empty |
Whether an empty selection matches all elements ( |
Like the other selections it is inert on a static render and enacted by a
capable host (vellumwidget). On its own it spotlights the neighbourhood; pair
it with condition() to restyle members explicitly, or filter_by() to show
only the neighbourhood.
A PlotSpec (piped form) or a SelectionSpec (free-standing form).
select_point(), condition(), vgraph(), mark_edges()
## Not run: g <- igraph::make_graph("Zachary") vgraph(g) |> mark_edges() |> mark_nodes(size = 3) |> select_neighbours(on = "hover") ## End(Not run)## Not run: g <- igraph::make_graph("Zachary") vgraph(g) |> mark_edges() |> mark_nodes(size = 3) |> select_neighbours(on = "hover") ## End(Not run)
A selection is a named set of data elements defined by a user gesture. On
its own it does nothing visible; refer to it from condition() (style by
membership), filter_by() (show only members), or bind_scale() (drive
another panel's view). Selections are part of the plot spec, so they travel
with it, serialise with it, and are enacted by any capable host
(vellumwidget). They are inert on a static render.
select_point( plot, name, on = c("click", "hover"), fields = NULL, group_by = NULL, toggle = TRUE, empty = TRUE ) select_interval( plot, name, on = c("xy", "x", "y"), region = c("rect", "lasso"), empty = TRUE )select_point( plot, name, on = c("click", "hover"), fields = NULL, group_by = NULL, toggle = TRUE, empty = TRUE ) select_interval( plot, name, on = c("xy", "x", "y"), region = c("rect", "lasso"), empty = TRUE )
plot |
A PlotSpec (piped form), or a selection name string (free-standing form). |
name |
The selection name (piped form) — a string other nodes reference. |
on |
The gesture. Point: |
fields |
For a point selection, the column name(s) whose match extends
membership: clicking one element selects every row equal to it on these
fields (e.g. |
group_by |
Alias for |
toggle |
For a point selection, whether clicking toggles membership
( |
empty |
Whether an empty selection contains all elements ( |
region |
For an interval selection, |
select_point() is driven by a click or hover (or a legend value);
select_interval() by a drag (a brush rectangle or a lasso), optionally locked
to an axis.
Both are pipe-first (attach to the plot and return it) or free-standing
(call with the name as the first argument to get a SelectionSpec you can share
across views, then attach with add_selection()).
A PlotSpec (piped form) or a SelectionSpec (free-standing form).
condition(), filter_by(), add_selection(), bind_scale()
df <- data.frame(x = 1:10, y = runif(10), g = rep(c("a", "b"), 5)) # highlight on hover (piped) vplot(df) |> mark_point(x = x, y = y, color = condition("hi", g, "grey80")) |> select_point("hi", on = "hover") # free-standing, for cross-view use sel <- select_interval("brush", on = "x")df <- data.frame(x = 1:10, y = runif(10), g = rep(c("a", "b"), 5)) # highlight on hover (piped) vplot(df) |> mark_point(x = x, y = y, color = condition("hi", g, "grey80")) |> select_point("hi", on = "hover") # free-standing, for cross-view use sel <- select_interval("brush", on = "x")
Draws dark, low-opacity copies of a stroked or point mark beneath the
original, offset by (x, y) and softened by stacking a few widened copies —
a drop shadow (with an offset) or an ambient shadow (offset 0). Applies to
the same marks as glow().
shadow( x = 0.5, y = -0.5, color = "black", alpha = 0.3, spread = 1.5, layers = 3L )shadow( x = 0.5, y = -0.5, color = "black", alpha = 0.3, spread = 1.5, layers = 3L )
x, y
|
Shadow offset in millimetres ( |
color |
Shadow colour. |
alpha |
Opacity of each copy. |
spread |
Softening spread, in millimetres, over which the copies widen. |
layers |
Number of stacked copies (more = softer). |
The offset is an absolute distance in millimetres (+x right, +y up),
resolved device-side, so a drop shadow stays the same physical distance and is
isotropic regardless of the panel's size or aspect (via vellum's compound
npc + mm unit).
A ShadowSpec object for a mark's effects list.
df <- data.frame(x = 1:20, y = cumsum(rnorm(20))) vplot(df) |> mark_line(x = x, y = y, effects = list(shadow()))df <- data.frame(x = 1:20, y = cumsum(rnorm(20))) vplot(df) |> mark_line(x = x, y = y, effects = list(shadow()))
A re-export of vellum::sketch() — the one vocabulary vellumplot speaks for the
hand-drawn look (wobbly outlines, hachure fills, à la
Rough.js). Pass a sketch() value to any mark's
sketch = argument, to an element_line() / element_rect() sketch =
slot, or set it plot-wide with theme_sketch():
sketch(...)sketch(...)
... |
Sketch parameters passed straight to |
vplot(mpg) |> mark_point(x = displ, y = hwy, sketch = sketch(roughness = 1.2))
Sketch is a geometry property, not a layer effect: it perturbs the
mark itself (its wobble is generated natively in the vellum engine, so it is
exact, cross-backend, and works in PDF), rather than compositing extra copies.
Text is never sketched — pair a handwriting family with it for a fully
hand-drawn plot.
Resolution is most-specific-wins: a mark's sketch = beats an element slot,
which beats the plot-wide theme_sketch() default. At any level sketch = NA
(or FALSE) forces that element crisp, overriding a broader default;
sketch = NULL inherits.
A vellum_sketch object.
theme_sketch(), mark_point(), element_line()
vplot(mtcars) |> mark_point(x = wt, y = mpg, sketch = sketch(roughness = 1.5, seed = 7))vplot(mtcars) |> mark_point(x = wt, y = mpg, sketch = sketch(roughness = 1.5, seed = 7))
spec_diagnose() checks a spec (a list, JSON string, or path) without
throwing: it parses it, validates every referenced field against the data,
and dry-run compiles it, returning a structured verdict. vplot_from_spec()
is the strict form — it returns the PlotSpec on success and raises a classed
vellumplot_spec_invalid error (carrying the same diagnostics) on failure.
spec_diagnose(spec, data = NULL, env = globalenv()) vplot_from_spec(spec, data = NULL, env = globalenv())spec_diagnose(spec, data = NULL, env = globalenv()) vplot_from_spec(spec, data = NULL, env = globalenv())
spec |
A spec list (from |
data |
The data frame the spec is drawn from. Required when the spec stores data by reference; optional (for field validation) when inlined. |
env |
Environment channel expressions are re-quoted in. |
This is the agent repair loop: a failure comes back as data an agent can act on (which field is unknown, the nearest real field) rather than a traceback.
spec_diagnose() returns a list with ok (logical), plot (the
PlotSpec or NULL), and diagnostics (a list of records with severity,
field, message, hint). vplot_from_spec() returns a PlotSpec.
spec_fields(), spec_schema(), vplot_ask()
spec <- as_spec(vplot(mtcars) |> mark_point(x = wt, y = mpg)) d <- spec_diagnose(spec, data = mtcars) d$okspec <- as_spec(vplot(mtcars) |> mark_point(x = wt, y = mpg)) d <- spec_diagnose(spec, data = mtcars) d$ok
spec_fields() returns one row per column of data with its name, inferred
encoding type (quantitative / nominal / ordinal / temporal), R
class, distinct-value count, and a few example values. It is the grounding
step for LLM plot generation (vplot_ask(), the MCP list_fields tool):
handing a model the real vocabulary up front is what prevents hallucinated
column names, and vplot_from_spec() then validates against exactly these.
spec_fields(data, n_examples = 3L)spec_fields(data, n_examples = 3L)
data |
A data frame. |
n_examples |
How many example values to show per field (default 3). |
A data frame with columns name, type, class, n_unique,
examples.
vplot_from_spec(), spec_schema()
spec_fields(mtcars)spec_fields(mtcars)
Returns the bundled JSON Schema (Draft 2020-12) describing a serializable
vellumplot spec — the input contract for spec_from_json() and the MCP
render_spec / get_schema tools. An agent can validate a generated spec
against it before rendering.
spec_schema(as = c("string", "list", "path"))spec_schema(as = c("string", "list", "path"))
as |
A character scalar: |
The schema as a string, a list, or a file path.
schema <- spec_schema(as = "list") schema$titleschema <- spec_schema(as = "list") schema$title
spec_to_json() renders a PlotSpec as a JSON string (via as_spec());
spec_from_json() parses one back into a PlotSpec (via from_spec()). This
is the portable wire format for the LLM / agent tooling and the Vega-Lite
bridge. See as_spec() for the serializable subset and its guarantees.
spec_to_json(plot, pretty = TRUE) spec_from_json(json, data = NULL, env = globalenv())spec_to_json(plot, pretty = TRUE) spec_from_json(json, data = NULL, env = globalenv())
plot |
A PlotSpec. |
pretty |
Whether to pretty-print (default |
json |
A JSON spec string (or a path to a |
data, env
|
Passed to |
spec_to_json() returns a length-1 JSON string; spec_from_json()
returns a PlotSpec.
as_spec(), spec_schema(), vplot_from_spec()
p <- vplot(mtcars) |> mark_point(x = wt, y = mpg) json <- spec_to_json(p) p2 <- spec_from_json(json)p <- vplot(mtcars) |> mark_point(x = wt, y = mpg) json <- spec_to_json(p) p2 <- spec_from_json(json)
spec_to_vegalite() translates a PlotSpec into a
Vega-Lite specification;
spec_from_vegalite() translates one back. Both are layered grammars of
graphics, so the mapping is direct for the common cases — marks, encodings,
scales (domain / log-sqrt type / categorical range / title), bin +
count, faceting, inline data, and the plot title.
spec_to_vegalite(plot, json = FALSE) spec_from_vegalite(vl, data = NULL, env = globalenv())spec_to_vegalite(plot, json = FALSE) spec_from_vegalite(vl, data = NULL, env = globalenv())
plot |
A PlotSpec. |
json |
For |
vl |
A Vega-Lite spec as a parsed list or a JSON string. |
data |
Optional data frame for a Vega-Lite spec whose data is external. |
env |
Environment channel expressions are re-quoted in (for
|
The bridge covers a documented subset (see the "Specs, agents, and interoperability" article). Anything it cannot map — polar/flipped coordinates, layer effects, patterns, statistical marks without a Vega-Lite equivalent — is reported via a warning listing the dropped features, never silently diverged.
spec_to_vegalite() returns a Vega-Lite spec (a list, or JSON string
if json = TRUE); spec_from_vegalite() returns a PlotSpec.
p <- vplot(mtcars) |> mark_point(x = wt, y = mpg, color = cyl) vl <- spec_to_vegalite(p) vl$markp <- vplot(mtcars) |> mark_point(x = wt, y = mpg, color = cyl) vl <- spec_to_vegalite(p) vl$mark
Control the non-data look of a plot. theme_gray() is the default (grey panel,
white gridlines); theme_minimal() drops the panel fill for light gridlines on
the page; theme_bw() is a white panel with light grey gridlines;
theme_classic() has axis lines and no gridlines; theme_void() strips
everything but the marks, legend, and titles; theme_cyberpunk() is a dark
neon theme (see Details).
theme_gray(plot) theme_minimal(plot) theme_bw(plot) theme_classic(plot) theme_void(plot) theme_light(plot) theme_dark(plot) theme_linedraw(plot) theme_cyberpunk(plot) theme(plot, ...) set_theme( plot, panel_bg = NULL, grid_col = NULL, label_col = NULL, strip_bg = NULL )theme_gray(plot) theme_minimal(plot) theme_bw(plot) theme_classic(plot) theme_void(plot) theme_light(plot) theme_dark(plot) theme_linedraw(plot) theme_cyberpunk(plot) theme(plot, ...) set_theme( plot, panel_bg = NULL, grid_col = NULL, label_col = NULL, strip_bg = NULL )
plot |
A PlotSpec. |
... |
Named theme elements, e.g. |
panel_bg, grid_col, label_col, strip_bg
|
Colours (or |
theme() overrides individual elements on top of the current theme using
element_text() / element_line() / element_rect() / element_blank().
set_theme() is a small back-compatible shortcut for the most common colours.
theme_cyberpunk() sets a dark canvas with dim neon gridlines and a bright
neon default palette (both discrete and continuous), in the spirit of
mplcyberpunk. It pairs with the
glow() layer effect and linear_gradient() fills for the full neon look;
the palette is only a default, so scale_* overrides still win.
The modified PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg) |> theme_minimal() vplot(mtcars) |> mark_point(x = wt, y = mpg) |> theme(panel.grid.minor = element_blank(), legend.position = "none")vplot(mtcars) |> mark_point(x = wt, y = mpg) |> theme_minimal() vplot(mtcars) |> mark_point(x = wt, y = mpg) |> theme(panel.grid.minor = element_blank(), legend.position = "none")
theme_sketch() turns a whole plot hand-drawn in one line: it sets a
plot-wide sketch() default that every geometry mark and theme element
inherits (wobbly gridlines, axis lines, ticks, and marks), on a warm
paper-toned background. Text is never sketched — pass a handwriting font to
complete the look.
theme_sketch( plot, roughness = 1, bowing = 1, fill_style = "hachure", seed = 1L, font = NULL, paper = "#f4ecd8", ink = "#2b2b2b" )theme_sketch( plot, roughness = 1, bowing = 1, fill_style = "hachure", seed = 1L, font = NULL, paper = "#f4ecd8", ink = "#2b2b2b" )
plot |
A PlotSpec. |
roughness, bowing, fill_style, seed
|
Passed to |
font |
Font family for all text (text is not sketched; a handwriting font
such as |
paper, ink
|
Background and foreground (text/line) colours. |
It is a complete theme (like theme_cyberpunk()): the sketch it sets is only
a default, so any mark's sketch = argument, any element_line() /
element_rect() sketch = slot, or a scale_* override still wins. Force an
individual element crisp with sketch = NA.
The modified PlotSpec.
sketch(), theme_gray(), mark_point()
vplot(mtcars) |> mark_point(x = wt, y = mpg, color = factor(cyl)) |> theme_sketch() # tune the wobble; a crosshatch-filled bar layer that stays crisp df <- data.frame(g = c("a", "b", "c"), n = c(3, 5, 2)) vplot(df) |> mark_bar(x = g, y = n, fill = g) |> theme_sketch(roughness = 1.4, fill_style = "crosshatch", seed = 7)vplot(mtcars) |> mark_point(x = wt, y = mpg, color = factor(cyl)) |> theme_sketch() # tune the wobble; a crosshatch-filled bar layer that stays crisp df <- data.frame(g = c("a", "b", "c"), n = c(3, 5, 2)) vplot(df) |> mark_bar(x = g, y = n, fill = g) |> theme_sketch(roughness = 1.4, fill_style = "crosshatch", seed = 7)
transition_reveal() wipes the plot into view left to right — the classic
"line draws itself" animation. Unlike transition_states(), it does not tween
between states: the full plot is compiled and a clip rectangle grows across the
panel, revealing the marks in along order. Best for a line or path over a
continuous along (typically the x variable, e.g. time).
transition_reveal(plot, along)transition_reveal(plot, along)
plot |
|
along |
The variable the reveal follows (mapped to x, increasing left to right). |
The modified PlotSpec.
transition_states(), transition_time(), animate()
vplot(data.frame(t = 1:20, y = cumsum(rnorm(20)))) |> mark_line(x = t, y = y) |> transition_reveal(t)vplot(data.frame(t = 1:20, y = cumsum(rnorm(20)))) |> mark_line(x = t, y = y) |> transition_reveal(t)
transition_states() turns a plot into a keyframe animation: the plot is
compiled once per level of states (a "keyframe"), and animate() tweens the
frames between successive keyframes. The scales are trained once over all
states and frozen, so axis breaks, colour ramps and sizes stay put across the
whole animation (the interpolation is non-reactive: the states are fixed at
author time, nothing retrains in response to anything).
transition_states( plot, states, transition_length = 1, state_length = 1, wrap = TRUE )transition_states( plot, states, transition_length = 1, state_length = 1, wrap = TRUE )
plot |
|
states |
A column (bare or a string) whose distinct values, in level order, are the animation's states. |
transition_length |
Relative duration of the moving segments between states. |
state_length |
Relative duration of the held pause on each state. |
wrap |
Loop the last state back to the first? |
The step only records the intent; call animate() to build the animation and
anim_save() to write it. A plain (non-animated) render ignores it.
The modified PlotSpec.
ease_aes(), animate(), anim_save()
if (requireNamespace("gapminder", quietly = TRUE)) { library(gapminder) p <- vplot(gapminder) |> mark_point(x = gdpPercap, y = lifeExp, size = pop, color = continent) |> scale_x_continuous(trans = "log10") |> transition_states(year) }if (requireNamespace("gapminder", quietly = TRUE)) { library(gapminder) p <- vplot(gapminder) |> mark_point(x = gdpPercap, y = lifeExp, size = pop, color = continent) |> scale_x_continuous(trans = "log10") |> transition_states(year) }
transition_time() is like transition_states() but treats time as a
continuous quantity: the states are its distinct values and each transition is
allocated frames in proportion to its time gap, so the animation plays at a
constant rate through unevenly spaced times. There is no pause on a state and no
wrap — time flows once, start to finish.
transition_time(plot, time)transition_time(plot, time)
plot |
|
time |
A numeric column giving each row's time. |
The modified PlotSpec.
transition_states(), ease_aes(), animate()
if (requireNamespace("gapminder", quietly = TRUE)) { vplot(gapminder::gapminder) |> mark_point(x = gdpPercap, y = lifeExp, size = pop, color = continent) |> scale_x_continuous(trans = "log10") |> transition_time(year) }if (requireNamespace("gapminder", quietly = TRUE)) { vplot(gapminder::gapminder) |> mark_point(x = gdpPercap, y = lifeExp, size = pop, color = continent) |> scale_x_continuous(trans = "log10") |> transition_time(year) }
vchord() draws a weighted flow as a circular chord diagram: one arc
(sector) per node, sized by the node's total incident weight, and one ribbon
per flow joining a slice of the source sector to a slice of the target sector
through the centre. Input is a flow list – from, to, value – or a
square flow matrix (row = from, column = to; dimnames are the node names).
Like vgraph() / vsankey() it returns a ready, axis-free, aspect-locked
PlotSpec; mark_chord() is the layer it adds.
vchord( data, from, to, value, gap = 0.02, sort = c("input", "value"), link_color = c("source", "target"), direction = c("gradient", "gap", "both", "none"), label = TRUE, width = 6, height = 6, dpi = 96 ) mark_chord( plot, from, to, value, gap = 0.02, sort = c("input", "value"), link_color = c("source", "target"), direction = c("gradient", "gap", "both", "none"), label = TRUE )vchord( data, from, to, value, gap = 0.02, sort = c("input", "value"), link_color = c("source", "target"), direction = c("gradient", "gap", "both", "none"), label = TRUE, width = 6, height = 6, dpi = 96 ) mark_chord( plot, from, to, value, gap = 0.02, sort = c("input", "value"), link_color = c("source", "target"), direction = c("gradient", "gap", "both", "none"), label = TRUE )
data |
A data frame of flows, or a square numeric matrix (row = from, column = to). |
from, to, value
|
Columns (tidy-eval) for the data-frame form: the source node, target node, and flow weight. Omit for the matrix form. |
gap |
Gap between sectors, as a fraction of the circle each (default
|
sort |
Sector and ribbon order: |
link_color |
Colour ribbons by their |
direction |
How to show a ribbon's direction: |
label |
Label each sector with its node name? Default |
width, height, dpi
|
Page size (inches) and resolution. |
plot |
A PlotSpec. |
Flows are directed: each node's arc splits into an outgoing block then an
incoming block, so a -> b and b -> a are separate ribbons and a self-flow
a -> a loops from the node's out-block to its own in-block. Sectors are
coloured by node (a qualitative palette); ribbons take their source node's
colour by default (link_color = "target" to colour by target).
A PlotSpec (vchord()) or the modified plot (mark_chord()).
flows <- data.frame( from = c("A", "A", "B", "C"), to = c("B", "C", "C", "A"), value = c(3, 2, 4, 1) ) vchord(flows, from, to, value)flows <- data.frame( from = c("A", "A", "B", "C"), to = c("B", "C", "C", "A"), value = c(3, 2, 4, 1) ) vchord(flows, from, to, value)
vdendrogram() turns a base hclust/dendrogram (e.g. from stats::hclust())
into a ready node-link dendrogram: leaves spread along a line, each merge drawn
at its height, joined by right-angle brackets. It is a thin preset over
vgraph(<clustering>, layout = "dendrogram") plus bracket edges and leaf
labels; for full control, use that path and add marks yourself.
vdendrogram( x, direction = c("down", "up", "left", "right"), k = NULL, labels = TRUE, label_size = 5, width = 7, height = 5, dpi = 96 )vdendrogram( x, direction = c("down", "up", "left", "right"), k = NULL, labels = TRUE, label_size = 5, width = 7, height = 5, dpi = 96 )
x |
An |
direction |
Growth direction (leaves opposite the root): |
k |
Optionally cut the tree into |
labels |
Draw the leaf labels? Default |
label_size |
Leaf-label font size (points). Default |
width, height, dpi
|
Page size (inches) and resolution. |
A PlotSpec.
vgraph() for the general node-link path (layout = "dendrogram"
or "unrooted").
hc <- hclust(dist(USArrests)) vdendrogram(hc, k = 3)hc <- hclust(dist(USArrests)) vdendrogram(hc, k = 3)
vgraph() begins a node-link diagram from an igraph graph. It computes a
layout (vertex x/y), builds a node table and an edge table, and returns a
PlotSpec with the aspect locked (coord_equal) and a void theme (no axes or
gridlines) – publication-quality defaults with no tuning. Add layers with
mark_edges(), mark_nodes(), and mark_node_text(); edges default to the
edge table and nodes to the node table.
vgraph( g, layout = "stress", ..., augment = FALSE, filter_nodes = NULL, filter_edges = NULL, k_core = NULL, seed = 42L, width = 6, height = 4, dpi = 96 )vgraph( g, layout = "stress", ..., augment = FALSE, filter_nodes = NULL, filter_edges = NULL, k_core = NULL, seed = 42L, width = 6, height = 4, dpi = 96 )
g |
An |
layout |
A layout: a name ( |
... |
Extra arguments forwarded to the layout function (e.g. |
augment |
Opt-in vertex metrics to attach as graph attributes (so they
can be mapped – |
filter_nodes, filter_edges
|
Data-masked predicates that keep the vertices
/ edges for which they are |
k_core |
Keep only the k-core: vertices with coreness |
seed |
Integer seed for stochastic layouts ( |
width, height
|
Page size in inches. |
dpi |
Output resolution in dots per inch (see |
The default layout is stress majorization
(graphlayouts::layout_with_stress): it is deterministic (same graph -> same
picture) and minimizes the difference between drawn and graph-theoretic
distance. Above 10^4 nodes it falls back to sparse stress automatically.
Reciprocal and parallel edges are drawn as parallel straight lines offset off
the centre line (not curved); self-loops as small loops.
igraph (and graphlayouts, for its layouts) are optional dependencies (in
Suggests); vgraph() errors with an install hint if they are not available.
Reductions apply in a fixed order: augment (metrics computed on the input
graph) -> filter_edges -> filter_nodes -> k_core. Augmented metrics thus
reflect the input graph, not the post-filter subgraph.
A PlotSpec whose data is the node table and whose edge_data is the
edge table.
mark_edges(), mark_nodes(), mark_node_text()
## Not run: g <- igraph::make_graph("Zachary") vgraph(g, layout = "stress") |> mark_edges() |> mark_nodes(size = 3) # attach degree, then plot only the 2-core, sized by degree vgraph(g, augment = TRUE, k_core = 2) |> mark_edges() |> mark_nodes(size = degree) ## End(Not run)## Not run: g <- igraph::make_graph("Zachary") vgraph(g, layout = "stress") |> mark_edges() |> mark_nodes(size = 3) # attach degree, then plot only the 2-core, sized by degree vgraph(g, augment = TRUE, k_core = 2) |> mark_edges() |> mark_nodes(size = degree) ## End(Not run)
vhierarchy() draws a tree as a space-filling diagram, choosing the geometry
with type: "sunburst" (concentric ring sectors), "icicle" (rectangular
partition), "treemap" (squarified nested rectangles), or "circlepack"
(circles within circles). All four take the same parent list — id,
parent (NA/"" at the root), and value (leaf values; an internal node's
value is the sum of its children) — so switching type re-encodes the same
data. Like vgraph() / vsankey() it returns a ready, axis-free,
aspect-locked PlotSpec; mark_hierarchy() is the layer it adds.
vhierarchy( data, id, parent, value, fill = NULL, type = c("sunburst", "icicle", "treemap", "circlepack"), inner_radius = 0, flow = c("down", "up", "right", "left"), lighten = 0.6, label = TRUE, show_values = FALSE, orientation = c("auto", "radial", "tangential", "horizontal"), root_label = FALSE, width = 6, height = 6, dpi = 96 ) mark_hierarchy( plot, id, parent, value, fill = NULL, type = c("sunburst", "icicle", "treemap", "circlepack"), inner_radius = 0, flow = c("down", "up", "right", "left"), lighten = 0.6, label = TRUE, show_values = FALSE, orientation = c("auto", "radial", "tangential", "horizontal"), root_label = FALSE )vhierarchy( data, id, parent, value, fill = NULL, type = c("sunburst", "icicle", "treemap", "circlepack"), inner_radius = 0, flow = c("down", "up", "right", "left"), lighten = 0.6, label = TRUE, show_values = FALSE, orientation = c("auto", "radial", "tangential", "horizontal"), root_label = FALSE, width = 6, height = 6, dpi = 96 ) mark_hierarchy( plot, id, parent, value, fill = NULL, type = c("sunburst", "icicle", "treemap", "circlepack"), inner_radius = 0, flow = c("down", "up", "right", "left"), lighten = 0.6, label = TRUE, show_values = FALSE, orientation = c("auto", "radial", "tangential", "horizontal"), root_label = FALSE )
data |
A data frame describing a hierarchy (a parent list). |
id, parent, value
|
Columns (tidy-eval): the node id, its parent id
( |
fill |
Optional column (tidy-eval) to colour nodes by. Unmapped
(default), nodes are coloured by their depth-1 branch and lightened with
depth; mapped, each node takes its |
type |
Diagram geometry: |
inner_radius |
Sunburst only: central hole radius, a fraction in
|
flow |
Icicle only: the direction of increasing depth — |
lighten |
Branch mode only: how far the deepest level fades toward white,
a fraction in |
label |
Label each node with its |
show_values |
Append each node's value to its label, e.g. |
orientation |
Sunburst labels only: |
root_label |
Write the root's name (and, with |
width, height, dpi
|
Page size (inches) and resolution. |
plot |
A PlotSpec. |
The root is structural and never drawn (in a sunburst it is the centre). Each
node is labelled with its id where the label fits, and show_values appends
the value; small nodes are left unlabelled so a dense diagram stays legible.
A PlotSpec (vhierarchy()) or the modified plot (mark_hierarchy()).
By default nodes are coloured by their depth-1 branch and lightened one step
per level, so sibling branches stay distinct and depth reads as shade. The
branch is an ordinary discrete fill scale, so scale_fill_*() recolours the
branches (e.g. scale_fill_brewer()), and lighten controls the depth fade
(0 = flat colour per branch). Map fill to a node column instead to colour
every node by that variable — discrete or continuous, with the matching
scale_fill_*() — in which case the depth fade is not applied.
h <- data.frame( id = c("root", "A", "B", "A1", "A2", "B1"), parent = c(NA, "root", "root", "A", "A", "B"), value = c(NA, NA, NA, 3, 2, 4) ) vhierarchy(h, id, parent, value, show_values = TRUE) vhierarchy(h, id, parent, value, type = "treemap")h <- data.frame( id = c("root", "A", "B", "A1", "A2", "B1"), parent = c(NA, "root", "root", "A", "A", "B"), value = c(NA, NA, NA, 3, 2, 4) ) vhierarchy(h, id, parent, value, show_values = TRUE) vhierarchy(h, id, parent, value, type = "treemap")
A thin re-export of vellum::vl_pattern() for building a pattern fill from an
arbitrary tile grob, when the ready-made pattern_stripe() family does not fit.
Like a gradient, the result is an unscaled fill value.
vl_pattern( grob, width = 0.1, height = 0.1, x = 0.5, y = 0.5, units = "npc", extend = "repeat" )vl_pattern( grob, width = 0.1, height = 0.1, x = 0.5, y = 0.5, units = "npc", extend = "repeat" )
grob, width, height, x, y, units, extend
|
See |
A vellum_pattern object usable as a fill value.
pattern_stripe(), linear_gradient()
dots <- vellum::circle_grob(r = 0.25, gp = vellum::vl_gpar(fill = "grey30")) vl_pattern(dots, width = 0.08, height = 0.08)dots <- vellum::circle_grob(r = 0.25, gp = vellum::vl_gpar(fill = "grey30")) vl_pattern(dots, width = 0.08, height = 0.08)
vplot() begins a declarative, pipe-first plot. It captures the data and
page size and returns an inspectable PlotSpec; nothing is drawn until the
spec is compiled (via render_plot() or vellum::as_vellum_scene()). Build
the plot up with mark_point() / mark_line() / mark_rule() and the
scale_*() functions.
vplot(data, width = 6, height = 4, dpi = 96)vplot(data, width = 6, height = 4, dpi = 96)
data |
A data frame. Encoding expressions in |
width, height
|
Page size in inches. |
dpi |
Output resolution in dots per inch. The exported PNG's pixel
dimensions are |
A PlotSpec.
vplot(mtcars) |> mark_point(x = wt, y = mpg)vplot(mtcars) |> mark_point(x = wt, y = mpg)
vplot_ask() is a thin, model-agnostic convenience: it assembles the
grounding payload (the JSON spec_schema() plus spec_fields() for data
and the user's prompt), hands it to a responder function you supply — any
function that takes the payload and returns a JSON spec string (wrapping the
Claude API, an MCP client, a local model, or a canned fixture) — and validates
the result with vplot_from_spec().
vplot_ask(prompt, data, responder, env = globalenv())vplot_ask(prompt, data, responder, env = globalenv())
prompt |
A natural-language description of the desired plot. |
data |
The data frame to plot. |
responder |
A function |
env |
Environment channel expressions are re-quoted in. |
vellumplot deliberately ships no built-in model client: the value is the
schema, the grounding, and the validated repair loop, not a hard dependency on
one provider. For a ready-to-run agent integration, point an MCP client at the
bundled server (system.file("mcp/server.R", package = "vellumplot")).
A PlotSpec.
spec_fields(), vplot_from_spec(), spec_schema()
# a canned responder standing in for a model call: responder <- function(payload) { spec_to_json(vplot(mtcars) |> mark_point(x = wt, y = mpg)) } p <- vplot_ask("scatter of weight vs mpg", mtcars, responder)# a canned responder standing in for a model call: responder <- function(payload) { spec_to_json(vplot(mtcars) |> mark_point(x = wt, y = mpg)) } p <- vplot_ask("scatter of weight vs mpg", mtcars, responder)
vsankey() draws a layered flow diagram from a flow list — one row per
flow with a from node, a to node, and a value (the ribbon width). Nodes
are the union of from/to; a node that is both a source and a target makes
the diagram multi-stage. Like vgraph(), it returns a ready PlotSpec with an
axis-free, aspect-free panel; mark_sankey() is the layer it adds and can be
used directly on a plot you have set up yourself.
vsankey( data, from, to, value, label = TRUE, show_values = FALSE, flow_color = "source", node_width = 0.04, node_gap = 0.02, width = 8, height = 5, dpi = 96 ) mark_sankey( plot, from, to, value, label = TRUE, show_values = FALSE, flow_color = "source", node_width = 0.04, node_gap = 0.02 )vsankey( data, from, to, value, label = TRUE, show_values = FALSE, flow_color = "source", node_width = 0.04, node_gap = 0.02, width = 8, height = 5, dpi = 96 ) mark_sankey( plot, from, to, value, label = TRUE, show_values = FALSE, flow_color = "source", node_width = 0.04, node_gap = 0.02 )
data |
A data frame of flows. |
from, to, value
|
Columns (tidy-eval): the source node, target node, and flow value. |
label |
Draw node labels? Default |
show_values |
Append each node's value to its label (e.g. |
flow_color |
Ribbon fill: |
node_width |
Node-rectangle width, as a fraction of the plotting width
(default |
node_gap |
Vertical gap between the nodes in a column, as a fraction of
the column height (default |
width, height, dpi
|
Page size (inches) and resolution. |
plot |
A PlotSpec. |
The flows must form a DAG (no cycles). Nodes within a column are ordered to minimise ribbon crossings (a deterministic Sugiyama barycenter sweep), and ribbons are stacked to meet each node in matching order. Nodes are coloured from the built-in qualitative palette.
A PlotSpec (vsankey()) or the modified plot (mark_sankey()).
flows <- data.frame( from = c("A", "A", "B", "C", "C"), to = c("B", "C", "D", "D", "E"), value = c(4, 6, 4, 4, 2) ) vsankey(flows, from, to, value) vsankey(flows, from, to, value, show_values = TRUE, flow_color = "target")flows <- data.frame( from = c("A", "A", "B", "C", "C"), to = c("B", "C", "D", "D", "E"), value = c(4, 6, 4, 4, 2) ) vsankey(flows, from, to, value) vsankey(flows, from, to, value, show_values = TRUE, flow_color = "target")
vsparkline() builds a compact, axis-free chart of a single numeric series,
sized in physical units (mm by default) so it reads as a word-sized graphic
(Tufte's sparkline) — for a table cell, a caption, or a dashboard tile. It is a
self-contained PlotSpec: render it with render_plot(), drop it into a
composition with inset(), or (soon) a table cell.
vsparkline( values, type = c("line", "bar", "winloss"), color = "grey30", points = c("extremes", "last", "none"), point_color = "firebrick", baseline = 0, win_color = "#2c7fb8", loss_color = "#d7301f", linewidth = 1, point_size = 1.4, width = 20, height = 6, units = "mm", dpi = 96 )vsparkline( values, type = c("line", "bar", "winloss"), color = "grey30", points = c("extremes", "last", "none"), point_color = "firebrick", baseline = 0, win_color = "#2c7fb8", loss_color = "#d7301f", linewidth = 1, point_size = 1.4, width = 20, height = 6, units = "mm", dpi = 96 )
values |
A numeric vector (the series), length >= 2. |
type |
|
color |
Trend / bar colour. Default |
points |
For |
point_color |
Dot colour (default |
baseline |
For |
win_color, loss_color
|
For |
linewidth |
Trend line width (default |
point_size |
Dot diameter in mm (default |
width, height, units
|
Physical size of the sparkline; |
dpi |
Resolution for raster output. |
Three shapes via type: a "line" trend (with optional dots on its extremes
or last point), a "bar" column micro-chart, and a "winloss" chart of equal
up/down bars about a baseline (for streaks of wins/losses, gains/drops).
The chart fills its box with no axes, gridlines, labels, or legend.
A PlotSpec.
set.seed(1) vsparkline(cumsum(rnorm(30))) vsparkline(rpois(20, 5), type = "bar") vsparkline(sample(c(-1, 1), 20, replace = TRUE), type = "winloss")set.seed(1) vsparkline(cumsum(rnorm(30))) vsparkline(rpois(20, 5), type = "bar") vsparkline(sample(c(-1, 1), 20, replace = TRUE), type = "winloss")
vtable() lays a data frame out as a grid of cells where an ordinary column
renders as text and a list-column of numeric vectors renders as a
per-row vsparkline() — chart-in-table, drawn as one vector scene (so it
renders on PNG / SVG / PDF like any plot). It returns a compiled object;
render_plot() it, print() it, or drop it into a composition.
vtable( data, spark = list(), cols = NULL, align = NULL, header = TRUE, font_size = 9, spark_width = 24, row_height = 7, cell_pad = 1.5, units = "mm", dpi = 96 )vtable( data, spark = list(), cols = NULL, align = NULL, header = TRUE, font_size = 9, spark_width = 24, row_height = 7, cell_pad = 1.5, units = "mm", dpi = 96 )
data |
A data frame. Sparkline columns must be list-columns whose cells are numeric vectors. |
spark |
A named list mapping a (list-)column name to how it draws: a
|
cols |
Character vector of columns to show, in order (default all). |
align |
Optional named list of per-column alignment
( |
header |
Draw a bold header row with an underline (default |
font_size |
Text size in points (default |
spark_width |
Width of a sparkline column, in |
row_height |
Row height, in |
cell_pad |
Horizontal padding inside a text cell, in |
units |
Length unit for the sizes above: |
dpi |
Resolution for raster output. |
A VTable (renders via render_plot()).
df <- data.frame(name = c("A", "B", "C"), mean = c(3.1, 5.4, 2.2)) df$trend <- list(cumsum(rnorm(20)), cumsum(rnorm(20)), cumsum(rnorm(20))) vtable(df, spark = list(trend = "line"))df <- data.frame(name = c("A", "B", "C"), mean = c(3.1, 5.4, 2.2)) df$trend <- list(cumsum(rnorm(20)), cumsum(rnorm(20)), cumsum(rnorm(20))) vtable(df, spark = list(trend = "line"))
vvenn() draws a Venn diagram of 2 or 3 sets: overlapping circles whose
disjoint regions are filled by how many elements fall in exactly that
combination of sets. Each region is drawn as solid geometry (via
vellum::vl_path_op()'s boolean set operations), so overlapping regions do
not alpha-composite and stay crisp — including in PDF, where a rasterised
mask would degrade.
vvenn(sets, width = 5, height = 5, dpi = 96)vvenn(sets, width = 5, height = 5, dpi = 96)
sets |
Either a named list of member vectors ( |
width, height, dpi
|
Figure size (inches) and resolution. |
A PlotSpec; print or render_plot() it.
vvenn(list( Coffee = c("Ann", "Bo", "Cy", "Di"), Tea = c("Bo", "Di", "Ed", "Fi") ))vvenn(list( Coffee = c("Ann", "Bo", "Cy", "Di"), Tea = c("Bo", "Di", "Ed", "Fi") ))
vwaffle() draws a waffle (square pie): a grid of cells coloured by
category, where each category takes a share of the cells proportional to its
count — a part-of-whole chart that is easier to read than a pie because the
eye counts squares. It is a self-contained chart (like vsankey() /
vvenn()): it returns a PlotSpec with no axes.
vwaffle( data, category, value = NULL, n_cells = 100, rows = 10, flip = FALSE, pad = 0.12, width = 5, height = 5, dpi = 96 )vwaffle( data, category, value = NULL, n_cells = 100, rows = 10, flip = FALSE, pad = 0.12, width = 5, height = 5, dpi = 96 )
data |
A data frame. |
category |
The categorical column that colours the cells (tidy-eval). |
value |
Optional per-row weight column; if omitted, each row counts once. |
n_cells |
Total number of cells in the grid (default |
rows |
Number of rows in the grid (default |
flip |
Fill row by row (left to right) instead of column by column. |
pad |
Gap between cells, as a fraction of a cell (default |
width, height, dpi
|
Page size (inches) and resolution for the standalone chart. |
A PlotSpec.
df <- data.frame(part = c("a", "b", "c"), n = c(50, 30, 20)) vwaffle(df, category = part, value = n)df <- data.frame(part = c("a", "b", "c"), n = c(50, 30, 20)) vwaffle(df, category = part, value = n)