Annotation aligned with abline

Hi all! I'm trying to align an annotation with an abline, but can't figure out how to determine the correct annotation angle. I'd prefer to set the annotation angle using the abline slope, but I'm instead required to use an angle. I believe that this angle is dependent on the abline slope and the limits and dimensions of the plot, making it tricky.

How can I get the annotation to line up with the abline without hard-coding the angle? Thanks for any suggestions!

library(tidyverse)

test_data <- tribble(
  ~x, ~y,
  0, 1,
  1, 0,
  4, 1
)

my_slope <- 1/3

# angles don't line up due to coord limits
test_data %>% 
  ggplot(aes(x, y)) +
  geom_abline(intercept = 0, slope = my_slope) +
  geom_point() +
  annotate(
    "text",
    x = 2,
    y = 2 * my_slope,
    angle = atan(my_slope) * 180/pi,
    label = "my line"
  )


# line and text line up, but with incorrect coordinate limits
test_data %>% 
  ggplot(aes(x, y)) +
  geom_abline(intercept = 0, slope = my_slope) +
  geom_point() +
  annotate(
    "text",
    x = 2,
    y = 2 * my_slope * 1.1,
    angle = atan(my_slope) * 180/pi,
    label = "my line"
  ) +
  coord_equal()


# I set angle manually, which is error-prone
test_data %>% 
  ggplot(aes(x, y)) +
  geom_abline(intercept = 0, slope = my_slope) +
  geom_point() +
  annotate(
    "text",
    x = 2,
    y = 2 * my_slope * 1.1,
    angle = 37,
    label = "my line"
  )

Created on 2019-03-17 by the reprex package (v0.2.1)

Try using coord_equal() instead of coord_fixed(). Does that work better for you?

library(tidyverse)
#> Warning: package 'purrr' was built under R version 3.5.3

test_data <- tribble(
  ~x, ~y,
  0, 1,
  1, 0,
  4, 1
)

my_slope <- 1/3

#set the axis ratio != 1 and adjust the slope
test_data %>% 
  ggplot(aes(x, y)) +
  geom_abline(intercept = 0, slope = my_slope) +
  geom_point() + coord_equal(ratio = 4) +
  annotate(
    "text",
    x = 2,
    y = 2 * my_slope,
    angle = atan(my_slope * 4) * 180/pi,
    label = "my line"
  )

Created on 2019-03-18 by the reprex package (v0.2.1)

2 Likes

Thanks, this works, but it still seems oddly hard-coded to include a set ratio. In reality I'd like to use whatever the ratio was without the text, rather than setting it to 4 or any other constant. I suppose the ideal way around this would be if geom_text actually had a slope argument in addition to the angle one? Is there a way to determine the current ratio and include that inside of the atan?

You can use layer_scales() to get the ranges of the x and y axes and scale the angle by their ratio.

library(tibble)
library(ggplot2)
library(magrittr)

test_data <- tribble(
  ~x, ~y,
  0, 1,
  1, 0,
  4, 1
)

my_slope <- 1/3

#set the axis ratio != 1 and adjust the slope
plt <- test_data %>% 
  ggplot(aes(x, y)) +
  geom_abline(intercept = 0, slope = my_slope) +
  geom_point()

y_range <- layer_scales(plt)$y$range$range
x_range <- layer_scales(plt)$x$range$range
x_to_y <- (x_range[2] - x_range[1])/(y_range[2] - y_range[1])


plt + coord_equal(ratio = x_to_y) + 
  annotate(
    "text",
    x = 2,
    y = 2 * my_slope,
    angle = atan(my_slope * x_to_y) * 180/pi,
    label = "my line"
  )

Created on 2019-03-18 by the reprex package (v0.2.1)

2 Likes

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.