legendplot provides tools to combine standard R plots,
or rgl 3D
plots, with a legend representing either a continuous color scale or a
categorical (factor) legend.
The basic graphics device only provides the legend()
function for adding legends, with the problem that it can obscure the
main plot; furthermore, it is only suitable for categorical values and
is not useful for adding a continuous color scale. The rgl
package only offers legend3d(), which incorporates the
standard legend as a bitmap background for the current RGL subscene.
legendplot (currently) provides the following main
functions:
splot(),
spoints(), simage(), and
spersp().fplot() and
fpoints().rgl plots:
splot3d(),
spoints3d(), spersp3d() and
sshade3d().fplot3d(),
fpoints3d() and fshade3d().scolor(),
jet.colors()and hot.colors()fcolor(),
hcld.colors() and cat.colors().rgl tools: new3d(),
viewpoint (e.g. setviewpoint3d()) and mouse actions
(e.g. setmouse3d()) utilities.Other packages that may be of interest are:
plot3D:
Plotting Multi-Dimensional Data.ggplot2:
Create Elegant Data Visualisations Using the Grammar of Graphics.plotly: Create
Interactive Web Graphics via plotly.js.Nevertheless, I prefer standard or rgl graphics, mainly
because they render faster when dealing with large amounts of data (also
following the “keep it small and simple”, KISS,
principle).
The base function for a continuous legend is splot(). It
splits the plotting region into a main panel and a legend strip showing
a continuous color scale (based on fields::image.plot()).
After calling this function, the main graph can be draw as usual. For
example:
scale.range <- range(mtcars$mpg)
res <- splot(slim = scale.range, legend.lab = "mpg")
with(mtcars,
plot(hp, qsec, col = scolor(mpg, slim = scale.range),
pch = 16, cex = 1.5, main = "Motor Trend Car Road Tests")
)scolor() maps a numeric vector to colors from a
continuous palette, such as:
jet.colors(): rainbow-style palette (similar to MATLAB
jet).hot.colors(): useful for values ranging from zero to a
maximum (e.g. densities).splot() can be also used with add = TRUE to
attach a legend to an existing plot. For instance, several plots can
share a common color scale:
set.seed(1)
nx <- c(40, 40)
x1 <- seq(-1, 1, length.out = nx[1])
x2 <- seq(-1, 1, length.out = nx[2])
trend <- outer(x1, x2, function(x, y) x^2 - y^2)
y <- trend + rnorm(prod(nx), 0, 0.1)
scale.range <- c(-1.2, 1.2)
scale.color <- jet.colors(256)
old.par <- par(mfrow = c(1, 2), omd = c(0.05, 0.85, 0.05, 0.95))
image(x1, x2, trend, zlim = scale.range, main = "Trend", col = scale.color)
image(x1, x2, y, zlim = scale.range, main = "Data", col = scale.color)
par(old.par)
splot(slim = scale.range, col = scale.color, legend.shrink = 0.7, add = TRUE)The package also supplies high-level functions that make this pattern
automatic. The sxxxx() family of functions
(spoints(), simage() and
spersp()) draws the color-scale legend and the
corresponding base plot (plot(), image() or
persp()), with the appropriate colors, in a single
call:
with(mtcars,
spoints(hp, qsec, mpg, main = "Motor Trend Car Road Tests",
xlab = "Horsepower", ylab = "1/4 mile time",
legend.lab = "Miles per gallon")
)These functions are “compatible” with the mfcol and
mfrow graphics parameters:
old.par <- par(mfrow = c(1, 2))
spersp(x1, x2, trend, slim = scale.range, main = "Trend", zlab = "y", legend = FALSE)
simage(x1, x2, y, slim = scale.range, main = "Data", legend.mar = 10, legend.width = 3)All of them share the same legend-related arguments as
splot(), and accept legend = FALSE to draw the
main plot without a legend. By default, the graphical parameters are
reset to the values before entering the function. If
reset = FALSE they will not be restored to make it possible
to add more features to the plot (e.g. using functions such as points or
lines). The graphical parameters can be restored using the
old.par returned values or by calling function
par.reset().
fplot() is the categorical counterpart of
splot(): instead of a color bar it draws a classic
factor-level legend (with boxes, points or line segments), using
legend() internally.
f <- as.factor(mtcars$cyl)
res <- fplot(levels(f), col = cat.colors(nlevels(f)), type = "point",
legend.lab = "cyl")
with(mtcars, plot(hp, qsec, col = fcolor(f, col = res$col),
pch = 16, cex = 1.5, main = "Motor Trend Car Road Tests"))fcolor() maps a factor (or a vector coercible to one) to
colors, using a categorical palette such as hcld.colors()
(based on hcl.colors() “Dark 3”) or
cat.colors() (based on ColorBrewer 2.0).
The plot shown above can also be generated with the following command:
with(mtcars,
fpoints(hp, qsec, f = cyl, col = cat.colors(cyl),
main = "Motor Trend Car Road Tests")
)Currently, only the high-level function fpoints() has
been implemented. Users can follow the same approach shown previously to
generate other types of graphs or to develop additional plot
functions.
rgl 3D plots with legendsThe same ideas extend to interactive 3D scenes built with the
rgl package. splot3d() and
fplot3d() split the active rgl device into a
main subscene and a legend subscene. After calling one of these
functions, rgl plotting functions can be used as usual. For
example:
library(rgl)
# Use `open3d()` or `new3d()` to open a new device.
scale.range <- range(mtcars$mpg)
splot3d(slim = scale.range, legend.lab = "mpg")
with(mtcars,
plot3d(hp, qsec, wt, type = "s",
col = scolor(mpg, slim = scale.range))
)new3d() serves as a replacement for the
open3d() and clear3d() functions1. It opens a new device
if none exists (or if argument open = TRUE is set) and,
otherwise, clears the current one. In addition, it changes several of
the default mouse actions in ‘rgl’, assigning the middle button to zoom
(via setmouse3d()), the right button to pan (via
pan3d()), and enabling a double-click with the left button
to restore the scene’s default viewpoint (via dbltrack3d();
keeping the mouse acting as a virtual trackball, rotating the scene,
when this button is held down). Unfortunately, these mouse actions
currently do not work with RMarkdown documents.
High-level 3D plot functions are also available, named in the form
sxxx3d() and fxxx3d(), which allow the
corresponding 3D graph to be plotted along with a legend, either
continuous or categorical, in a single call. For example, the plot shown
above could be generated with the following command:
Similarly, fpoints3d() draws a 3D scatter plot with a
categorical legend, spersp3d() draws a 3D surface plot with
a continuous color scale, and sshade3d() or
fshade3d() draw a colored triangular mesh together with a
continuous or categorical legend, respectively. As a final example, the
topography of Auckland’s Maunga Whau volcano (bundled as the
volcanom mesh) can be displayed with the following
code:
rgl utilitiesBeyond the plotting functions above, legendplot also
provides a few usefull tools for working with rgl
plots:
vb2tri3d(): computes one value per triangle from values
given at the vertices of a mesh (used by sshade3d() when
meshColor = "facesvertices").setviewpoint3d(), addviewpoint3d(),
getviewpoints3d(), lsviewpoints3d(),
rmviewpoints3d(), getview3d() and
setview3d(): manage (save, list, restore…) named
rgl user viewpoints.setmouse3d(), pan3d() and
dbltrack3d(): configure rgl mouse actions
(used internally by new3d()).axis3(): draws a 3D axis with control over tick length,
tick angle and label position (used internally by
fplot3d()).See the function reference pages for the full list of arguments and additional examples.
Note that it is not necessary to use these functions in
RMarkdown code chunks (see rgl::rglwidget()
and Documents
with ‘rgl’ Scenes).↩︎