11

我已经生成了一个图表:

library(DiagrammeR)
grViz("
digraph boxes_and_circles {

  # a 'graph' statement
  graph [layout = neato, overlap = true, fontsize = 10, outputorder = edgesfirst]

  # several 'node' statements
  node [shape = circle,
  fontname = Helvetica]
  A [pos = '1,1!']; 
  B [pos = '0,2!']; 
  C [pos = '1.5,3!']; 
  D [pos = '2.5,1!']; 
  E [pos = '4,1!']; 
  F [pos = '4,2!']; 
  G [pos = '5,1!']; 
  H [pos = '6,2!']; 
  I [pos = '1.5,-0.1!'];

  # several 'edge' statements
  A->B B->C
  D->E D->F E->F E->G F->G G->H F->H
  }
  ")

产生:

在此处输入图像描述

现在我想在节点 A、B 和 C 周围画一个虚线框。

我怎样才能在 R 中做到这一点?该解决方案的一个关键要求是它是可重现的,即我可以多次运行脚本并获得相同的结果。

4

3 回答 3

6

这是另一种基于 igraph 的方法。它的灵感来自这个 igraph代码示例

我假设使用 igraph 而不是 DiagrammeR 是一种选择 - 也许不是这样......

我们将顶点的定位留给标准布局算法,并查询结果顶点位置。然后使用这些位置在任意一组“选定”顶点周围绘制一个虚线矩形。不需要用户交互。

我们从图拓扑开始。

library(igraph)

set.seed(42)

df <- data.frame(from = c('A', 'B', 'I', 'D', 'D', 'E', 'E', 'F', 'F', 'G'),
                 to = c('B', 'C', 'I', 'E', 'F', 'G', 'F', 'H', 'G', 'H'))

g <- graph.data.frame(df, directed = TRUE)

图中顶点和箭头的大小可以根据喜好自由设置。

vertexsize <- 50
arrowsize <- 0.2

我们要求 Fruchterman-Reingold 布局引擎计算顶点的坐标。

coords <- layout_with_fr(g)

然后绘制图形。

plot(g,
     layout = coords,
     vertex.size = vertexsize,
     edge.arrow.size = arrowsize,
     rescale = FALSE,
     xlim = range(coords[,1]),
     ylim = range(coords[,2]))

如果我们想看看发生了什么,我们可以添加坐标轴并打印顶点坐标:

axis(1)
axis(2)

V(g) # ordered vertex list
coords # coordinates of the vertices (in the same coordinate system as our dotted rectangle)

我们现在找出我们想要一个矩形围绕的顶点的边界框。

selectedVertices = c("A", "B", "C")
vertexIndices <- sapply(selectedVertices, FUN = function(x) { return(as.numeric(V(g)[x])) } )
llx <- min(coords[vertexIndices, 1])
lly <- min(coords[vertexIndices, 2])
urx <- max(coords[vertexIndices, 1])
ury <- max(coords[vertexIndices, 2])

差不多好了。我们已经在 coords[]中获得了顶点中心的坐标,但我们还需要plot() 坐标系中顶点的大小。从 plot.igraph 源代码中,我们可以看到 plot() 的 vertex.size 选项除以 200,然后用作绘制顶点的半径。在绘制虚线矩形时,我们使用大 50% 的值作为顶点坐标边界框周围的边距。

margin <- (vertexsize / 200) * 1.5
rect(llx - margin, lly - margin, urx + margin, ury + margin, lty = 'dotted')

这是我们得到的结果:

在此处输入图像描述

于 2015-09-01T21:22:17.627 回答
5

您可以使用@StevenBeaupre 的小部件解决方案,但是有一些包用于使用 R 的图形绘制网络。一种是igraph您是否愿意使用其他解决方案。

这将使图表

library('igraph')
set.seed(11)
g <- data.frame(from = c('A', 'B', 'I', 'D', 'D', 'E', 'E', 'F', 'F', 'G'),
                to = c('B', 'C', 'I', 'E', 'F', 'G', 'F', 'H', 'G', 'H'))
(gg <- graph.data.frame(g, directed = TRUE))
plot(gg, vertex.color = 'white')

并且有很多方法可以在 r 图形中添加一个框;这是您可以单击绘图以添加框而无需计算任何内容的地方

rekt <- function(...) {
  coords <- c(unlist(locator(1)), unlist(locator(1)))
  rect(coords[1], coords[2], coords[3], coords[4], ..., xpd = NA)
}

rekt(border = 'red', lty = 'dotted', lwd = 2)

我明白了

在此处输入图像描述

于 2015-08-03T19:49:25.250 回答
2

一个简单的解决方案DiagrammR是使用点而不是neato。您大多失去了手动定位节点的能力(属性 pos 不再起作用),但您获得了使用集群和子图在节点集周围画线的能力。

library(DiagrammeR)
grViz("
      digraph boxes_and_circles {

      # a 'graph' statement
      graph [ fontsize = 10,rankdir=LR]

      # several 'node' statements
      node [shape = circle,
      fontname = Helvetica]

      # several 'edge' statements

      subgraph cluster_1 {
            style=dotted
            A->B->C
        }

      D->E D->F E->F E->G F->G G->H F->H
      I
      }

      ")

在此处输入图像描述

于 2015-09-05T10:55:15.657 回答