44

I used vjust as workaround and elaborate an acceptable distance by try and error. But this is sometimes very time consuming and changes with the font size and the axis scale.

Is there a better method to align the text in the example automatic?

library(ggplot2)

ggplot(data=mtcars, aes(x=hp, y=mpg))+
geom_point()+
theme_bw() +
  geom_vline(xintercept=200, colour="grey") +
  geom_text(aes(x=200, label="the strong cars", y=20), colour="blue", angle=90, vjust = 1.2, text=element_text(size=11))+
  geom_text(aes(x=200, label="the weak cars", y=20), colour="red", angle=90, vjust = -1, text=element_text(size=11))

ggsave(filename="geomline.png", width=5.5, height=2*3, dpi=300)

enter image description here

Jonas Stein
  • 6,826
  • 7
  • 40
  • 72
  • how do you want the alignment to be? vjust=0 and vjust=1 seem to do what they're supposed to, values outside this range are always more excentric. – baptiste Aug 06 '13 at 22:44
  • 1
    I want that the computer looks the fontsize up and places the textbox in the correct distance. So the user will not have to play around with the vjust values. – Jonas Stein Aug 06 '13 at 23:05
  • 1
    I think positioning labels automagically is going to be hard, even if the plot is always going to be a simple one. Have you looked at the [`directlabels`](http://cran.r-project.org/web/packages/directlabels/index.html) package? – SlowLearner Aug 08 '13 at 07:31
  • I think directlabels goes in the right direction. But I found no way to annotate lines like in the example above. – Jonas Stein Aug 08 '13 at 11:45

2 Answers2

48

Another solution for the case of one line labels would be to add a line break before/after and keep the default vjust=0.5.

ggplot(data=mtcars, aes(x=hp, y=mpg)) +
  geom_point() +
  theme_bw() +
  geom_vline(xintercept=200, colour="grey") +
  geom_text(aes(x=200, label="\nthe strong cars", y=20), colour="blue", angle=90, text=element_text(size=11)) +
  geom_text(aes(x=200, label="the weak cars\n", y=20), colour="red", angle=90, text=element_text(size=11))
Rosen Matev
  • 1,828
  • 19
  • 20
  • Easy and effective. I like that! – fdetsch Jan 22 '15 at 15:08
  • 9
    Also, to avoid rendering multiple copies, `annotate` should be used instead of `geom_text`, see https://stackoverflow.com/questions/10952832/ggplot2-is-there-a-fix-for-jagged-poor-quality-text-produced-by-geom-text – Valentas May 25 '17 at 07:44
  • @Valentas if `annotate` does the same thing but better, it would be great to update the answer to use it – stevec Apr 14 '20 at 08:59
2

Another option could be using the geom_textvline function from the great geomtextpath package. This can actually combine the functions geom_text and geom_vline. This package has some create function to create curved, straight automatic text annotations. Check this link for some extra examples. Here is a reproducible example:

library(ggplot2)
library(geomtextpath)
# Using geom_textvline
ggplot(data=mtcars, aes(x=hp, y=mpg)) +
  geom_point() +
  geom_textvline(label = "the strong cars", xintercept = 200, vjust = 1.3) +
  geom_textvline(label="the weak cars", xintercept = 200, vjust = -0.7) +
  theme_bw()

# Using geom_textabline with slope
ggplot(data=mtcars, aes(x=hp, y=mpg)) +
  geom_point() +
  geom_textabline(slope = 0.05, label = "the strong cars", intercept = 10, vjust = 1.3) +
  geom_textabline(slope = 0.05, label="the weak cars", intercept = 10, vjust = -0.7) +
  theme_bw()

Created on 2022-08-25 with reprex v2.0.2

Quinten
  • 35,235
  • 5
  • 20
  • 53
  • in this particular example (set by the OP), this will draw two lines one above the other, which can create funny and not always desired effects. – tjebo Aug 25 '22 at 18:35
  • More importantly, however, it doesn't remove the undesired manual vjust which this question is about – tjebo Aug 25 '22 at 18:41