News
If you are viewing this file on CRAN, please check the latest NEWS on our website where the formatting is also better.
0.2.1.99 (dev version)
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.
New plot type
processing system (#222 @vincentarelbundock):
- In addition to the standard character labels (e.g.,
"p"
,"density"
), thetype
argument now supports functional equivalents (e.g.,type_points()
,type_density()
. These new functional types all take the formtype_*()
. - The character and functional types are interchangeable. For example,
tinyplot(Nile, type = "hist")
andtinyplot(Nile, type = type_hist())
produce exactly the same result. - The main advantage of the functional
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 owntype_<typename>()
functions. - On the development side, overhauling the
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 totinyplot(Nile, type = "hist", breaks = 30)
. While the latter option will still work in this particular case, we cannot guarantee that it will for other cases. (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 thetinyplot()
function itself; see #267.) - Some minor breaking changes were unavoidable; see further below.
- For more details on the new
type
system, please see the dedicated Plot types vignette on the website.
New plot types:
- 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 ofy
along unique values ofx
(#274 @grantmcdermott)
Other new features:
- New
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 afree = <logical>
sub-argument for independently scaling the axes limits of individual facets. (#253 @grantmcdermott)
tpar()
gains additionalgrid.col
,grid.lty
, andgrid.lwd
arguments for fine-grained control over the appearance of the default panel grid whentinyplot(..., grid = TRUE)
is called. (#237 @grantmcdermott)- The new
tinyplot_add()
(alias:plt_add()
) convenience function allows easy layering of plots without having to specify repeat arguments. (#246 @vincentarelbundock) - The new
tinytheme()
function provides a convenient mechanism for styling plots according to a variety of pre-defined themes, e.g.tinytheme("clean")
. Users can also add their own custom themes or tweak an existing theme. Themes are persistent and will affect all subsequent plots until they are explicitly reset, e.g. by callingtinytheme()
(with no argument) to restore the default plot aesthetic. Behind the scenes,tinytheme()
sets a hook for a group graphical parameters by passing them throughtpar()
. Users can still usetpar()
to style their plots by manually setting individual graphical parameters. But going forward we expect that most tinyplot users will prefer the convenience of going throughtinytheme()
. More details are provided in the dedicated Themes vignette on the website. (#258 @vincentarelbundock and @grantmcdermott)
Breaking changes:
- There are a few breaking changes to grouped density plots. (#284 @grantmcdermott)
- The default smoothing bandwidth is now computed independently for each data subgroup, rather than being computed from the joint density. Users can still opt into using a joint bandwidth by invoking the
type_density(joint.bw = <option>)
argument. See the function documentation for details. - Grouped and/or faceted plots are no longer possible on density objects (i.e., via the
tinyplot.density()
method). Instead, please rather calltinyplot(..., type = "density")
ortinyplot(..., type = type_density())
on the raw data and pass grouping or facet arguments as needed.
- The default smoothing bandwidth is now computed independently for each data subgroup, rather than being computed from the joint density. Users can still opt into using a joint bandwidth by invoking the
- The
ribbon.alpha
argument intinyplot()
has been deprecated. Use thealpha
argument intype_ribbon()
(and equivalents) instead: e.g.,tinyplot(..., type = type_ribbon(alpha = 0.5))
.- Aside: Please note that this is not equivalent to using
tinyplot(..., type = "ribbon", alpha = 0.5)
because the latter matches the top-levelalpha
argument oftinyplot()
itself (and thus modifies the entirepalette
, rather than just the ribbon). See our warning about passing ancillary type-specific arguments above.
- Aside: Please note that this is not equivalent to using
Bug fixes:
- Better preserve facet attributes, thus avoiding misarrangement of facet grids for density and histogram types. (#209 @zeileis)
- Plots of the form
plt(numeric ~ character)
now work correctly, with the character variable automatically being coerced to a factor. (#219 @zeileis) - Respect
xlim
andylim
when explicitly supplied by the user. (Thanks to @mclements for code submission #221) - Axis titles for flipped (horizontal) boxplots are appropriately swapped too. (#223 @grantmcdermott)
- Ribbon plots without
ymin
orymax
args, now inherit these values fromy
(#224 @grantmcdermott) - Plots where
y
is a factor now work automatically, dispatching to the newtype_spineplot()
type. Thanks to @zeileis for the original suggestion all the way back in #2 and the eventual solution in #233.
Internals:
- Continued modularization/abstraction of the code logic. (#214 @vincentarelbundock)
- Major internal refactor of the type drawing and data processing. (#222 @vincentarelbundock)
Misc:
- Documentation improvements, e.g. explicit guidance on how to specify multiple grouping variables (thanks to @strengjacke for reporting #213).
0.2.1
New Features:
- The
axes
argument oftinyplot()
/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 toTRUE
),"none"
(no axes; equivalent toFALSE
),"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).
xaxt
andyaxt
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 thattinyplot(..., type = "boxplot", boxwidth = <num>)
is equivalent to theboxplot(..., width = <num>)
; we just use the “box(width)” prefix to avoid conflicting with the existingtinyplot(..., width)
argument. (#196 @grantmcdermott)
Bug fixes:
- Fix duplicate plots produced with
type = "density"
, which was a regression accidentally introduced in v0.2.0 (#187 @grantmcdermott) - Ensure correct boxplot positioning if
x
==by
, or these two are functionally identical. (#196 @grantmcdermott) xlab
andylab
arguments not respected in some plots. Thanks to @lbelzile for reporting Issue #203.- Avoid triggering an inadvertent legend when a function transformation of x is plotted against x itself,
tinyplot(log(x) ~ x)
. (#197 @zeileis) - Facets with interactions and/or multivariate formulas (e.g., complex grid arrangements like
tinyplot(mpg ~ wt, data = mtcars, facet = am + vs ~ gear)
) now plot all panels correctly, even if some combinations are missing. (#197 @grantmcdermott) - Fix alignment of facet titles when axes are logged. (#207 @grantmcdermott)
- Consistent decimals for gradient legends (#277 @grantmcdermott)
Internals:
- Continued modularization of the main code logic. (#192 & #198 @vincentarelbundock)
- Revamped formula processing that allows for better sanity checking and edge-case logic. (#197 @zeileis)
0.2.0
New features:
- Support for additional plot types:
type = "n"
, i.e. empty plot. Sincetype = "n"
implicitly assumes points, which limits the type of legend that can be drawn alongside the empty plot, we have also added a companionempty
argument that can be used alongside any plot type. (#157, #167 @grantmcdermott)type = "boxplot"
. Simultaneously enablesplt(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"
(aliastype = "hist"
). (#164 @grantmcdermott)type = "jitter"
(aliastype = "j"
). (#170 @grantmcdermott)
Internals:
- The main codebase has been significantly refactored (modularized), which should simplify future maintenance and enable better user-level error messages (#171, #173 @vincentarelbundock)
Misc:
- Various documentation improvements.
0.1.0
Our first CRAN submission! This v0.1.0 release includes the following new features and updates:
License:
- Formally switch to Apache 2.0 license. (#141 @grantmcdermott)
Breaking changes:
- To ensure consistent “dot.case” style for all
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
tinyplot
code in the wild, even though it is a breaking change. (#149 @grantmcdermott)
New features:
- Gradient legends are now supported if a continuous variable is passed to
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) - Ordered factors now inherit a discrete sequential color palette (“viridis”) by default. Thanks to @zeileis for the suggestion. (#130 @grantmcdermott)
- Support user-supplied polygons. (#127 @grantmcdermott)
- Support for the
lwd
argument for adjusting line widths. Similar topch
,lty
, etc. this arguments also accepts a “by” convenience keyword to automatically vary line widths by group. (#134 @grantmcdermott) tpar()
now accepts standardpar()
arguments in addition to thetinyplot
-specific ones. This allows users to set or query graphical parameters via a single convenience function, instead having to invoketpar
andpar
separately. (#140 @grantmcdermott)- As an aside,
tpar()
has gained some additional parameters for fine-grained control of global plot defaults, includinggrid
,ribbon.alpha
, and variousfile.*
parameters (see next bullet point).
- As an aside,
- Users can write plots directly to disk using the new
file
argument, alongside correspondingwidth
andheight
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 likepng()
,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) - We have a shiny new
tinyplot
logo. (#148 @grantmcdermott) - The new
get_saved_par()
function can be used to retrieve thepar
settings from immediately before or immediately after the precedingtinyplot
call. This function replaces some older (non-exported) internal functions thattinyplot
was using to restore and controlpar
environments. But it could also prove help to end users who are looking for additional ways to restorepar
settings after the fact. See?get_saved_par
for some examples. (#152 @grantmcdermott) tinyplot
/plt
gaina a newalpha = <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)- Similar to the preceding news item, transparency can be added to (grouped) background fill by passing
bg
(or its alias,fill
) a numeric in the range[0,1]
. This feature has the same effect asbg = "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:
- Fixed bug that prevented
tpar(facet.x = ...)
args from being passed forward and set correctly. (#137 @grantmcdermott) - Fixed bug where custom legends weren’t working with
type = "density"
. (#147 @grantmcdermott)
Internals:
- We no longer ship the vignette(s) with the built package. This helps to reduce the size of the installation tarball and also avoids some redundancy with the actual help documentation (since many of the examples are the same). Note that the vignettes are all still rendered and available online at the
tinyplot
website. (#135 @grantmcdermott) - Similarly, we anticipate skipping tests on CRAN since the large suite of test snapshots (images) held in
inst/tinytest
is pushing the install tarball over CRAN’s recommended 5 MB limit. Please note that local testing of the package requires adding theNOT_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) - Update some test snapshots to match slight changes in the way that R 4.4.0 calculates
density
grid coords. (#150 @grantmcdermott)
0.0.5
IMPORTANT BREAKING CHANGE:
The package has been renamed to tinyplot. (#22 @grantmcdermott)
This package renaming also incorporates the following function changes:
plot2()
is replaced bytinyplot()
(or its shorthand aliasplt()
).par2()
is replaced bytpar()
.
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:
- GitHub: https://github.com/grantmcdermott/tinyplot
- Website: https://grantmcdermott.com/tinyplot
- R-universe: https://grantmcdermott.r-universe.dev/tinyplot
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
0.0.4
Website:
We now have a dedicated website! (#80 @vincentarelbundock)
New features:
- Support for
cex
andbg
(aliasfill
) arguments. The latter also permit the “by” convenience keyword similar tolty
andpch
. 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) - Support for filled density plots. (#58 @grantmcdermott)
- The new
add
argument allows new plot2 objects to be added to / on top of the existing plot window. (#60 @grantmcdermott) - Support for one-sided formulas, e.g.
plot2(~ Temp | Month, airquality)
. (#62 @grantmcdermott and @zeileis) - Support for
plot2(x, type = "density")
as an alternative toplot2(density(x))
. Works for both the atomic and one-sided formula methods. (#66 @grantmcdermott) - Support for “area” type plots as a special case of ribbon plots. (#68 @grantmcdermott)
- Partial matching for palette keywords. (#74 @grantmcdermott)
plot2
gains a newfacet
argument for drawing faceted plots. Users can override the default square arrangement by passing the desired number of facet rows or columns to the companionfacet.args
helper function. Facets can be combined withby
grouping, or used on their own. (#83, #91, #94, #96, #101, #103 @grantmcdermott)- Users can now control
plot2
-specific graphical parameters globally via the newpar2()
function (which is modeled on the basepar()
function). At the moment only a subset of global parameters, mostly related to legend and facet behaviour, are exposed inpar2
. But users can expect that more will be added in future releases. (#33, #94 @grantmcdermott)
Bug fixes:
- Y-label correctly prints if a function was used for the atomic plot method, e.g.
plot2(rnorm(100)
. (#52 etiennebacher) - Ribbon plot types are now automatically ordered by the x variable. (#54 @grantmcdermott)
- Interval plots like ribbons, errorbars, and pointranges are now correctly plotted even if a y variable isn’t specified. (#54 @grantmcdermott)
- Correctly label date-time axes. (#77 @grantmcdermott and @zeileis)
- Improved consistency of legend and facet margins across different plot types and placement, via the new
lmar
andfmar
arguments ofpar2()
. The default legend margin ispar2(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 ispar2(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 topar2()
. 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) - Fix bug where grid wasn’t auto-expanding correctly for area plots. (#92 @grantmcdermott)
0.0.3
Breaking changes:
- Colour palettes are now controlled via a single
palette
argument that unifies the oldpalette
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) - Legends are now controlled via a single
legend
argument that unifies the previous (deprecated)legend.position
andlegend.args
arguments. This change also enables several enhancements over the old legend behaviour; see below. (#34 @grantmcdermott)
New features:
- Add support for the argument
log
. (#15 @etiennebacher) - Add support for grouped density plots. (#18 @grantmcdermott)
- Add support for (both grouped and non-grouped) “c”, “h”, “s”, and “S” types. (#26 @grantmcdermott)
- Both the
pch
andlty
arguments now accept a “by” convenience keyword for automatically adjusting plot characters and line types by groups. (#28 @grantmcdermott) - Add outside (“!”) placement support for remaining legend keywords, e.g. “top!”, “left!”, “topright!”, etc. Users also gain finer control over many other aspects of the legend via the new unified
legend
argument, including changing labels, turning of the legend title, and so on. (#34 @grantmcdermott) - Add support for
"pointrange"
,"errobar"
, and"ribbon"
plot types. (#35 @vincentarelbundock, #40 and #46 @grantmcdermott) - Support
grid = TRUE
as an alternative togrid = grid()
. (#43 @grantmcdermott)
Bug fixes:
- Setting
par(pch=X)
globally is now respected. (#20 @grantmcdermott) - Fix x-axis scale/index when y is NULL. (#24 @grantmcdermott)
- Setting a global palette, e.g.
palette("ggplot2")
is now respected. (#44 @grantmcdermott)
0.0.2
Breaking changes:
- Legend defaults have been changed. The default position is now “right!” and drawn without a border, i.e. bty = “n” (#14 by @grantmcdermott).
New features:
- Allow users to specify different
pch
,lty
, andcol
types per group (#5 and #11 by @vincentarelbundock).
Bug fixes:
- Adding further elements to
plot2
now works (#13 by @grantmcdermott, thanks @karoliskoncevicius for reporting).
Internals:
- Better formula parsing for
plot2.formula
(#8 by @zeileis). - Unit testing scaffolding based on tinysnaphot (#11 by @vincent).
Project:
- @vincentarelbundock and @zeileis have joined the project as core contributors. 🎉
0.0.1
- Initial release on GitHub.