【问题标题】:Arranging arrows between points nicely in ggplot2在ggplot2中很好地安排点之间的箭头
【发布时间】:2013-02-01 14:02:00
【问题描述】:

(注意 - 这与 using multiple size scales in a ggplot 的工作相同,但我问的是不同的问题)

我正在尝试构建一个显示从一个类到另一个类的转换的图。我想让圆圈代表每个班级,而从一个班级到另一个班级的箭头代表过渡。

我正在使用 geom_segment 和 arrow() 来绘制箭头。有什么办法:

  • 让箭头在到达圆圈之前停止
  • 调整位置,这样如果两个方向都有箭头,它们会被“躲避”而不是重叠。

我无法让 position="dodge" 在这里做任何有用的事情。

举个例子:

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)

【问题讨论】:

  • 有趣的问题。如果不首先转换基础数据,这在 ggplot 中是不可能直接实现的,但我建议在其他地方使用bending in the lines 来躲避倒数箭头。 Here is an example 在 R 中制作这样的弯曲箭头。虽然它仍然是一个复杂的情节,但我可能会建议您在初始阶段分面的小倍数,所以每个方面只显示流出。

标签: r ggplot2 data-visualization


【解决方案1】:

我想既然没有人给出解决方案,我会提供一个更针对此类问题的包示例:

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)

这至少会在圆圈问题之前解决您的箭头,并且当有倒数箭头时,它会使用曲线调整它们,如2&lt;-&gt;5

(当然可以修改箭头大小、线宽、颜色等)

【讨论】:

  • 看来 2 和 5 之间的曲线是由于多条边在两点之间指向同一方向。出于某种原因,如果两条边的方向相反, autocurve.edges() 似乎不会增加曲率(您甚至可以在此处看到 2->5 是直的)。有什么建议可以强制具有相同方向的重叠边缘的曲率?
【解决方案2】:

我整理了一个 geom_segment 的简单扩展,它允许规范

  • 在行首和行尾缩短
  • 共享反向源和目标的行的偏移​​量

这里的 pastebin 上有:geom_segment_plus

我使用的代码是这样的:

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)

这绝对不是完美的,但它有效 - 你可以看到一个双箭头指向左下角。

offset、shortcut.start 和 short.end 是添加的 aes 元素。它们可以设置为数据点,但我还没有弄清楚如何正确缩放它们。

【讨论】:

  • 为'geom_segment_plus'的原始海报添加评论。这完美地解决了我遇到的问题,但似乎这段代码不适用于对 ggplot 2.0 的更改。有修复的机会吗?我的SO post is here:
  • 我尝试使用您的代码,得到:Error in eval(quote({ : could not find function "eval" 我还从stackoverflow.com/questions/52568493/… 找到了其他版本,但后来我得到:Error in geom_segment_plus(arrow = arrow(length = unit(0.2, "cm")), lineend = "round", : attempt to apply non-function
  • 我更新了 mo-seph 的代码,现在它可以与 ggplot2 v3.3 一起使用:gist.github.com/burchill/9d07c306c90f10a50efae6f2c14e288f
猜你喜欢
  • 1970-01-01
  • 2012-10-18
  • 1970-01-01
  • 1970-01-01
  • 2019-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多