18

I need to find a way to annotate a reference line at the same angle as the reference line itself.

The following statement will produce the reference line and the label above it. However, the slope of the line may change and I need to find a way make sure the annotation is always at the same angle.

plot(1:10,1:10) 
abline(a=8, b=-1)
text(x=4, y=5, "reference line label", srt=-28)

enter image description here

Is there a simple way to do it in R? Thanks in advance

Max C
  • 2,573
  • 4
  • 23
  • 28

4 Answers4

18

One way is by setting the plot aspect ratio, using the asp argument, and then to calculate the angles using the specified asp:

asp <- 2

plot(1:10,1:10, asp=asp) 
abline(a=8, b=-1)
text(x=4, y=5, "reference line label", srt=180/pi*atan(-1*asp))

abline(a=4, b=-2)
text(x=1, y=3, "reference line label", srt=180/pi*atan(-2*asp))

enter image description here

Setting a different asp:

asp <- 0.8

plot(1:10,1:10, asp=asp) 
abline(a=8, b=-1)
text(x=4, y=5, "reference line label", srt=180/pi*atan(-1*asp))

abline(a=4, b=-2)
text(x=1, y=3, "reference line label", srt=180/pi*atan(-2*asp))

enter image description here

Andrie
  • 176,377
  • 47
  • 447
  • 496
14

An addendum to @Andrie's answer: instead of hard-coding the aspect ratio in the plot the first time to get the relative coordinate scales, you can recover the current working aspect ratio with the following function:

getCurrentAspect <- function() {
   uy <- diff(grconvertY(1:2,"user","inches"))
   ux <- diff(grconvertX(1:2,"user","inches"))
   uy/ux
}

So you can create your plot: set asp <- getCurrentAspect(); and proceed with the rest of @Andrie's solution.

For all I know this function exists somewhere in the R ecosystem, but I haven't seen it ...

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
  • Ah, thank you. I faffed around for five minutes with `par("usr")` but couldn't find anything useful. – Andrie Aug 01 '12 at 21:33
  • Thank you so much!!! I was hoping there was a way to avoid calculating the angle but this works too. Thanks – Max C Aug 01 '12 at 21:37
  • 1
    Just to address "For all I know this function exists somewhere in the R ecosystem" -- sadly, it doesn't -- [places where `grconvertX` is referred](https://github.com/wch/r-source/search?q=%22grconvertX%22) and [where the C routines are defined, there are no similar counterparts or other routines calling these](https://github.com/wch/r-source/blob/5a156a0865362bb8381dcd69ac335f5174a4f60c/src/library/graphics/src/init.c#L55-L56) – MichaelChirico Nov 19 '20 at 21:30
  • 1
    Also a note that `par('asp')` is a bit misleading -- `"asp"` is not a part of `par()` (it feels like it should be though?). The only thing I see in `par()` that gets close is to compare the 1st and third elements of `diff(par('usr') * par('plt'))` – MichaelChirico Nov 19 '20 at 21:53
6

A similar solution with ggplot2

data <- data.frame(x = 1:10, y = 1:10)
intercept <- 10
slope <- -1
ggplot(data, aes(x,y)) + geom_point(shape=1) +  
  geom_abline(intercept = intercept, slope = slope) + 
  geom_text(x=4, y=5, label="my label", angle=atan(slope)*180/pi)

with slope 1

intercept <- 10
slope <- -2
ggplot(data, aes(x,y)) + geom_point(shape=1) +  
  geom_abline(intercept = intercept, slope = slope) + 
  geom_text(x=4, y=5, label="my label", angle=atan(slope)*180/pi)

with slope 2

Maiasaura
  • 32,226
  • 27
  • 104
  • 108
  • 1
    I tried a similar solution, but couldn't get it to work. FYI, Your code doesn't work on my machine - the label doesn't have the same slope as the line. – Andrie Aug 01 '12 at 21:26
  • Andrie, doesn't this answer miss your point about the aspect ratio?? – Ben Bolker Aug 01 '12 at 21:27
  • I didn't adjust the actual position of the label in both plots but the angle does match the reference line correctly. – Maiasaura Aug 01 '12 at 21:32
  • PS: @Andrie Not sure why this code doesn't work on your machine. My [session info](https://gist.github.com/3230970) if it helps any. I have a function in my `.rprofile` that removes the default `ggplot2` theme but nothing else is different here. – Maiasaura Aug 01 '12 at 21:35
  • 1
    @Maiasaura It seems as if your default plot device is square. Mine is rectangular. If you change the shape of your plot device, does the plot still work? – Andrie Aug 01 '12 at 21:38
  • not just your default plot device, but your plotting *region*, should be square or nearly so in order for this to (nearly) work ... – Ben Bolker Aug 01 '12 at 21:39
  • getting the angle right (i.e. automatically incorporating the aspect ratio) in ggplot sounds like an interesting challenge .. – Ben Bolker Aug 01 '12 at 22:59
2

Working example for ggplot2:

slope<-1.3
asp<-1
p <- ggplot()
p<-p+scale_x_continuous(limits = c(1, 15), expand = c(0, 0)) 
p<-p+scale_y_continuous(limits = c(-8, 20), expand = c(0, 0)) 
p<-p+geom_abline(intercept = 0, slope = slope)
p<-p+coord_fixed(asp)
p<-p+annotate("text", label = "reference line label", x = 3.5, y = 5,  colour = "red",angle=atan(slope*asp)*180/pi)
p

text with angle:

Armali
  • 18,255
  • 14
  • 57
  • 171
Kobah
  • 21
  • 1