4

Please help me find a universal way to place text at a constant distance from the right side of the plot area as illustrated below. Since the plot area is narrower on the right, unfortunately, the current placement calculation positions the text too far to the left. Note the text is right-aligned.

My last idea: If we knew the distance in centimeters between say x=1 and x=2, we could calculate the position easily. Unfortunately, it's apparently not that easy to get that distance.

FYI: I am not looking to label the lines.

enter image description here Full-size image

library(ggplot2)
library(reshape)
library(gridExtra)

df = data.frame(x =(1:3),One=c(12, 8, 13),Two=c(13, 7, 11),Three=c(11, 9, 11))
df.melt = melt(df, id.vars="x")
xmax = max(df.melt$x); xmin = min(df.melt$x)
ymax = max(df.melt$value); ymin = min(df.melt$value)

dfa = data.frame(x=(xmax-xmin)*1.15+xmin, y=c(11,12,13.5), ann=c("10.1|","1.1|","Texttexttext|"))
dfa.melt = melt(dfa, id.vars=c("x","ann"))

p = ggplot() + 
  geom_line(data=df.melt,  aes(x=x, y=value, color=variable), show_guide=F) +
  geom_text(data=dfa.melt, aes(x=x, y=value, hjust = 1, label=ann), size=3) + 
  coord_cartesian(xlim=c(xmin,xmax), ylim=c(ymin,ymax))

p1 = p + theme(plot.margin=unit(c(1,3,0,0),"cm"), axis.text.y=element_text(size=10))
p2 = p + theme(plot.margin=unit(c(1,3,0,3),"cm"), axis.text.y=element_text(size=35))
p1c <- ggplot_gtable(ggplot_build(p1))
p1c$layout$clip[p1c$layout$name=="panel"] <- "off"
p2c <- ggplot_gtable(ggplot_build(p2))
p2c$layout$clip[p2c$layout$name=="panel"] <- "off"
grid.arrange(p1c, p2c, ncol=2)
Community
  • 1
  • 1
u17
  • 2,776
  • 4
  • 31
  • 43

1 Answers1

3

Because everything is named, it is possible to access any component of the plot using the grid functions.

The problem is ggplot2 creates many viewports and grobs when it draws a plot. So it is is not easy to make changes to this plot. I notice also that the name of grobs and viewports changes for each new execution of the plot. So I tried to get viewports by some criteria (here depth = 4)

#Get the viewports: 
scene.vps <- grid.ls(viewports=T,grobs=F)
scene.flat <- as.data.frame(do.call('cbind',scene.vps))
vps <- subset(scene.flat ,vpDepth == '4')$name[1:2]
vps <- as.character(vps)


# modify the plot by grid.text
depth <- downViewport(vps[1])
grid.text("1.1|",x=unit(1, "npc") - unit(1, "mm"),
                 y=unit(1, "npc") - unit(20, "mm"),
                 just=c("right", "top"))

grid.text("10.1|",x=unit(1, "npc") - unit(1, "mm"),
                  y=unit(1, "npc") - unit(60, "mm"),
                  just=c("right", "top"))

grid.text("Texttexttext|",x=unit(1, "npc") - unit(10, "mm"),
                          y=unit(1, "npc") -unit(2,'mm'),
          just=c("right", "top"))

upViewport(depth)  # come back to the root viewport

depth <- downViewport(vps[2])

grid.text(...

enter image description here

joran
  • 169,992
  • 32
  • 429
  • 468
agstudy
  • 119,832
  • 17
  • 199
  • 261
  • Thanks. Your answer measures from the right-most border of the grid vs the right side of the plot, I think. See [HERE](http://i.stack.imgur.com/Uknt7.png). In addition, it is somewhat hard to position the text at specific y-values. In my example, the text is placed accurately at `y=11` and `y=12`. – u17 Dec 16 '12 at 00:12
  • @Frank yes from the right yes. it is question of reference. Do you need to place the text at y=11,12? – agstudy Dec 16 '12 at 00:48
  • Yes, it would be nice if y-position would relate to chart coordinates. Anyway, with the solution to my other question [(LINK)](http://stackoverflow.com/questions/13867325/get-width-of-plot-area-in-ggplot2), it should be possible. Will finalize my application next year. Thanks for your help on both questions! – u17 Dec 17 '12 at 15:25