2
votes

In ggplot, I want to label some error bars with asterisks ('*') to indicate significance level. The graph is arranged with category labels on the y axis, so that they are easily legible. This means that the error bars are horizontal, and the *'s need to align vertically with them. However, the symbol '*' is not vertically centred in a line of text, so it gets plotted too high using geom_text.

Reproducible example

set.seed(123)
x = data.frame(grp = LETTERS[1:8], val = sample(10,8))
se = runif(8, 0.1,2)
x$upper = x$val + se
x$lower = x$val - se
x$labs = sample(c('*','**', '***', ''), 8, T)

gg = ggplot(x, aes(grp,val)) +
  geom_point() +
  geom_errorbar(aes(ymax = upper, ymin=lower), width=0.3) +
  scale_y_continuous(limits = c(-2,12)) +
  coord_flip()

gg + geom_text(aes(y=upper+0.2, label=labs), size=8, hjust='left')

enter image description here

I know that I can nudge the label position like this:

gg + geom_text(aes(y=upper+0.2, label=labs), size=8, nudge_x = -0.2, hjust='left')

However, getting the correct value of nudge_x needs to be done in an ad-hoc manner and the correct value varies with size of graphics output, font size, number of categories on the y scale etc. Is there a way to get the labels to automatically align vertically? I tried using geom_point with shape=42 instead of geom_text to draw the asterisks. Although this solves the vertical alignment issue, it introduces its own problem with getting the spacing between a horizontal row of asterisks correct (i.e. getting '**' and '***' to print with the correct separation between adjacent symbols).

1
I haven't tested this, but how much does a vjust adjustment need to be altered with different output sizes, font sizes, etc? - joran
Part of the issue might stem from the fact that textGrobs and pointsGrobs don't align perfectly by design: grid.newpage(); grid.draw(textGrob("test", x = 0.5, y = 0.5)); grid.draw(pointsGrob( x = unit(0.5, "npc"), y = unit(0.5, "npc"), size = unit(0.25, "cm"), pch = 19)). Relative to the text, the point looks a little higher than we would expect it to be. - Mike H.
@joran vjust seems to actually be pretty much immune to changes in y scale, font size, and graphics output size. So simple I feel a little embarrased. If you want to work this up into an answer, I'll accept - dww

1 Answers

2
votes

Just eyeballing it on my machine, it looks like this vjust adjustment seems to work, and I think it may be fairly robust to changes in device output size, font size, etc.

gg + geom_text(aes(y=upper+0.2, label=labs), size=8, hjust='left',vjust = 0.77)