Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add multiple arrows to a path according to line direction using ggplot2?

I have a data frame that I want to plot a path from. The data frame also indicates the direction the arrows should have. I have been using the ggplot2 package and the geom_path() function for this, however, I want to add arrows that indicate the direction of the path. I used the arrow() function but I don't know how to make the arrows the way I would like (example below).

library(ggplot2)

X <- c(0.596, 0.641, 0.695, 0.741, 0.788, 0.837,
       0.887, 0.937, 0.993, 0.984, 0.934, 0.886,
       0.838, 0.778, 0.738, 0.681, 0.642, 0.593)

Y <- c(23.630, 24.085, 24.643, 25.067, 25.491, 25.899,
       26.305, 26.670, 27.049, 27.025, 26.836, 26.636,
       26.429, 26.152, 25.965, 25.664, 25.442, 24.510)

Direction <- c(rep('up', 9), rep('down', 9))

DF <- data.frame(X, Y, Direction)

ggplot(data = DF,
       aes(x = X,
           y = Y)) +
  geom_path(arrow = arrow(ends = "both"))

ggplot2 result

enter image description here

Desired result

enter image description here

like image 655
Daniel Valencia C. Avatar asked Dec 06 '21 17:12

Daniel Valencia C.


Video Answer


1 Answers

I'd split your path in segments and use geom_segment. Although the direction will be given by starting and end point in geom_segment, you will still need a grouping variable for your two paths, in order to avoid an ugly arrow between the two paths. Instead, you will get a barely noticeable gap. However, if you wish not to have this gap, omit the grouping step (group_by).

You can change the look of the arrows following this popular thread.

Also maybe you want to have a look at the metR package, there is a geom that creates arrows based on vectors

library(tidyverse)

X <- c(0.596, 0.641, 0.695, 0.741, 0.788, 0.837, 0.887, 0.937, 0.993, 0.984, 0.934, 0.886, 0.838, 0.778, 0.738, 0.681, 0.642, 0.593)
Y <- c(23.630, 24.085, 24.643, 25.067, 25.491, 25.899, 26.305, 26.670, 27.049, 27.025, 26.836, 26.636, 26.429, 26.152, 25.965, 25.664, 25.442, 24.510)
Direction <- c(rep('up', 9), rep('down', 9))

DF <- data.frame(X, Y, Direction)

DF %>%
group_by(Direction) %>%
mutate(xend = lead(X), yend = lead(Y)) %>%
ggplot( aes(x = X, y = Y)) +
  geom_segment(aes(xend = xend, yend = yend), arrow = arrow())

enter image description here

like image 59
tjebo Avatar answered Sep 20 '22 12:09

tjebo