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

发布于 2024-10-23 01:01:00 字数 933 浏览 4 评论 0原文

我正在尝试绘制一个类似于流程图的网络可视化。我非常接近以下代码,但我有几个问题:

  1. 这是最好的布局()算法吗?或者我可以手动为每个节点分配一个位置吗?
  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)

I am trying to draw a network visualization to resemble a flow diagram. I'm fairly close with the following code, but I have a couple questions:

  1. Is this the best layout() algorithm, or can I manually assign a position for each node>
  2. How can I make sure that these nodes don't overlap in the plot (as they do here)?
  3. Can I assign one node as an "anchor" or starting point? i.e., can I make "C" the top-most or left-most node?

Thanks so much!!

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

惜醉颜 2024-10-30 01:01:00

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 来控制布局 abit 这是一个包含的列表。一个显然可以用来设置图的根的参数(记住 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))

The layout in igraph is defined in a matrix with 2 columns and a row for each node. The first column indicates its x position and the second its y position, and scale is not relevant (it is always rescaled to fit a -1 to 1 plotting area. You can get this layout before plotting by just calling the layout function on the graph:

 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

This way you can change it in any way you want manually, and then send it to the plot:

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)

It also seems that you can set the argument params to control the layout abit. This is a list containing an argument root that apparently can be used to set the root of the graph. Assign this a number of the node (renember that igraph uses C like indexes for nodes, first one is 0). So setting the root at "C":

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

EDIT: Also the RGraphViz has some nice tree-layouts in it that might be worth checking out.


EDIT 2:

This is a modified snippet of the source codes from my package, which uses a same kind of layout matrix to define placement of nodes in a graph, that you might find useful:

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)
}

What this function does is transform a matrix specifying the layout in a grid (similar to layout()) to a two-column layout with x and y positions. Define a matrix of zeros and for each node integer from 1 to the total number of nodes ( this is the igraph ID + 1 ).

For example, for a silly 4 node graph:

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))
段念尘 2024-10-30 01:01:00

如果您想自己分配节点位置,比上述方法简单的方法是在数据表中添加标记为 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)

输入图像此处描述

A less complicated method than the above if you want to assign the node locations yourself is to add columns labelled x and y in your datasheet with the x and y coordinates for the respective nodes in those columns. e.g.

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)

enter image description here

故人爱我别走 2024-10-30 01:01:00

比上面更简单的方法是直接使用坐标矩阵:

## 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)

An even less complicated method than above is to use the coordinate matrix directly:

## 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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文