【问题标题】:How to make grouped layout in igraph?如何在 igraph 中进行分组布局?
【发布时间】:2013-04-29 16:55:35
【问题描述】:

igraph 中,在应用模块化算法来查找图形社区之后,我想绘制一个网络布局,清楚地显示不同社区及其连接。 Cytoscape 中的“组属性布局”之类的东西:我想显示每个组/社区的成员彼此靠近,并在组/社区之间保持一定距离。我在igraph 中找不到任何提供开箱即用功能的功能。在发布这个问题时,我已经找到了一个简单的 d.i.y 解决方案,我将把它作为答案发布。但我想知道是否有更好的可能性,或更详细的解决方案?

【问题讨论】:

    标签: r igraph


    【解决方案1】:

    受 Antoine 的建议启发,我创建了这个函数:

    edge.weights <- function(community, network, weight.within = 100, weight.between = 1) {
    bridges <- crossing(communities = community, graph = network)
    weights <- ifelse(test = bridges, yes = weight.between, no = weight.within)
    return(weights) 
    }
    

    函数也是如此;只需将您的社区对象放在社区插槽中,您的图形在网络中。我会离开 weight.between = 1 并调整 weight.within 值。

    然后将权重转移到节点中的weight槽:

    E(graph)$weight <- edge.weights(community, graph)
    

    最后使用一种使用权重的布局算法,例如layout_with_frigraph 1.0.1fruchterman.reingold 的新名称)。

    我以 Zachary 的空手道俱乐部网络为例。

    library(igraph)
    library(igraphdata)
    #I load the network
    data(karate)
    #for reproducible purposes
    set.seed(23548723)
    karateLayout <- layout_with_fr(karate)
    par(mar = c(0,0,2,0))
    plot(karate, vertex.size = 10, vertex.color = "steelblue4", edge.width = 1, 
    vertex.label = NA, edge.color = "darkgrey", layout = karateLayout,
    main = "Zachary's karate club network" )
    

    我通过 cluster_louvain 函数对模块化进行多级优化来检测社区:

    Communitykarate <- cluster_louvain(karate)
    

    接下来是个人偏好而不是默认设置:

    prettyColors <- c("turquoise4", "azure4", "olivedrab","deeppink4")
    communityColors <- prettyColors[membership(Communitykarate)]
    

    用颜色突出显示社区的图表是:

    plot(x = Communitykarate, y = karate, edge.width = 1, vertex.size = 10, 
    vertex.label = NA, mark.groups = NULL, layout = karateLayout, col = communityColors,
    main = "Communities in Zachary's karate club network",
    edge.color = c("darkgrey","tomato2")crossing(Communitykarate, karate) + 1])
    

    现在,这个问题存在的意义。

    E(karate)$weight <- edge.weights(Communitykarate, karate)
    # I use the original layout as a base for the new one
    karateLayoutA <- layout_with_fr(karate, karateLayout)
    # the graph with the nodes grouped
    plot(x = Communitykarate, y = karate, edge.width = 1, vertex.size = 10, 
    mark.groups = NULL, layout = karateLayoutA, vertex.label = NA, col = communityColors, 
    c("darkgrey","tomato2")[crossing(Communitykarate, karate) + 1],
    main = "Communities in Zachary's karate club network (grouped)")
    

    如果您尝试增加体重,您将拥有:

    E(karate)$weight <- edge.weights(Communitykarate, karate, weight.within = 1000)
    karateLayoutB <- layout_with_fr(karate, karateLayout)
    plot(x = Communitykarate, y = karate, edge.width = 1, vertex.size = 10,
     mark.groups = NULL, layout = karateLayoutB, vertex.label = NA, col = communityColors, 
    c("darkgrey","tomato2")[crossing(Communitykarate, karate) + 1],
    main = "Communities in Zachary's karate club network (grouped)")
    

    【讨论】:

      【解决方案2】:

      为了扩展 Gabor 的建议,我创建了这个函数:

      weight.community=function(row,membership,weigth.within,weight.between){
      if(as.numeric(membership[which(names(membership)==row[1])])==as.numeric(membership[which(names(membership)==row[2])])){
      weight=weigth.within
      }else{
      weight=weight.between
      }
      return(weight)
      }
      

      只需将其应用于图形边矩阵的行(由get.edgelist(your_graph)) 给出以设置新边权重(成员资格是任何社区检测算法结果的成员资格向量):

      E(g)$weight=apply(get.edgelist(g),1,weight.community,membership,10,1)
      

      然后,只需使用接受边缘权重的布局算法,例如 Gabor 建议的 fruchterman.reingold。您可以调整权重参数以获得所需的图形。例如:

      E(g)$weight=apply(get.edgelist(g),1,weight.community,membership,10,1)
      g$layout=layout.fruchterman.reingold(g,weights=E(g)$weight)
      plot(g)
      

      E(g)$weight=apply(get.edgelist(g),1,weight.community,membership,1000,1)
      g$layout=layout.fruchterman.reingold(g,weights=E(g)$weight)
      plot(g)
      

      注 1:边缘的透明度/颜色是我的图表的其他参数。我按社区对节点进行了着色,以表明它确实有效。

      注意 2:确保使用 membership(comm) 而不是 comm$membership,其中 comm 是社区检测算法的结果(例如,comm=leading.eigenvector.community(g))。原因是在第一种情况下,你得到一个带有名字的数字向量(我们想要的),而在第二种情况下,你得到一个没有名字的同一个向量。

      要获得多个社区检测算法的共识,请参阅function

      【讨论】:

        【解决方案3】:

        一种解决方案是基于模块化设置图的边权重。将模块内边缘设置为较大的权重,将模块边缘设置为较小的权重。然后调用layout.fruchterman.reingold(),或任何支持边缘权重的算法。

        您可能需要稍微调整一下实际的重量值,因为这取决于您的图表。

        【讨论】:

        • 嗨,Gabor,你能看看这个相关的thread。提前致谢。
        【解决方案4】:

        函数layout.modular 为图表提供分组布局,来自任何 igraph 社区检测方法的结果:

        c <- fastgreedy.community(G)
        
        layout.modular <- function(G,c){
        nm <- length(levels(as.factor(c$membership)))
        gr <- 2
        while(gr^2<nm){
            gr <- gr+1
        }
        i <- j <- 0
        for(cc in levels(as.factor(c$membership))){
            F <- delete.vertices(G,c$membership!=cc)
            F$layout <- layout.kamada.kawai(F)
            F$layout <- layout.norm(F$layout, i,i+0.5,j,j+0.5)
            G$layout[c$membership==cc,] <- F$layout
            if(i==gr){
                i <- 0
                if(j==gr){
                    j <- 0
                }else{
                    j <- j+1
                }
            }else{
                i <- i+1
            }
        }
        return(G$layout)
        }
        
        G$layout <- layout.modular(G,c)
        V(G)$color <- rainbow(length(levels(as.factor(c$membership))))[c$membership]
        plot(G)
        

        【讨论】:

        • 如果我尝试你的方法,我会得到一个错误。我在您的代码上方仅添加了两行来模拟网络,即:library(igraph); G &lt;- barabasi.game(100, directed = FALSE)。错误消息说:Error in G$layout[c$membership == cc, ] &lt;- F$layout : incorrect number of subscripts on matrix
        • 抱歉,这是因为 G$layoutNULL。如果你用任何尺寸正确的矩阵填充它,或者只是用G$layout &lt;- layout.fruchterman.reingold(G) 填充它,那么代码运行良好。
        猜你喜欢
        • 1970-01-01
        • 2019-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-12
        • 2017-04-17
        • 2011-07-10
        • 2021-03-27
        相关资源
        最近更新 更多