Nothing
### Process data points using the Positioning Method and draw the
### resulting direct labels. This is called for every panel with
### direct labels, every time the plot window is resized.
drawDetails.dlgrob <- function
(x,
### The dlgrob list object. x$method should be a Positioning Method
### list and x$data should be a data.frame with the following
### variables: \describe{
### \item{x,y}{numeric horizontal and vertical positions of direct
### labels, in native units. These are converted to cm units before
### applying the Positioning Method.}
### \item{groups}{factor that indices the different groups, and
### colour indicates the corresponding group colour.}
### \item{hjust and vjust}{(optional) numeric values usually in
### [0,1] that control the justification of the text label relative to
### the x,y position.}
### \item{rot}{(optional) numeric value in [0,360] that specifies
### the degrees which the text should be rotated.}
### \item{cex, alpha, fontface, fontfamily}{(optional) passed to
### gpar.}
### } Additionally, x$debug should be set to TRUE or
### FALSE, and x$axestonative should be a function that converts units
### shown on the axes to native units of x$data[,c("x","y")].
recording
){
## calculate x and y position in cm --- by this time we should have
## done any preprocessing necessary to convert 1d data to 2d data!
cm.data <- x$data
cm.data$x <- convertX(unit(cm.data$x,"native"),"cm",valueOnly=TRUE)
cm.data$y <- convertY(unit(cm.data$y,"native"),"cm",valueOnly=TRUE)
cm.data$groups <- factor(cm.data$groups)
## save original levels for later in case Positioning Methods mess
## them up.
levs <- unique(cm.data[,c("groups","colour")])
code <- as.character(levs$colour)
names(code) <- as.character(levs$groups)
## apply ignore.na function -- these points are not plotted
cm.data <- ignore.na(cm.data)
if(is.null(cm.data$label)){
cm.data$label <- cm.data$groups
}
cm.data <- apply.method(
x$method,
cm.data,
debug=x$debug,
axes2native=x$axes2native)
if(nrow(cm.data)==0)return()## empty data frames can cause many bugs
## Take col from colour or groups.
colour <- cm.data[["colour"]]
cm.data$col <- if(is.null(colour)){
code[as.character(cm.data$groups)]
} else {
colour
}
## defaults for grid parameter values:
defaults <- list(hjust=0.5,vjust=0.5,rot=0)
for(p in names(defaults)){
if(!p %in% names(cm.data))cm.data[,p] <- NA
cm.data[is.na(cm.data[,p]),p] <- defaults[[p]]
}
cm.data <- unique(cm.data)
gpargs <- c("cex","alpha","fontface","fontfamily","col")
gp <- do.call(gpar,cm.data[names(cm.data)%in%gpargs])
if(x$debug){
print(cm.data)
##browser()
}
text.name <- paste0(
"directlabels.text.", x$name)
with(cm.data, grid.text(
label,x,y,hjust=hjust,vjust=vjust,rot=rot,default.units="cm",
gp=gp,
name=text.name))
}
### This environment holds an integer id that will be incremented to
### get a unique id for each dlgrob.
dl.env <- new.env()
dl.env$dlgrob.id <- 0L
dlgrob <- function
### Make a grid grob that will draw direct labels.
(data,
### Data frame including points to plot in native coordinates.
method,
### Positioning Method.
debug=FALSE,
axes2native=identity,
...
){
## increment dlgrob.id to get a unique name because as explained on
## ?grid::gTree "Grob names need not be unique in general, but all
## children of a gTree must have different names."
dl.env$dlgrob.id <- dl.env$dlgrob.id+1L
mstr <- if(is.character(method))method[1] else "NA"
name <- sprintf("GRID.dlgrob.%d.%s", dl.env$dlgrob.id, mstr)
grob(data=data,method=method,debug=debug,axes2native=axes2native,
cl="dlgrob",
name=name,...)
}
direct.label <- structure(function # Direct labels for color decoding
### Add direct labels to a plot, and hide the color legend. Modern
### plotting packages like lattice and ggplot2 show automatic legends
### based on the variable specified for color, but these legends can
### be confusing if there are too many colors. Direct labels are a
### useful and clear alternative to a confusing legend in many common
### plots.
(p,
### The "trellis" or "ggplot" object with things drawn in different
### colors.
method=NULL,
### Positioning Method, which determines the positions of the direct
### labels as a function of the plotted data. If NULL, we examine the
### plot p and try to choose an appropriate default. See
### \code{\link{apply.method}} for more information about Positioning
### Methods.
debug=FALSE
### Show debug output?
){
##alias<< directlabels
if(is.character(method)&&method[1]=="legend")
UseMethod("uselegend")
else
UseMethod("direct.label")
### A plot with direct labels and no color legend.
},ex=function(){
if(require(ggplot2)){
## Add direct labels to a ggplot2 scatterplot, making sure that each
## label is close to its point cloud, and doesn't overlap points or
## other labels.
scatter <- qplot(jitter(hwy),jitter(cty),data=mpg,colour=class,
main="Fuel efficiency depends on car size")
direct.label(scatter)
}
## direct labels for lineplots that do not overlap and do not go off
## the plot.
if(require(nlme) && require(lattice)){
oldopt <- lattice.options(panel.error=NULL)
ratplot <-
xyplot(weight~Time|Diet,BodyWeight,groups=Rat,type='l',layout=c(3,1))
## Using the default Positioning Method (maxvar.qp), the labels are
## placed on the side which is most spread out, so in multipanel
## plots they sometimes end up on different sides.
print(direct.label(ratplot))
## To put them on the same side, just manually specify the
## Positioning Method.
print(direct.label(ratplot,"last.qp"))
lattice.options(oldopt)
}
})
default.picker <- function
### Look at options() for a user-defined default Positioning Method
### picker, and use that (or the hard-coded default picker), with the
### calling environment to figure out a good default.
(f
### Object class to look for (trellis or ggplot).
){
varname <- paste("defaultpf.",f,sep="")
p <- getOption(paste("directlabels.",varname,sep=""))
if(is.null(p))p <- get(varname)
do.call(p,as.list(parent.frame()))
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.