Skip to content

directlabels: Adding direct labels to ggplot2 and lattice plots

January 3, 2010

Sometimes it is preferable to label data series instead of using a legend. This post demonstrates one way of using labels instead of legend in a ggplot2 plot.

> library(ggplot2)
> p <- ggplot(dfm, aes(month, value, group = City,
     colour = City)) + geom_line(size = 1) +
     opts(legend.position = "none")
> p + geom_text(data = dfm[dfm$month == "Dec",
     ], aes(label = City), hjust = 0.7, vjust = 1)
directlabel-006.png

The addition of labels requires manual calculation of the label positions which are then passed on to geom_text(). If one wanted to move the labels around, the code would need manual adjustment – label positions need to be recalculated..

This problem is easily solved with the help of directlabels package by Toby Dylan Hocking that “is an attempt to make direct labeling a reality in everyday statistical practice by making available a body of useful functions that make direct labeling of common plots easy to do with high-level plotting systems such as lattice and ggplot2”.

> install.packages("directlabels", repos = "http://r-forge.r-project.org")
> library(directlabels)

The above plot can be reproduced with one line of code.

> direct.label(p, list(last.points, hjust = 0.7,
     vjust = 1))

In addition to several predefined positioning functions, one can also write their own positioning function. For example, placing the rotated labels at the starting values of each series.

> angled.firstpoints <- list("first.points",
     rot = 45, hjust = 0, vjust = -0.7)
> direct.label(p, angled.firstpoints)
directlabel-011.png

I agree with the author’s conclusion that the directlabels package simplifies and makes more convenient the labeling of data series in both lattice and ggplot2.

Thanks to Baptiste for bringing this package to my attention.

9 Comments leave one →
  1. January 3, 2010 11:44 pm

    You may want to have a look at the labcurve function in the Hmisc package by Frank Harrell which had similar functionality for several years.

  2. January 24, 2010 7:05 am

    Hi, I have a silly questions, but do you know how to change text labels to have italic fonts? I tried change the theme for a specific geom_text object, but that does not work. Maybe I am doing something completely wrong, or is it possible that one simply can’t specific italics for text labels (as opposed to axis labels, etc.). cheers.

    • learnr permalink*
      January 24, 2010 11:26 am

      Yes, this is one of the features that is not yet implemented (see here).

      • January 24, 2010 6:42 pm

        Thanks. I hadn’t known that site.

    • August 30, 2011 12:19 pm

      Labels with italic fonts in ggplot2 is supported in the new version of directlabels:

      install.packages("directlabels")
      library(ggplot2)
      iplot <- qplot(Petal.Length,Sepal.Length,data=iris,colour=Species)
      library(directlabels)
      direct.label(iplot,list(fontface="italic","smart.grid"))

      or, continuing the example above:

      p <- ggplot(dfm, aes(month, value, group = City, colour = City)) + geom_line(size = 1)
      direct.label(p, list("last.points",hjust = 0.7, vjust = 1,fontface="italic"))

  3. Alex Brown permalink
    January 25, 2010 4:50 pm

    Here’s a quick way to do this in ggplot:


    # the sample data
    # data frame where each factor is deliberately in non-adjacent rows. try reversing the rep calls and see what happens
    d=data.frame(set=factor(rep(1:4,4)),x=rep(1:4,each=4),val=rnorm(4*4))

    # functions to select the appropriate element to label
    # in-place apply returns original data order
    inplaceapply=function(x,g,fun){o<-order(g);x[o]=do.call(c,tapply(x[o],list(g[o]),fun));x}
    # we want to attach a label to the LAST x element, so
    # last gives a vector which is true only for the last element, expect this is rightmost.
    last=function(x)c(rep(F,length(x)-1),T)
    # generate last element in each factor level
    lastgroup=function(val,group)inplaceapply(val,group,last)
    # test the data
    data.frame(d,last=lastgroup(d$val,d$set))

    # do the ggplot
    require(ggplot2)
    ggplot(d,aes(x=x,y=val,colour=set))+geom_line()+geom_text(subset=.(lastgroup(val,set)),aes(label=val,group=set),position=position_dodge(height=0.1), vjust=-2, hjust=1,cex=3)

    # alternative fun things to try:
    # also try maxgroup. does not remove duplicate maxes.
    whichmax=function(x)x==max(x)
    maxgroup=function(val,group)inplaceapply(val,group,whichmax)
    # then replace lastgroup with maxgroup in the ggplot call

  4. Parth permalink
    May 21, 2014 4:29 pm

    Hi, Thank you for the post!!
    Small question, what if one wants to keep the titles separated.
    For e.g. instead of all City names appearing over “Dec” if one wants the City names to be appearing across different months.

    Thank You in advance!

Trackbacks

  1. ggplot2 resources

Leave a comment