type_lines() and its shortcut equivalents like "l" and "b" now order
categorical x data by (coerced) factor levels, rather than simple order of
appearance. This resolves a longstanding tension between line types and
other types like type_points(), which have always ordered the x axis by
implied factor levels. It also improves layering consistency via plt_add()
and co. so that plots are identical, regardless of whether lines are layered
on top of points, or vice versa. Note that you can still select into the
old behaviour by passing the (new) xord = "asis" argument as an
explicit override; see "Other new features" below. (#683 @grantmcdermott)type_hexbin() / "hexbin" for hexagonal bin plots, a 2D analogue of a
histogram. (#667 @grantmcdermott)type_tile() / "tile" for tile plots, i.e. a grid of rectangles whose fill
encodes a third variable. (#677 @grantmcdermott)type_heatmap() / "heatmap" builds on type_tile(), adding a scale
argument that scales the fill values within each category of one axis. This
is analogous to base R's heatmap() function, and like the latter it z-scores
along the chosen margin by default. It also reverses the y-axis by default, so
that the first row sits at the top (again matching heatmap()); pass an
explicit ylim to override. (#677 @grantmcdermott)type_sina() / "sina" for sina plots,
a variant of the violin plot where the raw observations are displayed as points,
with each group's width bounded by its density. This makes them arguably a more
principled version of the beeswarm plot. (#734 @grantmcdermott)type_area() gains a new stack argument
for drawing stacked area plots, where each layer represents a discrete by
category group. This functionality is further enhanced by two (also new)
sister arguments. First, byord enables on-the-fly (re-)ordering of the
stacked by layers, via convenience keywords or custom functions (e.g.,
byord = "end" ranks groups according to their largest final value). Second,
a fun argument permits stacking of multi-observation data by collapsing
repeated y values. (#688 @grantmcdermott)The top-level facet.args list argument gains several new (sub-)arguments that
enable finer control and customization of faceted plots:
axes: gives explicit control over which facets draw their own axes: "all",
"outer" (drop redundant interior axes), or "none". Previously this was
only achievable as a side effect of frame.plot = FALSE, so axes = "outer"
now allows redundant axes to be dropped while keeping the facet frames. Left
unspecified, the behaviour is still inferred from whether the plot is framed.
(#661, #673 @grantmcdermott)
"classic", "socviz", "tufte", and
"float") now default to facet.axes = "outer", so that they drop the
redundant interior axes of faceted plots.drop: allows for the removal of empty facets. The behaviour varies slightly
depending on whether a one-sided (wrapped) or two-sided (gridded) facet
formula is specified. The former simply removes the missing factor level,
while the latter retains its spot (to preserve the rectangular grid) but is
not drawn. (#708, #710 @grantmcdermott)drop.levels: allows each free facet (free = TRUE) to keep only the
categories of a categorical axis that it actually uses. The panel's axis is
recomputed as if its own data had been passed through factor(), so that the
surviving categories are re-spaced evenly rather than leaving a gap where an
unused one sat. Note the distinction from drop above: the latter removes
empty facets, whereas drop.levels removes unused categories within a
facet. Default is FALSE, i.e. every facet keeps the full set of categories.
(#718 @grantmcdermott)labeller: for formatting facet titles via tinylabel(). Accepts the usual
mix of convenience keywords (symbols) known to tinylabel(), or formatting
functions. A (named) vector or list can be used to separately format
multi-variable facets, e.g. labeller = c(country = toupper, size = ",").
(#684 @grantmcdermott)prefix: for adding an informative prefix to facet titles. In its simplest
form, prefix = TRUE prepends the facet variable name, e.g. "vs = 0" and
"vs = 1" (rather than just "0" and "1"). Like labeller above,
multi-variable facets can be prefixed separately via a (named) vector or list,
e.g. prefix = c(am = "Automatic", vs = "V-shaped"). (#684 @grantmcdermott)sep: controls how the individual variables of a multi-variable facet title
are separated, e.g. use sep = "\n" to stack on separate lines rather than
concatenating via the default ":". (#684 @grantmcdermott)Note that each of these facet.args arguments is paired with an equivalent
tpar(facet.<arg>) parameter. For example, call tpar(facet.axes = "outer")
to set this behaviour globally. This also means that they can be set as part of
a (custom) theme, e.g. tinytheme("clean", facet.axes = "outer").
This release brings several enhancements for working with categorical
variables, i.e. where x, y, or by are characters or factors with discrete
levels. This includes improvements to existing arguments, as well as the
provision of some new arguments that enable finer control over level ordering
and convenient label formatting.
xlevels, ylevels: these (type-level) arguments permit on-the-fly
reordering of a categorical variable via literal specification, either a
character vector of level names (e.g., c("C", "B", "A")), or a numeric
vector of level indices (e.g., 3:1). While this argument is not new---having
been supported by type_barplot and several other types for a while---we now
extend xlevels support to type_points(), type_lines(),
type_errorbar(), and type_pointrange(). (#683, #694 @grantmcdermott)xord, yord: these are new (type-level) arguments that provide an alternate
ordering interface to x/ylevels. Specifically, while x/ylevels require a
literal ordering, x/yord computes the order on the fly, according to
(type-appropriate) convenience keywords or a custom ranking function. For
example, "desc(ending)"/"asc(ending)" orders by value, while "asis"
ignores factor levels and just takes the order of appearance in the data as
given. Among other things, this makes it possible to sort barplots by height
(e.g., type_barplot(xord = "desc")), or ridges by their spread (e.g.,
type_ridge(yord = "minvar")) without relevelling the underlying factor by
hand. (#683, #694 @grantmcdermott)x/ylevels and x/yord are provided, the former takes precedence as
the more explicit.)tinylabel() gains a dictionary form, i.e., a named character vector or
list that maps existing labels to new ones a la
c(old1 = "new1", old2 = "new2"). Partial mapping is fine since the lookup is
by value rather than by position, so that some levels can be left unnamed.
Importantly, this behaviour extends to the rest of tinyplot's
(re)labelling machinery---including x/yaxl, type_text(), and any function
with a labeller argument---since everything is routed through tinylabel().
(#690 @grantmcdermott)x/yaxlabels arguments of type_spineplot() and
type_barplot() are deprecated in favour of the top-level x/yaxl arguments.
The type-level arguments predated their top-level cousins, which now offer the
same functionality via a consistent interface across all types. The old
arguments still work (with a warning) for now. But we will be formally
removing them in a future release and, going forwards, encourage users to move
over to xaxl and yaxl as the idiomatic tinyplot way to relabel
and format axis ticks. (#692 @grantmcdermott)Beyond convenience, these improvements to categorical variable handling also provide the scaffolding to eliminate some niggling inconsistencies; for example, related to plot layering. See "Bug fixes" below.
"p", "l", "errorbar", and friends) gain smart padding
behaviour for categorical axes. Most notably, we now use more generous axis
padding when there are few unique categories (levels), so that the end tick
marks aren't drawn flush against the plot frame. Users can also override with
the new x/ypad arguments (see below) to match their own aesthetic
preferences. (#732 @grantmcdermott)tinyplot.* methodstinyplot.array(): for (unclassed) array objects with up to four
dimensions. This extends the tinyplot.matrix() conventions by mapping the
third dimension to facets, and a fourth to a facet grid. The names of the
dimnames (if any) are used for the axis, legend, and facet titles. Arrays
with a length-2 dimension (e.g., gait) are plotted as x/y pairs, i.e. one
slice against the other. See the tinyplot.array-specific xy argument.
Passing facet = FALSE draws everything in a single panel instead.
(#746 @grantmcdermott)tinyplot()/plt() arguments:
xpad and ypad enable control over how much padding (as a fraction of the
data range) is added to each end of the axes. Following base R conventions,
the default for most plots is 0.04, i.e. 4% padding on each side. Also
settable globally via tpar(xpad = <xpad>, ypad = <ypad>).
(#729 @grantmcdermott)xaxr and yaxr enable rotating of the x- and y-axis tick labels by
arbitrary angles, closing a long-standing feature request (#346). Note that
setting one overrides las for that axis. Best combined with a dynamic
theme, since the plot margins are resized to fit the rotated labels. Also
settable globally via tpar(xaxr = <xaxr>, yaxr = <yaxr>) and thus as part
of a tinytheme too. (#717 @grantmcdermott)las does the same thing, but limited to the four right angles of base R's
par(las=) convention, having previously been settable only via tpar() or
a theme. Note that this top-level argument applies to a single plot only and
takes precedence over the active theme, so it can also be used to opt out
of a theme's las, e.g. tinyplot(..., theme = "clean", las = 0).
(#353 @grantmcdermott)record enables recording plots as replayable objects,
closing another long-standing feature request (#121). Specifically, setting
record = TRUE returns a "recordedtinyplot" object (see
?recordedtinyplot), allowing for assignment and later recall, e.g.
myplot = tinyplot(...); myplot. Also settable globally via
tpar(record = TRUE), so that all tinyplot() plots are automatically
recorded---with potential memory implications for detailed plots with many
elements. Note that a recorded plot will still render its display on the
initialising call if you are using an interactive graphics device. While we
have done our best to vet this new record functionality carefully, users
should still regard it as experimental. We may change its behaviour
(availability) in a future release if we observe undesirable side-effects.
Please help us by testing on your own machines and reporting any issues.
(#686 @grantmcdermott)type_lines() and its shortcut equivalents like "l" and "s" now support
a continuous by variable, drawing a colour gradient along the line
itself rather than reverting to a discrete legend. Useful for trajectories,
where a third variable (typically time) orders the path; see the new
?type_lines examples. (#712 @grantmcdermott)type_density() gains an echo.bw argument for reporting the smoothing
bandwidth and the number of observations behind it, neither of which is
visible from the curve itself. Destinations are "sub", "cap", and
"cat" (console), in any combination; a destination the user has already
labelled is left alone. Shared bandwidths are reported once and named as
joint, individual bandwidths per group. (#287 @haomeng797-ship-it)type_area() gains a stack argument for drawing stacked area plots. See
"New plot types" above for more details. (#688 @grantmcdermott)type_summary() gains a dodge (and fixed.dodge) argument, thus enabling
dodging of grouped plots. This is mostly useful for adding summaries on top
of a base layer that is itself dodged. Separately, type_summary()'s
internals have been refactored to use stats::aggregate instead of
stats::ave. (#701 @grantmcdermott)type_barplot() gains a na.as.zero argument for controlling whether a
category that no observation reaches is treated as a zero (and so marked
with a flat bar along the baseline) or left undrawn. The default NULL
lets fun decide; see the new "Implicit zeros and empty cells" section of
?type_barplot. (#718 @grantmcdermott)type_barplot()'s aggregation argument is now spelled fun, for
consistency with the other types that take a function and with
tinyplot's lowercase argument naming generally. FUN is retained as a
backwards-compatible alias, so existing code keeps working; supply one or
the other, and fun takes precedence if both are given.
(#695 @grantmcdermott)type_histogram() now (correctly) supports mapping by grouping along the
x variable, e.g. tinyplot(~mpg | mpg, data = mtcars, type = "hist").
Bar colours map to mean bin values. (#727 @grantmcdermott)type_loess() is now much faster on large data. Thanks to @eleuven for
bringing this slowness issue to our attention. (#509 @grantmcdermott)"heatmap" provides a dedicated companion theme to the new type_tile()
and type_heatmap() types (see above). The theme removes all axis padding,
so that tiles meet the panel edge, and also rotates the tick labels against
their respective axes. Colour fills default to the "tealgrn" sequential
palette. (#677 @grantmcdermott)tinytheme_get() function returns the name of the currently active
theme. (#629 @grantmcdermott)type_hints mechanism. A type can declare properties about itself---that
it draws its own axes, needs a secondary right-hand axis, uses proportional
limits, fills its legend key from col, and so on---and tinyplot adjusts
margins, axis limits and legend keys accordingly. Previously this behaviour
was hard-coded against the names of built-in types, so it was unavailable to
custom types. See
Advanced customization
in the Types vignette for the list of supported hints. (#543 @grantmcdermott)cex.xaxs and cex.yaxs graphical parameters allow the x- and y-axis
tick labels to be sized independently, e.g. tpar(cex.yaxs = 0.6) to shrink a
long list of category names on the y-axis without also shrinking the x-axis.
Both default to NULL, in which case the shared cex.axis value is used, so
existing plots are unaffected. (#677 @grantmcdermott)tinyplot(1:10, array(1:10, c(1, 10))) works
just like plot(). (#548, #746 @tony-aw @zeileis @grantmcdermott)facet = rows ~ cols) now work with the default
(non-formula) method, e.g. tinyplot(x, y, facet = a ~ b, data = dat).
Previously this errored because data was not forwarded. (#746
@grantmcdermott)facet.args = list(free = TRUE)) now respect asp.
(#744 @grantmcdermott)"Hello\nWorld") are now spaced
correctly under dynamic themes. (#742 @grantmcdermott)type_lm(), type_glm() and type_loess() now space their prediction grid
evenly in log(x) when the x-axis is logarithmic. Previously a log = "x"
plot spanning several decades drew the left-hand ones as a few straight
segments. (#509 @grantmcdermott)theme argument no longer clobbers a persistent tinytheme()
i.e., beyond the intended single plot override. Similarly for a user's own
tpar() settings. (#739 @grantmcdermott)theme
argument are no longer clipped to the wrong region. Only triggered once an
intervening annotation changed xpd (e.g. box(), mtext(), or
type_text(xpd = NA)), since that is what makes base R recompute the
clipping rectangle. Thanks to @bastistician for the report.
(#629 @grantmcdermott)type_text() no longer converts a categorical axis to a numeric one.
(#730 @grantmcdermott)type_hline(), type_vline(), and type_abline() now respect
flip = TRUE, so that (e.g.) h refers to the flipped y variable and is
drawn vertically. Code that previously used type_vline() as a workaround
for a vertical line on a flipped plot should switch to type_hline(), and
vice versa. (#733 @grantmcdermott)adjust argument of type_density(), type_violin(), and
type_ridge() was accepted but never passed on to the underlying
density() call, so it silently did nothing. (#734 @grantmcdermott)type_violin() receives two further bug fixes:
joint.bw = "full" computed the joint bandwidth from the x categories
rather than the y values being smoothed. (#734 @grantmcdermott)by variable's underlying integer codes.
A numeric by therefore errored outright, and a factor by carrying an
unused level silently dropped the affected group from the plot. Offsets are
now keyed by position among the observed groups. (#734 @grantmcdermott)by now reverts to discrete groups and a matching
discrete legend, as it already did for "boxplot", "polygon" and the
other types that cannot render a colour gradient. Previously every violin
was drawn in the same colour while the legend showed a colourbar.
(#734 @grantmcdermott)par("xlog")/par("ylog") state. We now
avoid this by grabbing the log state directly from the top-level log
argument instead. Thanks to @eddelbuettel for the report.
(#725 @grantmcdermott)type_barplot() receives several consistency improvements and bug fixes:
barplot(). (#714 @grantmcdermott)fun or the new na.as.zero
argument (above). At the same time, explicit zeros remain unaffected. Again,
see the new "Implicit zeros and empty cells" section of ?type_barplot for
details and examples. (#711 @grantmcdermott)type_ridge() no longer errors under themes that set a relative (negative)
numeric col.default, e.g. theme = "classic". (#703 @grantmcdermott)tinyplot_add() now align correctly on a categorical axis:
x variable to a
factor, as type_barplot() and type_violin() do. The base layer's
categories are the coerced labels, while the added layer still carried the
raw values, so it was drawn at those coordinates instead of at the category
positions---often well outside the plotting region. (#691 @grantmcdermott)tinyplot(..., center = TRUE, yaxl = "percent") labelled its axis 80.00000% rather than
80%. (#689 @grantmcdermott)xaxl / yaxl arguments now work for type_spineplot() and
type_ridge(). Both types draw their own axes, and so never reached the
standard path where those arguments are applied, meaning they were silently
ignored. (#694 @grantmcdermott)xlevels / ylevels no longer drop data silently. Naming a strict subset of
a variable's levels sent every other level to NA, quietly removing those
observations from the plot; this now warns. Supplying a value that matches no
level at all is now an error, rather than surfacing later as an unrelated
complaint about zero-length ranges. (#688, #694 @grantmcdermott)type_area() now labels a categorical x axis with its factor levels,
rather than falling back to the underlying integer positions.
(#688 @grantmcdermott)by and
facet combinations containing only one observation. Such groups are now
dropped, together with a warning reporting how many were removed. The
affected types---type_density(), type_violin(), and type_ridge()---also
gain a singletons argument for controlling this behaviour: option "drop"
removes them quietly, while "none" retains them (and so requires a numeric
bw). (#687 @grantmcdermott)flip = TRUE now flips the drawn geometry of the single-letter line types,
not just the axes: type = "h" draws horizontal segments to the baseline,
and the step types "s" and "S" swap which coordinate moves first.
(#675 @haomeng797-ship-it)flip = TRUE and for a factor y variable. Previously the y-axis fell back
to numeric tick labels for every line type except "p".
(#679 @grantmcdermott)facet.args = list(free = TRUE)):
drop.levels arg
(above) for the opposite behaviour. (#718 @grantmcdermott)'labels' is supplied and not 'at'. The free-facet code path listed the eligible types by name, so
any other type lost its tick positions while keeping the corresponding
labels, whether flipped (e.g. type = "b" with flip = TRUE) or not
(e.g. type = "p" with a factor y variable). (#679 @grantmcdermott)par(usr) values.
(#668 @grantmcdermott)par(usr) values either. (#705 @grantmcdermott)x/ylim overrides now work correctly with flipped plots.
(#670 @grantmcdermott)x/ylim limits (e.g., ylim = 0 or
ylim = c(0, NA)) are now resolved per facet, rather than once against the
range of the whole dataset. (#706 @grantmcdermott)cex, lwd and lty as their fixed-scale
counterparts. Previously the free-facet code path built its axis calls by
hand and so silently ignored cex.axis, lwd.axis and lty.axis (plus
their per-side variants), which was most visible under themes that set them,
e.g. tinytheme("bw"). (#673 @grantmcdermott)cex.axis as cex, which base axis()
ignores in favour of cex.axis when sizing tick labels, so the setting had
no effect. This also means the per-side cex.xaxs/cex.yaxs parameters
(see above) take effect. (#677 @grantmcdermott)cex.axis, so a plot setting
cex.xaxs/cex.yaxs to different values clipped the labels on the larger
axis and reserved dead whitespace on the smaller one, e.g.
tinytheme("heatmap", cex.xaxs = 2, cex.yaxs = 0.5). (#677 @grantmcdermott)"spineplot" types (e.g. facet = "by"), where the
self-drawn axis labels were overplotted several times and rendered too heavy.
(#637 @grantmcdermott)"spineplot" and "ridge" types, which draw their own axes and so
bypassed the shared outer-axis logic, but some affected other types too.
(#660, #661 @grantmcdermott)
tinytheme("clean2")), where the category labels previously spilled into the
neighbouring facet.tinytheme("clean")). The tick-label width was only reserved once, in
the outer margin, which is correct only when a single facet draws that axis.type = "boxplot", flip = TRUE) no longer duplicate the
category axis while omitting the interior x-axes, which had left facets
labelled against a neighbour's scale.axes = "t" (and other tick-style axes) no longer drop the interior facet
labels.y ~ 1 formulas no longer silently drop explicitly-typed layers,
e.g. tinyplot(body_mass ~ 1, data = penguins) followed by
tinyplot_add(type = type_vline(4500)). The x-axis swap these formulas
require was only applied when the type had to be inferred, so an explicit type
was mistaken for an empty plot and never drawn. (#647 @grantmcdermott
@zeileis)legend = "bottom!") no longer
ride up over the x-axis under dynamic themes. (#719 @grantmcdermott)tinyplot v0.7.0 is a big release with many new features, including major updates to our theming logic and aesthetic stylings. Related updates are grouped below for easier navigation.
A major focus of v0.7.0 is bringing various aesthetic improvements to tinyplot. These aesthetic improvements should carry over to all of your (tiny)plots automatically and do not require any changes to user-facing inputs or the core API. From that perspective they are not a breaking change, even though some of your plots may look slightly different from before. Still, we hope that you agree the following changes result in better looking visualizations:
"right!" and "left!". This is a minor visual
change from the previous default of centered legends, which we inherited from
base R. However, users can still override this behaviour with the new ljust
parameter, which accepts values of "l(eft)" (new default) or "c(enter)"
(old default). (#500 @grantmcdermott)
tpar(ljust = "c"), or revert for a
single plot by passing the parameter as part of the legend list arguments,
i.e. plt(..., legend = list(ljust = "c")).legend = "direct"
keyword. This places the legend labels at the last observation of each data
group and is thus best suited to line or ribbon plots, where the data is
sorted along the x-axis. (#587 @grantmcdermott)
repel (for automatic vertical separation) or
nudge_x/nudge_y (for manual per-group offsets). For example,
plt(..., legend = list("direct", repel = TRUE)).We have significantly refactored our dynamic themes logic. Recall, these are
themes like "dynamic", "clean", "bw", etc. that automatically adjust
margin spacing and related plot elements to reduce whitespace and improve the
overall plot aesthetic. The ?tinytheme help file and online
Themes vignette
cover the new features in detail. But see below for the highlights.
(#549, #591, #595, #606, #614 @grantmcdermott, @vincentarelbundock, @zeileis)
New theme features:
tinytheme() now accepts additional gap.axis and gap.lab "primitives",
providing finer control for spacing between ticks-to-labels and
labels-to-titles, respectively, in dynamic themes. (#590 @grantmcdermott)tinytheme() also accepts gap.main and gap.sub primitives
for controlling the spacing between titles and the plot region.
(#595 @grantmcdermott)"tufte" and "void" are now dynamic (responsive margins).ggplot2-inspired themes ("bw", "classic", etc.) now use
smaller axis text and tighter spacing to better match their upstream
ggplot2 counterparts."ipsum" has been similarly overhauled to match the upstream theme (bold
title, no ticks, fine grid, custom palette). Our original tinyplot variant
is preserved as "ipsum2" for those who still want to use it."dark" now uses a better default ribbon.alpha for better contrast
against the black background."dynamic" (new foundation for all other dynamic themes)"broadsheet" (data journalism style à la The Economist or NY Times)"float" (floating axes; a variant of "tufte")"linedraw" (based on the ggplot2 theme)"nber" (NBER working paper style)"socviz" (based on Kieran Healy's book)"web" (web publication, e.g. FiveThirtyEight)tinytheme_register() function for registering custom user themes.
Registered themes inherit from any built-in (or previously registered) theme,
apply user-specified overrides, and can then be used by name with
tinytheme(<theme>) or tinyplot(..., theme = <theme>). Companion functions
tinytheme_list() and tinytheme_unregister() further support this
functionality. (#608 @grantmcdermott)by grouping) versus multi-group displays. The upshot
is that, for many themes, single-group displays will simply default to
"black", whereas multi-group displays will drop "black" and only present
colour palettes. This behaviour is operationalized through the new
col.default parameter, settable via tpar() or within a theme.
(#614 @grantmcdermott @zeileis)
"clean(2)", "dark", "nber", "web") consistently use that colour for
single-group displays too."bw", "classic", "linedraw", and
"minimal") continue to use black for single-group display. But they now
drop the leading black from their grouped palettes. (Note that these
themes also use the default "ggplot2" palette now, so grouped plots start
at the familiar salmon hue.)"ipsum2" and "broadsheet" themes use the
Okabe-Ito palette less its leading black, so grouped plots start at orange.
The "float" and "void" themes also default to black for single-group
displays."boxplot", "violin", "barplot",
and "histogram" displays is now unified across these four types, so that a
single-group plot looks the same regardless of which one you reach for.
(#614 @grantmcdermott @zeileis)
"clean"
or the teal of "dark"), the fill is a lighter-but-opaque tint of it;
following the same sequential HCL ramp that "ridge" type plots have been
using for a while."bw"/"classic"/"ipsum" themes), all four types share a neutral
"lightgray" fill, matching base R's hist() and boxplot() defaults.
Note that this does imply a change for "barplot" types, which previously
used a slightly darker "grey" (to match base R's barplot()), but we
decided internal consistency was the more important feature to prioritize."boxplot", "violin", and "barplot"
displays now also use the lighter-but-opaque fill, so that grouped plots match
their single-group counterparts (previously grouped barplots used dark
saturated fills and grouped boxplots/violins used semi-transparent fills). Each
type gains a lighten argument (default TRUE); set
type_barplot(lighten = FALSE) (etc.) to recover the fully-saturated palette
colours. "histogram" is deliberately excluded, since semi-transparency
remains preferable for overlapping grouped distributions. "spineplot" also
gains a lighten argument (only relevant for the y == by case), but defaults
to FALSE (saturated fills): its tiles abut one another with no gap, so the
darker fills read better against their matching border colours.
(#646 @grantmcdermott @zeileis)
fill or alpha is now layered on
top of the (lightened) fill rather than the saturated base colour. This
fixes a counterintuitive case where adding an alpha fill (e.g. fill = 0.7)
could darken the interior of an area-based plot.Theme fixes:
main,
sub, and x/y axis titles. For example, a plot without a main (or
sub) title will expand to the top of the device region to reduce excess
whitespace. (#303)main and sub titles now correctly anchor to the y-axis
line, even when long horizontal tick labels widen the left margin. (#479)cex.xlab and cex.ylab now correctly control axis title size. The
more general cex.lab is still respected as a fallback. (#574)mgp now scale correctly with cex.axis and
cex.lab, maintaining constant visual gaps between axis elements
regardless of text size. From the user perspective, this is
operationalized through the new gap.axis and gap.lab theme
primitives, which let you control the spacing between margin elements
directly (tick-to-label gap and label-to-title gap, respectively),
replacing the guesswork of manually combining mar, mgp, and tcl
values. (#590)gap.main and gap.sub theme primitives control the spacing
between titles and the plot box. gap.main sets the gap from the main
title to whatever is below it (plot box or subtitle top); gap.sub
sets the gap from the subtitle to the plot box. Both default to 0.7.
(#597)legend = "top!". The title,
subtitle, and legend stack correctly above the plot region with proper
spacing. (#605)type_chull() (equivalently, type = "chull") for drawing convex hulls
around grouped points. Uses grDevices::chull() under the hood and delegates
drawing to draw_polygon(). Works well as a layer on top of points, e.g.
plt_add(type = "chull", fill = 0.2). (#600 @grantmcdermott)type_ellipse() (equivalently, type = "ellipse") for drawing confidence
ellipses around grouped points. Like type_chull, works well as a filled
layer, e.g. plt_add(type = "ellipse", fill = 0.2). (#610 @grantmcdermott)tinyplot.* methodstinyplot.data.frame(): Supports direct plotting of data frames, alongside
the new top-level function tinypairs(). Can be called with or without a
formula. One benefit of the former is that it facilitates piping, e.g.
iris |> plt(Sepal.Length ~ Petal.Width | Species)
If no formula is provided, then the behaviour depends on the number of
variables (columns) in the data frame. For example, a dataset with 3 or more
variables will yield a pairs()-style grid of all variable combinations.
Thanks to @mthulin for the suggestion and original implementation idea.
(#613, #640 @zeileis @grantmcdermott)
tinyplot.matrix(): for matrix objects, e.g.
plt(VADeaths, type = "b")
The output largely mimics the base matplot/matlines equivalents, but with
additional tinyplot functionality related to automatic legends, options
for faceting, etc. (#649 @grantmcdermott)
tinyplot.ts(): for ts time series, e.g.
plt(EuStockMarkets)
Produces a line plot by default, although users can override by passing an
explicit type argument. Similarly, multivariate series are faceted by
default, but users can also override to obtain, say, a single frame with
direct labels. (#558 @zeileis @grantmcdermott)
New and updated top-level tinyplot()/plt() arguments:
cap = <string> for adding a caption to your plots. Captions are drawn at
the bottom of the plot and are best paired with dynamic themes (since
separation from sub is guaranteed). Appearance is customizable via
tpar() parameters: adj.cap, cex.cap, col.cap, font.cap, and
line.cap. (#592 @grantmcdermott)
weights = <varname> for adding weights to statistical transformations.
Supported types are models (type_lm(), type_glm(), type_loess()) and
distributions (type_density(), type_histogram(), type_spineplot()). A
warning is emitted if weights is passed to an unsupported type and the
argument is also ignored. The top-level weights argument supports
non-standard evaluation (NSE) in the formula method, so that bare column
names can be passed for convenience. Users can also pass a weights argument
directly at the type-specific function level, but this must be a vector
of correct length (no NSE). For example:
plt(y ~ x, data = dat, type = "lm", weights = w) # top-level, NSE
plt(y ~ x, data = dat, type = type_lm(weights = dat$w)) # type-level, vector
In addition to NSE convenience, the top-level variant is preferred since it is correctly matched to the model frame construction with the formula method (e.g., so missing values are handled automatically). Thanks to @eleuven for the original suggestion, as well as various discussion participants for helping to frame the scope. (#639 @grantmcdermott)
labels = <varname> for passing labels to type = "text". Like the new
weights argument (above), the main benefit is the convenience of NSE, as
well as the automatic handling of missing values and subsets as part of the
model frame construction. For example, compare:
plt(y ~ x, data = dat, type = "text", labels = labs, subset = x < 10)
plt(y ~ x, data = subset(dat, x < 10), type = type_text(labels = subset(dat, x < 10)$labs))
The labels arg is silently ignored for non-text types.
(#639 @grantmcdermott)
The grid argument (and tpar("grid")) now accepts character strings to
control axis-specific grids at different resolutions. Uppercase letters
("X", "Y", "XY") draw grid lines at the standard tick positions, while
lowercase letters ("x", "y", "xy") draw a finer grid with additional
lines at the midpoints between ticks. Thanks to @zeileis for the suggestion.
(#578 @grantmcdermott)
Facet formulas now support 1 as a convenience syntax for single row or
column arrangements. (#562 @zeileis)
plt(..., facet = z ~ 1) <-> plt(..., facet = ~z, facet.args = list(ncol = 1))plt(..., facet = 1 ~ z) <-> plt(..., facet = ~z, facet.args = list(nrow = 1)).x/ylim gain several "smart" override forms. (#644 @grantmcdermott)
ylim = 0) ensures that value is covered by the
axis range, e.g. for forcing zero onto a coefficient plot.NA (e.g. ylim = c(0, NA)) pins the non-NA
limit and lets the data determine the other."rev" (or "reverse") reverses the auto-computed axis range,
without needing to know the data extent in advance.Type-specific updates:
type_barplot() gains an offset argument for shifting bar baselines away
from zero. (#611, #615 @grantmcdermott @zeileis)
by group, pulling them out of the stack
and drawing them as standalone bars. This is useful for Likert plots,
where you want to show a neutral category (e.g., "Unsure") apart from
the diverging stack. Thanks to @strengejacke for the suggestion.type_text() gains two new arguments:
labeller argument that is passed to tinylabel() for formatting the
text labels. (#620 @grantmcdermott)repel argument that automatically nudges overlapping text labels
apart. One limitation is that the repulsion logic operates within groups.
So there may still be some overlapping text for grouped data.
(#621 @grantmcdermott)weights argument; although
this is best provided from the top-level tinyplot()/plt() call. See
above.legend = list(title = FALSE) now suppresses the legend title, matching the
existing title = NULL behaviour. (#653 @grantmcdermott)
grid = grid() not drawing grid lines on all facets. That said, logical
or character inputs (e.g., grid = TRUE, grid = "xy") remain the more
idiomatic way to generate a background grid in tinyplot.
(#193 @grantmcdermott)facet.cex; inter-panel gaps for
multiline facet titles remain fixed regardless of strip height; and strip
text is now vertically centered within the background rect.
(#586 @grantmcdermott)palette.qualitative in themes could not be a
function. Thanks to @katrinabrock for the report. (#594 @zeileis)type_polygon, type_chull, and type_ellipse when
density is set. (#610 @grantmcdermott)tinylabel() currency and comma
formatters (e.g., "$", "€", "£", ","). These now use a consistent
number of decimal places across the whole vector, matching the existing
behaviour of the percent formatter. The currency formatters additionally show
at least two decimal places whenever a fractional component is present (e.g.
"$0.50" rather than "$0.5"), while still keeping clean integers
integer-valued (e.g. "$1,000"), and place the negative sign in front of the
currency symbol (e.g. "-$1.50" rather than "$-1.50").
(#618, #623 @grantmcdermott)xlab = NA / ylab = NA gotchas for "barplot", "spineplot", and
"ridge" types. (#635, #650 @grantmcdermott)tinyplot_add() (plt_add()) now captures its arguments unevaluated, so
arguments that rely on non-standard evaluation against data (e.g.,
plt_add(..., subset = <>)) resolve correctly instead of erroring with
"object not found". (#638 @grantmcdermott)plt(..., ann = FALSE) correctly turns off title annotations now, fixing a
regression that we missed from at least v0.6.0. Thanks to @bastistician for
the report. (#641 @zeileis)bquote() (and other unevaluated language) annotations such as main,
sub, cap, xlab, and ylab being evaluated instead of coerced to
plotmath expressions, e.g. plt(0, 0, main = bquote(foo == .(pi))). Thanks
(again) to @bastistician for the report. (#642 @grantmcdermott)type = "l", and relatives like "b"/"o") with a factor or
character x variable now draw the category labels on the x-axis, matching
the behaviour of point plots. Previously these tick labels were only shown
when dodging was active. (#648 @grantmcdermott)legend = FALSE.
(#656 @grantmcdermott)"pointrange" and "errorbar" types now
include a line, to better resemble the actual plot elements (#533 @grantmcdermott)y ~ 1, ~ x, and ~ 0. These are
translated to x = NULL or y = NULL in the default method call, with
automatic type inference: y ~ 1 (numeric) produces a histogram, y ~ 1
(factor) produces a barplot, ~ x (factor) produces a barplot, and ~ x
(numeric) produces a scatterplot against the index. The ~ 0 form is useful
for types that don't require x/y, such as segments and rect. Thanks to
@katrinabrock for the suggestion. (#534 @zeileis @grantmcdermott)facet.args = list(free = TRUE) lead to an error
when used without facets. Thanks to @katrinabrock for the report.
(#554 @zeileis)type_ridge() fill errors for themes that set a qualitative palette,
e.g. "clean2". (#564 @grantmcdermott)theme = "default" with a legend
and tinyplot_add(). Thanks to @katrinabrock for the report in #557.
(#565 @grantmcdermott)tinyplot_add(type = "jitter") no longer errors when layered on top of
boxplot, violin, or similar categorical plot types. (#560 @grantmcdermott)tinyplot_add() now align correctly with grouped
(offset) boxplot, violin, and ridge base layers. (#561 @grantmcdermott)Types vignette. (#531 @grantmcdermott)type_<type> constructors. (#531 @grantmcdermott).CLAUDE.md context file for AI-assisted development. (#563 @grantmcdermott)revdep* branch. (#567 @grantmcdermott)tinyplot calls are now
stored in a dedicated (temporary) internal environment called settings,
which can be accessed and modified by type-specific functions. This change
will enable various internal enhancements, from improving the modularity and
maintainability of the tinyplot codebase, to reducing memory overhead and
performance (since we require fewer object copies). Looking ahead, we also
expect that it will make it easier to support new features and integration
with downstream packages. Most tinyplot users should be unaffected by these
internal changes. However, users who have defined their own custom types will
need to make some adjustments to match the new settings logic; details are
provided in the updated Types vignette. (#473 @vincentarelbundock and @grantmcdermott)fixed.pos argument for dodged plots has been renamed to
fixed.dodge to avoid ambiguity, especially when passed down from a top-level
tinyplot(...) call. (#528 @grantmcdermott)type_text() gains a family argument for controlling the font family,
separate to the main plot text elements. (#494 @grantmcdermott)dodge argument capabilities and consistency for dealing with
overlapping groups:
dodge argument now also supported by type_lines(), type_points(), and
type_ribbon(). (#522, #528 @grantmcdermott)dodge values must be in the range [0,1).
(#526 @grantmcdermott)dodge = TRUE argument,
which gives automatic width spacing based on the number of groups. (#525 @grantmcdermott)fixed.pos -> fixed.dodge, per the breaking
change above. (#528 @grantmcdermott)pretty breaks
algorithm that we use to create discrete legend categories. The interior plot
elements, e.g. bubble points, are unaffected. (#498 @grantmcdermott)type_text() now defaults to displaying y values if an explicit labels
arg is not provided, mirroring the behaviour of the base text() function.
(#501 @grantmcdermott)tinyplot() generic in preparation for
tinyplot_add() is now more robust so that it is compatible with do.call()
again (reported by @FlorianSchwendinger). This is achieved by inspecting
the functions called rather than just their names. (#504 @zeileis)by is logical. Thanks to @TCornulier for
the report. (#512 @grantmcdermott)legend passed as a symbol through S3 methods
(e.g., tinyplot.foo) would fail. (#515 @grantmcdermott)tinyplot_add(), should now respect the
x-axis order of the original plot layer. This should ensure that we don't end
up with misaligned layers. For example, when ribbon is added on top of an
errorbar plot. (#517, #520, #523, #526 @grantmcdermott)Add a "recession bars" section to the Tips & tricks vignette.
(#503 @grantmcdermott)
Point out more explicitly how the draw argument is evaluated within
tinyplot() and that it thus has access to the local definition to all
variables such as x and y etc. (#507 @zeileis)
cex argument (e.g., a continuous variable from your dataset).
Simultaneously enables dual-legend support for combined size + color mappings.
The updated ?type_points documentation contains several examples.
(#433 @grantmcdermott)tinyplot.default(), so that tinyplot(x, type = "boxplot") and
tinyplot(~ x, type = "boxplot") essentially produce the same output as
boxplot(x). (#454 @zeileis)type_errorbar() and type_point_range() get a dodge argument.
(#461 @vincentarelbundock)tinyplot(..., theme = <theme>) argument enables users to invoke
ephemeral themes as an alternative to the persistent themes that follow
tinytheme(<theme>). (#484 @grantmcdermott)x/yaxl arguments allow for axes label adjustment, users
can now adjust the legend labels too with
tinyplot(..., legend = list(labeller = <labeller>)). The labeller argument
is passed to tinylabel; see the latter's help documentation for examples.
(#488 @grantmcdermott)tinyplot_add() now evaluates the additional call in the environment from
which tinyplot_add() is called so that it also works in non-base environments
such as in function definitions. Additionally, the call matching is now more
precise, matching only tinyplot() or plt() or their fully-qualified
counterparts (with tinyplot:: prefix). Finally, the internals where these
calls are stored are streamlined, avoiding modifying the user-visible
options(). (#460 @zeileis)tinylabel bugs. (#468 @grantmcdermott)
tinylabel(x, "%") is more precise, preserving unique levels of x through
automatic decimal level determination. Thanks to @etiennebacher for the
bug report in #449.x/y variables, even if the
plot type internally coerces it to factor (e.g., "boxplot")type_text() can now also deal with factor x/y variables by converting
them to numeric which helps to add text to barplots etc. (#470 @zeileis)tinytheme() bugs.
tinytheme() calls now inherit the
correct parameters and spacing. (#475, #481 @grantmcdermott)cex theme settings are now reset correctly. (#482 @grantmcdermott)altdoc from Suggests to Config/Needs/website.
Thanks to @etiennebacher for the suggestion and to @eddelbuettel for help
with the CI implementation.devcontainer.json file for remote testing. (#480 @grantmcdermott)type_text() gains xpd and srt arguments for controlling text clipping
and rotation, respectively. (#428 @grantmcdermott)xlevels (in addition to ylevels) in type_spineplot() for spine plots
with categorical x variable. (#431 @zeileis)plt_add(), to become misaligned in
faceted plots (#313). This also resolves a related alignment + layering issue
specific to the Positron IDE
(positron#7316).
As an aside, tinyplot should now be fully compatible with Positron. (#438 @grantmcdermott)"p"-alike plot types (including "jitter") if y is a factor or character.tinyplot
behaves inside loops, particularly for themed plots where only the final plot
was being drawn in Quarto/RMarkdown contexts. Special thanks to @hadley and @cderv
for helping us debug. (#425 @vincentarelbundock)xlevels argument of type_barplot() could not handle numeric indexes correctly.
(#431 @zeileis)type_hline,
type_vline, type_abline) through better recycling logic. For example,
these types now work correctly across non-by facets. Simultaneously, users
can also call them in a base plot layer, relaxing the requirement that they
must be called as part of a subsequent plot layer via tinyplot_add(). (#422 @grantmcdermott)tinytheme("ridge") regression that was accidentally introduced in
v0.4.0, which was causing a palette mismatch for gradient legends. (#415 @grantmcdermott)"barplot" / type_barplot() for bar plots. This closes out
one of the last remaining canonical base plot types that we wanted to provide
a native tinyplot equivalent for. (#305 and #360 @zeileis and @grantmcdermott)"violin" / type_violin() for violin plots. (#354 @grantmcdermott)tinyplot(..., file = "*.pdf") will now default to using cairo_pdf() if
cairo graphics are supported on the user's machine. This should help to ensure
better fidelity of (non-standard) fonts in PDFs. (#311 @grantmcdermott)
The palette argument now accepts a vector or list of manual colours, e.g.
tinyplot(..., palette = c("cyan4", "hotpink", "purple4")), or
tinytheme("clean", palette = c("cyan4", "hotpink", "purple4")) (#325 @grantmcdermott)
Two new sets of top-level arguments allow for greater axis customization:
xaxb/yaxb control the manual break points of the axis tick marks. (#400 @grantmcdermott)xaxl/yaxl apply a formatting function to change the appearance of the
axis tick labels. (#363, #391 @grantmcdermott)
These x/yaxb and x/yaxl arguments can be used in complementary fashion;
see the new (lower-level) tinylabel function documentation. For example:tinyplot((0:10)/10, yaxb = c(.17, .33, .5, .67, .83), yaxl = "%")
The x/ymin and x/ymax arguments can now be specified directly via the
tinyplot.formula() method thanks to better NSE processing. For example,
instead of having to write
with(dat, tinyplot(x = x, y = y, by = by ymin = lwr, ymax = upr))
users can now do
tinyplot(y ~ x | by, dat, ymin = lwr, ymax = upr)
Underneath the hood, this works by processing these NSE arguments as part of
formula model.frame() and reference against the provided dataset. We plan to
extend the same logic to other top-level formula arguments such as weights
and subset in a future version of tinyplot.
tinyplot(..., cex = <cex>) argument should be respected when using
type = "b". Thanks to @rjknell for report #307 and @vincentarelbundock for
the fix.tinyplot(..., lwd = <lwd>) argument is now correctly passed down to
pt.lwd for type "p", which sets proper line weight for the border of pch
symbols in legend. Report in #319 and fix in #320 by @kscott-1.x and/or y as character variables now triggers the same default
plot type behaviour as factors, e.g. boxplots. (#323 @grantmcdermott)type_points()/"p") now work even if x or y is a factor
or character variable. (#323 @grantmcdermott)tinyplot(..., col = <col>) argument now accepts a numeric index.
(#330 @grantmcdermott)type_text() now accepts non-character labels. (#336 @grantmcdermott)tinyplot(..., pch = <pch>) argument now accepts character literals, e.g.
pch = ".". (#338 @grantmcdermott)type_lines()/"l") now pass on the bg argument to the
drawing function. Thanks to @wviechtb for report in #355 (@zeileis)."boxplot" and "jitter"
types. Thanks to @eddelbuettel for the report in #357 (@grantmcdermott).las = 2 or las = 3. (#369 @grantmcdermott)plt_add() on a
faceted plot, but this appears to be an upstream limitation/bug
positron#7316."p"-alike plot types (including "jitter") if y is a factor or character.
(#387 @grantmcdermott)palette and col arguments,
particularly with respect to recycling behaviour. Thanks to @eddelbuettel for
the report (#352) and @grantmcdermott for the fix (#410).altdoc fix)tinyplot v0.3.0 is a big release with many new features, both internal and user-facing. Related updates are grouped below for easier navigation.
type logic and functional equivalents(Primary PR and author: #222 @vincentarelbundock)
"p", "density", etc.), the
type argument now supports functional equivalents (type_points(),
type_density(), etc.). These new functional types all take the form
type_*().tinyplot(Nile, type = "hist")
and
tinyplot(Nile, type = type_hist())
produce exactly the same result.type_*() variants is that they offer
much more flexibility and control beyond the default case(s). Users can pass
appropriate arguments to existing types for customization and can even define
their own type_<typename>() functions. More information is available in the
dedicated help page for each type (e.g., ?type_hist, ?type_lm, etc.)type system has also allowed us to
introduce a number of new plot types and features (see list below). We have
also simplified our internal codebase, since explicit argument passing
requires less guesswork on our end. Speaking of which, we now recommended that
users explicitly pass ancillary type-specific arguments as part of the
relevant type_*() call. For example,
tinyplot(Nile, type = type_hist(breaks = 30))
is preferable to
tinyplot(Nile, type = "hist", breaks = 30)
While the latter option will still work, we cannot guarantee that argument
passing will work in every situation. (Reason: Passing ancillary type-specific
arguments at the top level of the plot call only works if these do not
conflict with the main arguments of the tinyplot() function itself; see
#267.)type system, please see the dedicated
Plot types vignette
on the website.Visualizations:
type_spineplot() (shortcut: "spineplot") spine plots and
spinograms. These are modified versions of a histogram or mosaic plot,
and are particularly useful for visualizing factor variables. (#233
@zeileis with contributions from @grantmcdermott)type_qq() (shortcut: "qq") for quantile-quantile plots. (#251
@vincentarelbundock)type_ridge() (shortcut: "ridge") for ridge plots aka Joy plots.
(#252 @vincentarelbundock, @zeileis, and @grantmcdermott)type_rug() (shortcut: "rug") adds a rug to an existing plot. (#276
@grantmcdermott)type_text() (shortcut: "text") adds text annotations. (@vincentarelbundock)Models:
type_glm() (shortcut: "glm") (@vincentarelbundock)type_lm() (shortcut: "lm") (@vincentarelbundock)type_loess() (shortcut: "loess") (@vincentarelbundock)type_spline() (shortcut: "spline") (#241 @grantmcdermott)Functions:
type_abline(): line(s) with intercept and slope (#249 @vincentarelbundock)type_hline(): horizontal line(s) (#249 @vincentarelbundock)type_vline(): vertical line(s) (#249 @vincentarelbundock)type_function(): arbitrary function. (#250 @vincentarelbundock)type_summary(): summarize values of y along unique values of x (#274
@grantmcdermott)(Primary PR and authors: #258 @vincentarelbundock and @grantmcdermott)
tinytheme() function provides a convenient mechanism for styling
plots according to a variety of pre-defined themes, e.g. tinytheme("clean").tinytheme() (with no argument) to restore
the default plot aesthetic.tinytheme() sets a hook for a group graphical parameters
by passing them through tpar(). Users can still use tpar() to style their
plots manually by setting individual graphical parameters. But going forward
we expect that most tinyplot users will prefer the convenience of going
through tinytheme().tinyplot() arguments:
flip <logical> allows for easily flipping (swapping) the orientation
of the x and y axes. This should work regardless of plot type, e.g.
tinyplot(~Sepal.Length | Species, data = iris, type = "density", flip = TRUE).
(#216 @grantmcdermott)draw = <draw_funcs> allows users to pass arbitrary drawing functions that
are evaluated as-is, before the main plotting elements. A core use case is
drawing common annotations across every facet of a faceted plot, e.g. text or
threshold lines. (#245 @grantmcdermott)facet.args gains a free = <logical> sub-argument for independently
scaling the axes limits of individual facets. (#253 @grantmcdermott)tpar() gains additional grid.col, grid.lty, and grid.lwd arguments for
fine-grained control over the appearance of the default panel grid when
tinyplot(..., grid = TRUE) is called. (#237 @grantmcdermott)tinyplot_add() (alias: plt_add()) convenience function allows
easy layering of plots without having to specify repeat arguments. (#246
@vincentarelbundock)type_density(joint.bw = <option>) argument. See the
function documentation for details. (#291 @grantmcdermott and @zeileis)tinyplot.density() method). Instead, please rather call
tinyplot(..., type = "density") or tinyplot(..., type = type_density())
on the raw data and pass grouping or facet arguments as needed.
(#284 @grantmcdermott)ribbon.alpha argument in tinyplot() has been deprecated. Use the
alpha argument in type_ribbon() (and equivalents) instead: e.g.,
tinyplot(..., type = type_ribbon(alpha = 0.5)).
tinyplot(..., type = "ribbon", alpha = 0.5) because the latter matches the
top-level alpha argument of tinyplot() itself (and thus modifies the
entire palette, rather than just the ribbon). See our warning about passing
ancillary type-specific arguments above.plt(numeric ~ character) now work correctly, with the
character variable automatically being coerced to a factor. (#219 @zeileis)xlim and ylim when explicitly supplied by the user. (Thanks to
@mclements for code submission #221)ymin or ymax args, now inherit these values from y
(#224 @grantmcdermott)y is a factor now work automatically, dispatching to the new
type_spineplot() type. Thanks to @zeileis for the original suggestion all the
way back in #2 and the eventual solution in #233.type_histogram(free.breaks = <logical>, drop.zeros = <logical>) arguments
enable fine-grained control over this behaviour. (#228 @eleuven and
@grantmcdermott)?type_hist, type_ridge, etc.)New Features:
The axes argument of tinyplot()/plt() gains extra options for
fine-grained control of the plot axes. In addition to the existing logical
(TRUE/FALSE) option, users can now specify one of the following character
keywords (or, just their first letters as a convenient shorthand):
"standard" (with axis, ticks, and labels; equivalent to TRUE),"none" (no axes; equivalent to FALSE),"ticks" (only ticks and labels without axis line),"labels" (only labels without ticks and axis line),"axis" (only axis line and labels but no ticks).Simultaneously, the main plotting functions also gain the xaxt and yaxt
for separately controlling the two axes using the same keyword options. For
example, plt(0:10, xaxt = "l", yaxt = "t") will yield a plot where the x-axis
only contains labels and the y-axis contains both labels and ticks, but no axis
line. (#190 @zeileis)
Support additional boxplot arguments like varwidth, notch, etc. Note
that tinyplot(..., type = "boxplot", boxwidth = <num>) is equivalent to the
boxplot(..., width = <num>); we just use the "box(width)" prefix to avoid
conflicting with the existing tinyplot(..., width) argument.
(#196 @grantmcdermott)
Bug fixes:
type = "density", which was a regression
accidentally introduced in v0.2.0 (#187 @grantmcdermott)x == by, or these two are
functionally identical. (#196 @grantmcdermott)xlab and ylab arguments not respected in some plots. Thanks to @lbelzile
for reporting Issue #203.tinyplot(log(x) ~ x). (#197 @zeileis)tinyplot(mpg ~ wt, data = mtcars, facet = am + vs ~ gear))
now plot all panels correctly, even if some combinations are missing. (#197
@grantmcdermott)Internals:
New features:
type = "n", i.e. empty plot. Since type = "n" implicitly assumes points,
which limits the type of legend that can be drawn alongside the empty plot, we
have also added a companion empty argument that can be used alongside any
plot type. (#157, #167 @grantmcdermott)type = "boxplot". Simultaneously enables plt(numeric ~ factor)
support, first raised in #2, so that a boxplot is automatically plotted if a
numeric is plotted against a factor. (#154 @grantmcdermott)type = "polypath". (#159 @grantmcdermott)type = "rect". (#161 @grantmcdermott)type = "segments". (#163 @grantmcdermott)type = "histogram" (alias type = "hist"). (#164 @grantmcdermott)type = "jitter" (alias type = "j"). (#170 @grantmcdermott)Internals:
Misc:
Our first CRAN submission! This v0.1.0 release includes the following new features and updates:
License:
Breaking changes:
tinyplot() function arguments,
the following two arguments have been renamed (old => new):
par_restore => restore.par (note the change in word order too!)ribbon_alpha => ribbon.alpha
We don't believe that these two arguments are much used in practice. So
hopefully it will only have a negligible effect on existing tinyplot code in
the wild, even though it is a breaking change. (#149 @grantmcdermott)New features:
by. Thanks to @zeileis for detailed feedback and advice around the default
palette choice (a restricted version of the "viridis" palette), as well as
StackOverflow user mnel, whose answer
here provided the inspiration for the
final implementation. (#122 @grantmcdermott)lwd argument for adjusting line widths. Similar to pch,
lty, etc. this arguments also accepts a "by" convenience keyword to
automatically vary line widths by group. (#134 @grantmcdermott)tpar() now accepts standard par() arguments in addition to the
tinyplot-specific ones. This allows users to set or query graphical parameters
via a single convenience function, instead having to invoke tpar and par
separately. (#140 @grantmcdermott)
tpar() has gained some additional parameters for fine-grained
control of global plot defaults, including grid, ribbon.alpha, and various
file.* parameters (see next bullet point).file argument,
alongside corresponding width and height arguments for output customization
(both of which are defined in inches). For example,
tinyplot(..., file = "~/myplot.png", width = 8, height = 5). This
implementation relies on a simple internal wrapper around the traditional R
external graphics devices like png(), pdf(), etc. But it may prove more
convenient, since the current global graphics parameters held in (t)par() are
carried over to the external device too and don't need to be reset. Note that
the appropriate device type is determined automatically by the file extension,
which must be one of ".png", ".jpg" (".jpeg"), ".pdf", or ".svg".
(#143 @grantmcdermott)tinyplot logo. (#148 @grantmcdermott)get_saved_par() function can be used to retrieve the par settings
from immediately before or immediately after the preceding tinyplot call.
This function replaces some older (non-exported) internal functions that
tinyplot was using to restore and control par environments. But it could
also prove help to end users who are looking for additional ways to restore
par settings after the fact. See ?get_saved_par for some examples. (#152
@grantmcdermott)tinyplot/plt gains a new alpha = <numeric[0,1]> convenience argument for
adding transparency to plot elements and colours. Example use:
plt(rnorm(1e3), pch = 19, alpha = 0.3). (#129 @grantmcdermott)bg (or its alias, fill) a numeric in the range
[0,1]. This feature has the same effect as bg = "by" except for the added
transparency. Example use:
tinyplot(lat ~ long | depth, data = quakes, pch = 21, cex = 2, bg = 0.2). (#129
@grantmcdermott)Bug fixes:
tpar(facet.x = ...) args from being passed forward
and set correctly. (#137 @grantmcdermott)type = "density". (#147
@grantmcdermott)Internals:
tinyplot
website.
(#135 @grantmcdermott)inst/tinytest is pushing the install tarball over
CRAN's recommended 5 MB limit. Please note that local testing of the package
requires adding the NOT_CRAN=TRUE environment variable to your .Renviron file
(or, exporting it in your .bashrc/.zshrc/etc. dotfile if you prefer that
approach). (#145 @vincentarelbundock & @grantmcdermott)density grid coords. (#150 @grantmcdermott)IMPORTANT BREAKING CHANGE:
The package has been renamed to tinyplot. (#22 @grantmcdermott)
This package renaming also incorporates the following function changes:
plot2() is replaced by tinyplot() (or its shorthand alias plt()).par2() is replaced by tpar().So, where you used to write...
library(plot2)
plot2(Sepal.Length ~ Petal.Length | Species, iris)
... you should now write:
library(tinyplot)
tinyplot(Sepal.Length ~ Petal.Length | Species, iris)
# Or, use the equivalent shorthand `plt` alias
plt(Sepal.Length ~ Petal.Length | Species, iris)
The package URLs have been updated accordingly:
Many thanks to everyone who provided thoughtful feedback about this prospective name change, especially @zeileis and @vincentarelbundock for kicking off the discussion, as well as the 100+ participants who voted in the social media poll.
For more details about the rational underlying this renaming decision, please see the following GitHub comment, as well as the discussion that preceded it: https://github.com/grantmcdermott/plot2/issues/22#issuecomment-1928472754
Website:
We now have a dedicated website! (#80 @vincentarelbundock)
New features:
cex and bg (alias fill) arguments. The latter also permit
the "by" convenience keyword similar to lty and pch. This is useful for
plotting filled point characters (e.g., pch = 21), where you want a different
colour for the fill and border. (#50, #75 @grantmcdermott)add argument allows new plot2 objects to be added to / on top of the
existing plot window. (#60 @grantmcdermott)plot2(~ Temp | Month, airquality). (#62
@grantmcdermott and @zeileis)plot2(x, type = "density") as an alternative to
plot2(density(x)). Works for both the atomic and one-sided formula methods.
(#66 @grantmcdermott)plot2 gains a new facet argument for drawing faceted plots. Users can
override the default square arrangement by passing the desired number of facet
rows or columns to the companion facet.args helper function. Facets can be
combined with by grouping, or used on their own.
(#83, #91, #94, #96, #101, #103 @grantmcdermott)plot2-specific graphical parameters globally via
the new par2() function (which is modeled on the base par() function). At
the moment only a subset of global parameters, mostly related to legend and
facet behaviour, are exposed in par2. But users can expect that more will be
added in future releases. (#33, #94 @grantmcdermott)Bug fixes:
plot2(rnorm(100)). (#52 etiennebacher)lmar and fmar arguments of par2(). The default
legend margin is par2(lmar = c(1,0, 0.1), which means that there is 1.0 line
of padding between the legend and the plot region (inside margin) and 0.1 line
of padding between the legend and edge of the graphics device (outer margin).
Similarly, the default facet padding is par2(fmar = c(1,1,1,1), which means
that there is a single line of padding around each side of the individual
facets. Users can override these defaults by passing numeric vectors of the
appropriate length to par2(). For example, par2(lmar = c(0,0.1) would shrink
the inner gap between the legend and plot region to zero, but leave the small
outer gap to outside of the graphics device unchanged. (#94 @grantmcdermott)Breaking changes:
palette argument that
unifies the old palette and (deprecated) palette.args arguments. In
addition, the default palette for small groups has been changed from "Okabe-Ito"
to "R4". (#31 and #32 @grantmcdermott)legend argument that unifies the
previous (deprecated) legend.position and legend.args arguments. This
change also enables several enhancements over the old legend behaviour; see
below. (#34 @grantmcdermott)New features:
log. (#15 @etiennebacher)pch and lty arguments now accept a "by" convenience keyword for
automatically adjusting plot characters and line types by groups. (#28
@grantmcdermott)legend argument, including changing
labels, turning of the legend title, and so on. (#34 @grantmcdermott)"pointrange", "errobar", and "ribbon" plot types. (#35
@vincentarelbundock, #40 and #46 @grantmcdermott)grid = TRUE as an alternative to grid = grid(). (#43
@grantmcdermott)Bug fixes:
par(pch=X) globally is now respected. (#20 @grantmcdermott)palette("ggplot2") is now respected. (#44
@grantmcdermott)Breaking changes:
New features:
pch, lty, and col types per group (#5
and #11 by @vincentarelbundock).Bug fixes:
plot2 now works (#13 by @grantmcdermott, thanks
@karoliskoncevicius for reporting).Internals:
plot2.formula (#8 by @zeileis).Project: