R 在图形上手工绘制

R 在图形上手工绘制,r,plot,drawing,figure,diagrammer,R,Plot,Drawing,Figure,Diagrammer,我生成了一个图表: 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

我生成了一个图表:

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中实现这一点?解决方案的一个关键要求是它是可复制的,即我可以多次运行脚本并获得相同的结果。

您可以使用@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')
library('igraph'))
种子(11)

g这是另一种基于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)
如果我们想了解情况,可以添加坐标轴并打印顶点坐标:

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])
selectedVertices=c(“A”、“B”、“c”)

顶点使用
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
      }

      ")

您希望它是一个小部件还是仅仅是一个应用程序image@rawr字体有什么区别?最后,我需要输出一个图像以放入Word文档。@histelheim也许您可以尝试手动定位一个矩形作为节点,使用
engine=“neato”
(而不是circo)和
pos
属性:
a[pos='-3,4!',宽度=3.5,高度=0.5,形状=矩形,标签=''
。看一看,对于你的原始问题,你可以使用
子图在节点周围添加一个框,但我不确定这是否是你需要的,因为你的赏金中的文本表明你想要不同类型的图形(例如,不特定于你的问题?)。有没有办法使这一点重现,也就是说,不需要手动点击?@histelheim我想不出一个好办法
igraph
有一些内置的布局
?igraph::layout
,可以确定所有东西的去向,而不是随机的。你可以为布局指定一个矩阵,这样你就可以在开始之前知道坐标。我可以指定节点的位置,但我不能指定矩形的位置…@histelheim你能用代码提出一个新问题吗?问题的本质不一样吗?你的解决方案很好,只是不符合(在那一点上没有明确的)再现性假设。如果你使用
fdp
布局,你可以使用
pos
——但是位置是集群的本地位置(i tihnk)。您可能可以通过添加不可见的节点/边来调整位置。
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])
margin <- (vertexsize / 200) * 1.5
rect(llx - margin, lly - margin, urx + margin, ury + margin, lty = 'dotted')
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
      }

      ")