u17
u17

Reputation: 2824

Place text at a fixed distance from chart

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)

Upvotes: 4

Views: 379

Answers (1)

agstudy
agstudy

Reputation: 121608

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

Upvotes: 3

Related Questions