symbolrush
symbolrush

Reputation: 7457

Add arrow at the end of a `geom_segment` instead of pointing to the end of a `geom_segment` in `ggplot2`?

Is there a possibility to add the arrow head at the end of a geom_segment instead of having the arrow head pointing to the end of a geom_segment in ggplot2?


An example:

enter image description here


What I did so far:

The code that produced the plot above is manually tweaked and only works for a given plot size:

ggplot() + 
  geom_segment(aes(x = 0, y = 1, xend = 1, yend = 1), arrow = arrow()) + 
  geom_segment(aes(x = 0, y = 0, xend = 1.05, yend = 0), arrow = arrow()) +
  ylim(-1, 2)

With another plot size, the code does produce something different that is not what I want:

enter image description here

Therefore I'm on the search for an option inside arrow() (I did not find something useful, as ends = "last" is the default value and produces the same plots as shown above..) or an alternative geom_. Inside arrow().

Any hints?


The comments from @mnm do not do what I am searching for:

ggplot() + 
  geom_segment(aes(x = 0, y = 1, xend = 1, yend = 1), arrow = arrow(ends = "last")) + 
  geom_segment(aes(x = 0, y = 0, xend = 1.01, yend = 0), arrow = arrow(ends = "last")) +
  ylim(-1, 2)

enter image description here

Upvotes: 1

Views: 3502

Answers (1)

Jon Spring
Jon Spring

Reputation: 66500

I don't know a way to do this natively with geom_segment, but you could make a function to help with this. It modifies the ending coordinates to extend the length as much as the arrow_length term specifies.

geom_segment_extra <- function(x, y, xend, yend, arrow_length) {
  angle = atan2(yend - y, xend - x)  # Trig reminder from https://stackoverflow.com/a/34617867/6851825
  xend = xend + arrow_length * cos(angle)
  yend = yend + arrow_length * sin(angle)

  list(    # ggplot accepts list objects as new layers
    geom_segment(aes(x = x, y = y, xend = xend, yend = yend), arrow = arrow()) 
  )
}

Then we can use it. Note how the first geom_segment_extra just repeats the normal segment appearance, while adding arrow_length = 0.1 extends it by 0.1 unit:

ggplot() +
  geom_segment(aes(x = 0, y = 1, xend = 1, yend = 1), arrow = arrow()) + 
  geom_segment_extra(0, 0.9, 1, 0.9, arrow_length = 0) +
  geom_segment_extra(0, 0.8, 1, 0.8, arrow_length = 0.1) +
  scale_x_continuous(breaks = 0.2*0:100)

enter image description here

Upvotes: 2

Related Questions