Arrange arrows between points in ggplot2

(note - this is the same job as using multiple size scales in ggplot , but I'm asking another question)

I am trying to build a graph that shows transitions from one class to another. I want circles to represent each class, and arrows from one class to another represent transitions.

I use geom_segment with arrow () to draw arrows. Is there any way:

  • make the arrows stop before they reach the circles.
  • adjust the position so that if there is an arrow in both directions, they "dodge" rather than overlap.

I could not get position = "dodge" to do anything useful here.

As an example:

library(ggplot2) points <- data.frame( x=runif(10), y=runif(10),class=1:10, size=runif(10,min=1000,max=100000) ) trans <- data.frame( from=rep(1:10,times=10), to=rep(1:10,each=10), amount=runif(100)^3 ) trans <- merge( trans, points, by.x="from", by.y="class" ) trans <- merge( trans, points, by.x="to", by.y="class", suffixes=c(".to",".from") ) ggplot( points, aes( x=x, y=y ) ) + geom_point(aes(size=size),color="red",shape=1) + scale_size_continuous(range=c(4,20)) + geom_segment( data=trans[trans$amount>0.6,], aes( x=x.from, y=y.from, xend=x.to, yend=y.to ),lineend="round",arrow=arrow(),alpha=0.5, size=0.3) 

Example graph

+4
source share
2 answers

I put together a simple geom_segment extension that allows you to specify

  • reduction at the beginning and end of lines
  • offsetting amount that separates the return source and destination

This is on pastebin here: geom_segment_plus .

I used the code line by line:

 ggplot( points, aes( x=x, y=y ) ) + geom_point(aes(size=size),color="red",shape=1) + scale_size_continuous(range=c(4,20)) + geom_segment_plus( data=trans[trans$amount>0.3,], aes( x=x.from, y=y.from, xend=x.to, yend=y.to ), lineend="round",arrow=arrow(length=unit(0.15, "inches")), alpha=0.5, size=1.3, offset=0.01, shorten.start=0.03, shorten.end=0.03) 

This is definitely not perfect, but it works - you can see the double arrow going to the bottom left point.

offset, shorten.start and shorten.end add aes elements. They can be set to data points, but I did not understand how to scale them correctly.

enter image description here

+2
source

I thought, since no one gave a solution, I would provide an example of a package more aimed at such a problem:

 vecs <- data.frame(vecs =1:6,size=sample(1:100,6)) edges <- data.frame(from=sample(1:6,9,replace=TRUE), to=sample(1:6,9,replace=TRUE)) library(igraph) g <- graph.data.frame(edges, vertices = vecs, directed = TRUE) coords <- cbind(sample(1:20,6), sample(1:20,6)) plot(g, vertex.size=V(g)$size,vertex.color="white",layout=coords,axes=TRUE) 

This will at least solve your arrows in front of the circle problem, and also when there are arrows in the opposite direction, they will correct them with curved lines, as in 2<->5 :

enter image description here

(markup sizes, line widths, colors, etc., of course, can be changed)

+4
source

All Articles