Direct Labels for Multicolor Plots

An extensible framework for automatically placing direct labels onto multicolor 'lattice' or 'ggplot2' plots. Label positions are described using Positioning Methods which can be re-used across several different plots. There are heuristics for examining "trellis" and "ggplot" objects and inferring an appropriate Positioning Method.



Implement a solver for vertical.qp, to avoid depending on the compiled code in quadprog which I guess is not always available.

Define makeContent.dlgrob instead of drawDetails.dlgrob in R-3.0?

image labels: draw a grob on screen instead of assuming it is text. Have a toggle for drawing images and/or text. Handle both in a uniform way in Positioning Methods by just asking for the grob size instead of the text size.

Get rid of dl.summarize and for simplicity?

method for .zoo plots?

handling custom densityplot params in lattice?

problems with plotting color labels in lattice when col= is specified, see etc/individual.R, and gabor.R

see etc/xYplot.R for a problem with plotting some weird trellis objects.

contourplot labels as in lattice::panel.contourplot or C source code in r-source/src/main/plot3d.c

other contourplots, see etc/contour.R


importFrom non-base packages.


ggplot2 does not need to be installed for package checks to pass.


suggest ggplot2 >= 2.0.


Works with new ggplot2 >= internals. (and no longer works with older ggplot2 internals!)


Namespaces fixes to ensure that R CMD check runs cleanly, and that you can use geom_dl() without attaching directlabels to the search path.


geom_dl(show_guide=FALSE) is default.


custom colors for dotplots in lattice, see etc/lattice-custom-colors.R


BUGFIX: bumpup works when there is only 1 group.


use fill if no colour in ggplots.



polygon.methods for lineplots.


projectionSeconds data set and angled.boxes Positioning Method, inspired by Mark Schmidt's prettyPlot.

draw.rects draws a rotated box when rot is specified.


label.endpoints can handle the case (common for scatterplots) where there are several endpoints with the same x value.


geom_dl aes inherits from the colored geom aes.


Doc updates: drawDetails.dlgrob documents interpretation of columns, apply.method uses itemize list, \code{\link{fun}} hyperlinks.


Documentation updates.


Depend on quadprog.

Bugfix for decrease the text size based on previous cex, rather than assuming the previous cex is 1.

Remove follow.points, perpendicular.(lines|grid).

Change with/within/transform/subset to alternatives that do not generate NOTEs during package check.


Fixed: stat_contour(breaks=custom_breaks): From Doug Peterson: Side point: Something else I noticed when playing with this - if any kind of bin adjustment is used within the stat_contour (e.g., stat_contour(aes(colour=..level..), binwidth=50) directlabels ignores the binned contour lines and labels everything (=whatever default contour lines are produced, even if not plotted!). This should also work for specifying custom # of bins in geom_bar.

data("quoted") for R-3.0 package checks.

4 Nov 2012 fix some doc typos.

2.9 --- 25 Sep 2012

Delete several examples to reduce timings.

2.8 --- 13-29 Aug 2012

Attempted submission to CRAN 25 Sept 2012.

top.points uses xlimits to avoid labels going off the left and right sides.

draw.rects: use grid.polygon instead of grid.lines so we can fill the box. set the column fill="transparent" if you don't want the background.

empty.grid: only consider boxes for which the class of the closest point is the target direct label. This avoids weird problems that can happen on smaller plots, where sometimes labels would appear next to another class.

qp.labels: reduce text size if there is not enough space to read all the labels. You can still increase the xlim and ylim if you want to labels to render at full size. This is the best fix I could think of for the following long-standing issue:

how to automatically adjust axes to make direct labels immediately legible? For multipanel plots you would have to adjust all the scales!

qp.labels: respect any predefined vjust for overlap calculation, by calculating top and bottom before and using these in the QP.

qp.labels takes a new argument limits which specifies the lower limit for the bottom of the first label and the upper limit of the top of the last label.

API change: qp.labels takes a function order.labels instead of tiebreak.

Bugfix: pass on ... args in dl.combine.

Bugfix: if only 1 row to call to qp.labels, then just return it.

Bugfix: calc.boxes does not use transform since that was ignoring the cex specified.

2.7 --- 12 July 2012

New lasso.labels Positioning Method that applies the QP solver to both the top and bottom labels.

New tiebreaker argument for qp.labels so we can do that for top.qp as well.

2.6 --- 5 June 2012

In ggplot2 >= 0.9.1, layer$data is an empty list of class "waiver" in the ggplot object, but geom_xxx(data=waiver) results in an error, so we check for this now and use data=NULL when we find a waiver.

2.5 --- 6 April 2012

draw.rects with configurable color, default black.

bugfix for ggplot2 geom_line picker. before we were not actually checking the number of levels of the groups.

bugfixes for scatterplots using perpendicular.grid and [ac]hull.grid.

new check.for.columns function to make sure the data.frames returned by Positioning Functions in apply.method have the necessary info.

bugfix for apply.method restore invariant columns for each group after applying Positioning Method algorithm.

2.4 --- 5 March 2012

Suggest nlme to avoid warning on pkg check.

require(proto) in geom_dl to avoid error if it is called without direct.label.ggplot

2.3 --- 2 March 2012

In apply.method, we look at all groups and determine which columns are invariant in each, then after the Positioning Function is applied, we write these values to the resulting data.frame if it does not contain these variables. That way each individual Positioning Method doesn't have to worry about keeping track of all the weird annotation columns that can be there on input.

Works with ggplot2 0.9.0, including new simplified hiding of the legend, using guides(colour="none")

dlgrobs have names == GRID.dlgrob.method if method is a character string.

Tiebreaking for qp.labels when we are doing lineplots.

2.2 bugfixes

ggplot2 autopicker simpler.

use aes_string instead of aes in direct.label.ggplot

2.1 31 August 2011 -- bugfixes

gapply can take positional arguments like gapply(d,subset,y==max(y))

melt is no longer used in top.bumptwice

2.0 29 August 2011

dl.move and static.labels allow specification of label positions in terms of the displayed axes! Internally, they convert the user-specified numbers to cm.

Figured out how to calculate label bounding boxes for ggplot2, by returning dlgrobs from the draw() method of the new GeomDirectLabel. The special drawDetails.dlgrob method is called within the plotting viewport, so we can calculate the bounding boxes of the text before they are drawn.

In fact all Positioning Methods which take into account visual distance need to calculate visual distance instead of plotting coordinate distance. ie smart.grid tries to find the label position which is closest to the center, but this can be very skewed if x and y axes are not on the same scale. This is now fixed since all coordinates are converted to cm before being passed to Positioning Methods.

fontface and fontfamily for direct labels are now supported even on ggplot2, thanks to the new dlgrob backends! See example(dlcompare).


if(require(pkg)) in examples so you can see the rest even if you don't have pkg


delete ... now to use empty.grid, do i.e. list("get.means","empty.grid") for labels with target points at the means of each point cloud. Positioning Method for removing rows with NA x or y. This is applied before all Positioning Methods in label.positions().

no longer depend on ggplot2/proto for further modularity.

gapply function for applying a Positioning Method to each group, also eliminates need to depend on plyr.

dl.indep ->

eval.list -> apply.method

path example datasets.

redo ggplot2 backend --- analyze layers to determine which has the color.

Respect predefined scale_colour_manual() in ggplot2: I tried to do a hack that looks into p$scales$.scales to turn off the legend (r371), but that didn't work so well, so I went back to the method of just adding a new scale_colour_discrete(legend=FALSE) (r382) You could always set the scale_colour_manual AFTER the call to direct.label(): p <- ggplot(...) p2 <- direct.label(p) p2+scale_colour_manual(...,legend=FALSE) As of r400 I do analysis of the layers of the ggplot object, and turn off the color legend off if there was one. Thus this should be equivalent: p <- ggplot(...)+ scale_colour_manual(...) direct.label(p)

1.2 Positioning Function -> Positioning Method.

1.1 26 nov 2010 delete many examples so CRAN check completes quicker.

1.0 16 nov 2010 initial release attempted to CRAN -- too many examples.

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.


2017.03.31 by Toby Dylan Hocking, 6 months ago

Browse source code at

Authors: Toby Dylan Hocking

Documentation:   PDF Manual  

GPL-3 license

Imports grid, quadprog

Suggests MASS, inlinedocs, ggplot2, lattice, alphahull, nlme, ElemStatLearn, lars, latticeExtra

Imported by QCAtools, dartR.

Depended on by SparseFactorAnalysis, prevR, primerTree.

Suggested by bossMaps, mirt, penaltyLearning, propr, re2r.

See at CRAN