7

I'm making an animated plot using the ggplot2 and animation packages. Each frame of the animation consists of a map with two bits of information that I want to use as titles/labels.

It seems to me there are two ways of doing this.

  1. Adjust the plot margins so there is no title margin and then use geom_text to add the "titles" as text annotations on the plot.
  2. Add a second title. (I've tried padding a single title with spaces to simulate two titles but this breaks down with repeated plots because of kerning.)

The first approach isn't ideal as I need to use the same plot limits for each frame and I get these from the map extents measured in lat/long. Determining the extra height needed for the labels results in an ugly mish-mash of units. Adding a second title therefore seems semantically more sensible to me but after playing around with annotation_custom, I can't seem to figure it out.

Here's a mock-up of what I'm after, showing the two "titles" and each with separate alignments to ensure they stay in place in repeated frames. I've turned on the plot border to help visualize the position. In the final plot, this would be removed.

Mock-up of ggplot with two titles

Thanks for your help!

Edit

Thanks Baptiste for the sign-posting. I had to use slightly different arguments to (a) get the positioning right and (b) use the same font for both titles. Here's an example:

require(gtable)
require(ggplot2)

## Create the basic plot
df <- data.frame(x=1:10, y=1:10)
gg <- ggplot(df, aes(x,y)) + geom_point() + labs(title="Left") +
    theme(plot.title=element_text(hjust=0))

## Get the title style from the original plot
g <- ggplotGrob(gg)
title_style <- g$grobs[[8]]$gp

## Add the second title and plot
g2 <- gtable_add_grob(g, textGrob("Right", x=1, hjust=1, gp=title_style),
                      t=2, l=4, b=2, r=4, name="right-title")
grid.draw(g2)

Here's the result:

ggplot figure with two titles

jkeirstead
  • 2,881
  • 3
  • 23
  • 26
  • I tried playing with the title_style but I need my grob to be a different color from the rest of the title, so I can't grab the style from the title nor from any other text that is on my graph. Is there another way of changing color of the grob? – zazu Apr 01 '16 at 17:58

3 Answers3

10

try this

p = qplot(1,1) 
g = ggplotGrob(p)

require(gtable)
g = gtable_add_grob(g, grobTree(textGrob("left", x=0, hjust=0), 
                                textGrob("right", x=1, hjust=1)), 
                    t=1, l=4)

grid.draw(g)
baptiste
  • 75,767
  • 19
  • 198
  • 294
  • please could you explain how the values t and l are chosen. For example, setting l equal to 3 or 5 gives quite different results. – user20650 Feb 24 '14 at 23:32
  • 1
    t and l stand for top and left respectively, they correspond to the positions in the gtable layout (a matrix of cells) where you want the grob to be inserted. I found the indices by trial and error (educated guess, rather), knowing roughly the layout of a typical ggplot2 (titles, axes, panel, etc.), but you can do it programmatically by inspecting the names of `g$layout`. – baptiste Feb 24 '14 at 23:37
1

Solution based on grid package

require(ggplot2)
require(grid)

df <- data.frame(x = 1:10, y = 1:10)
gg <- ggplot(df, aes(x, y)) + geom_point() + labs(title = "Left") +
    theme(plot.title = element_text(hjust = 0))
gg
grid.text("Right", x = unit(0.95, "npc"), y = unit(0.96, "npc"))
Stepan S. Sushko
  • 1,250
  • 1
  • 9
  • 5
0

alternative with annotate and clipping turned off (not recommended)

p = qplot(1,1) + annotate("text", label="left", 
                          x=-Inf, y=Inf, vjust=-1, hjust=0) 
g = ggplotGrob(p)
g$layout$clip[g$layout$name == "panel"] = "off"
grid.draw(g)
baptiste
  • 75,767
  • 19
  • 198
  • 294