如何使用固定位置控制igraph图的布局?

28
我正在尝试绘制一个类似流程图的网络可视化。以下是我的代码,但我有几个问题:
  1. 这是最好的layout()算法吗?还是我可以手动为每个节点分配位置?
  2. 如何确保这些节点在绘图中不重叠(就像这里一样)?
  3. 我能否将一个节点指定为“锚点”或起始点?例如,我可以使“C”成为最上方或最左侧的节点吗?
非常感谢!
library("igraph")
L3 <- LETTERS[1:8]
d <- data.frame(start = sample(L3, 16, replace = T), end = sample(L3, 16, replace = T),
                weight = c(20,40,20,30,50,60,20,30,20,40,20,30,50,60,20,30))


g <- graph.data.frame(d, directed = T)

V(g)$name 
E(g)$weight

ideg <- degree(g, mode = "in", loops = F)

col=rainbow(12) # For edge colors

plot.igraph(g, 
  vertex.label = V(g)$name, vertex.label.color = "gray20",
  vertex.size = ideg*25 + 40, vertex.size2 = 30,
  vertex.color = "gray90", vertex.frame.color = "gray20",
  vertex.shape = "rectangle",
  edge.arrow.size=0.5, edge.color=col, edge.width = E(g)$weight / 10,
  edge.curved = T, 
  layout = layout.reingold.tilford)
3个回答

45

在igraph中,布局是在一个矩阵中定义的,其中有2列和每个节点的一行。第一列表示其x位置,第二列表示其y位置,比例尺不相关(它总是重新缩放以适合-1到1的绘图区域)。您可以通过对图形调用布局函数来获取此布局:

 l <-layout.reingold.tilford(g) 
 l
     [,1] [,2]
[1,]    0    0
[2,]   -1    3
[3,]    0    1
[4,]    0    3
[5,]    0    2
[6,]    0    4
[7,]    1    3

这样,您可以手动以任何想要的方式更改它,然后将其发送到图表中:
plot.igraph(g, 
  vertex.label = V(g)$name, vertex.label.color = "gray20",
  vertex.size = ideg*25 + 40, vertex.size2 = 30,
  vertex.color = "gray90", vertex.frame.color = "gray20",
  vertex.shape = "rectangle",
  edge.arrow.size=0.5, edge.color=col, edge.width = E(g)$weight / 10,
  edge.curved = T, 
  layout = l)

看起来您可以设置参数params来控制布局。这是一个包含参数root的列表,显然可以用于设置图的根节点。将其分配给节点的编号(请记住,igraph对节点使用类似C语言的索引,第一个为0)。因此,将根节点设置为“C”:

l <- layout.reingold.tilford(g,params=list(root=2))

编辑:此外,RGraphViz中还有一些不错的树形布局可以值得尝试。


编辑2:

这是我包中源代码的修改片段,使用了与图中节点位置定义相同类型的布局矩阵,您可能会发现它很有用:

gridLayout <- function(x)
{
    LmatX <- seq(-1,1,length=ncol(x))
    LmatY <- seq(1,-1,length=nrow(x))

    loc <- t(sapply(1:max(x),function(y)which(x==y,arr.ind=T)))
    layout <- cbind(LmatX[loc[,2]],LmatY[loc[,1]])
    return(layout)
}

这个函数的作用是将矩阵转换为指定网格布局(类似于layout()),并按x和y位置生成两列布局。定义一个零矩阵,对于每个节点整数从1到节点总数(这是igraph ID + 1)。
例如,对于一个愚蠢的4节点图:
grid <- matrix(c(
    0,0,1,0,0,
    2,0,3,0,4),nrow=2,byrow=TRUE)

library("igraph")

g <- graph.adjacency(matrix(1,4,4))

plot(g,layout=gridLayout(L))

谢谢你的建议!像这样设置位置把它们放在一起:l2 <- as.matrix(data.frame(c(0,6,12,12,12,24,24,24), c(0,.5,-.5,0,-1,1,-1,.25))) - david h
3
两年后,这个答案对我很有帮助 :-) - Ferdinand.kraft
3
Sacha,当我应用你的代码时,出现了“Error in ncol(x) : object 'L' not found”的错误。在plot(g,layout=gridLayout(L))这一行中可能存在一个我无法理解的问题。 - Erdogan CEVHER

11

如果您想自己分配节点位置,那么比上述方法更简单的方法是在您的数据表中添加标记为x和y的列,并在这些列中为相应的节点提供x和y坐标。 例如:

library('igraph')
nodes <- c('a','b','c','d')
x <- c(0,1,2,3)
y <- c(0,1,2,3)
from <- c('a','b','c')
to <- c('b','c','d')
NodeList <- data.frame(nodes, x ,y)
EdgeList <- data.frame(from, to)
a<- graph_from_data_frame(vertices = NodeList, d= EdgeList, directed = FALSE)
plot(a)

在此输入图片描述


0
一个比上面更简单的方法是直接使用坐标矩阵:
## plot graph using matrix layout
require('igraph')
x    <- c(0,1,2,3)
y    <- c(0,1,2,3)
grid <- matrix(c(x, y), ncol=2)
g <- make_graph(~ a-b-c-d)
    
plot(g, layout = grid)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接