问题
(note - this is the same piece of work as using multiple size scales in a ggplot, but I'm asking a different question)
I'm trying to construct a plot which shows transitions from one class to another. I want to have circles representing each class, and arrows from one class to another representing transitions.
I'm using geom_segment with arrow() to draw the arrows. Is there any way to:
- make the arrows stop before they reach the circles
- adjust the position so that if there is an arrow in both directions, they are "dodged" rather than overlapping.
I couldn't 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)
回答1:
I thought since nobody has given a solution i would provide an example of package more aimed a this sort of 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 before the circle issue and also when there are reciprocal arrows it will adjusts them with the curved lines as in 2<->5:
(arrrow sizes, line widths, colours etc can of course be modified)
回答2:
I've put together a simple extension of geom_segment, which allows specification of
- shortening at the start and end of the lines
- an amount to offset lines which share a reversed source and destination
It's up on pastebin here: geom_segment_plus.
I used code along the lines of this:
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)
It's definitely not perfect, but it works - you can see a double arrow going to the bottom left point here.
offset, shorten.start and shorten.end are the aes elements added. They can be set to data points, but I haven't figured out how to scale them properly.
来源:https://stackoverflow.com/questions/14647988/arranging-arrows-between-points-nicely-in-ggplot2