【问题标题】:In igraph in R: how can I remove non-branch-point vertices, while maintaining connectivity?在 R 中的 igraph 中:如何在保持连通性的同时删除非分支点顶点?
【发布时间】:2017-06-29 02:58:59
【问题描述】:

我有一个从几个树状结构的图像中提取的图形。该图对于每个关节点都有一个顶点,即使该点不是分支或端点(即节点顺序为 2)。我想删除这些 2 阶顶点,但保持连通性,以便通过这些中间体连接的分支点或末端顶点现在由一条边连接。我可以通过删除顶点并一次连接一个边来对小图执行此操作,但是在处理 10,000 多个边时这会很慢。

这是一个示例起始图。我想删除(例如)顶点 8 和 6,同时插入连接 9 和 4 的边。同样,我想删除顶点 5,同时插入 7 和 4 之间的边。

edge_matrix = cbind(
  c(1,2,3,4,4,5,6,8,9,9,10,11),
  c(2,3,4,5,6,7,8,9,10,11,12,13))
example_graph = graph.data.frame(edge_matrix, directed=F)

structure(list(13, FALSE, c(1, 2, 3, 4, 5, 10, 6, 7, 8, 9, 11, 
12), c(0, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9), c(0, 1, 2, 3, 4, 
6, 7, 8, 9, 5, 10, 11), c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
), c(0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), c(0, 1, 2, 
3, 5, 6, 7, 8, 10, 11, 12, 12, 12, 12), list(c(1, 0, 1), structure(list(), .Names = character(0)), 
    structure(list(name = c("1", "2", "3", "4", "5", "6", "8", 
    "9", "10", "11", "7", "12", "13")), .Names = "name"), list()), 
    <environment>), class = "igraph")

【问题讨论】:

    标签: r igraph


    【解决方案1】:

    实际上,最好只删除图中的 2 次节点,而不是尝试用最少的信息重建图。这个函数不用递归,可能效率更高

    trim_deg2 <- function(g) {
      get_deg2 <- function(x) {
        dd <- degree(x)
        trim <- V(x)[names(dd[dd==2])]    
      }
      ng <- g
      trim <- get_deg2(ng)
      while(length(trim)) {
        tv <- trim[1]
        touch <- adjacent_vertices(ng, tv)[[1]]
        ng <- delete_edges(ng, E(ng)[tv %--% touch])
        ng <- add_edges(ng, touch$name)
        ng <- delete_vertices(ng, V(ng)[tv])
        trim <- get_deg2(ng)
      }
      ng
    }
    

    它适用于您的示例数据

    g <- trim_deg2(example_graph)
    plot(g)
    

    【讨论】:

      【解决方案2】:

      我很确定我这样做是错误的,但这里有一个函数,它基本上会遍历图表,寻找度数 != 2 的节点并将它们重新连接到一个新图表中。

      walk_thin <- function(g, v=V(g)[[1]]) {
        dd <- degree(g)
        keep <- V(g)[names(dd[dd!=2])]
        edges <- c()
        find_next <- function(v, from, past = c()) {
          v2 <- adjacent_vertices(g, v)[[1]]
          v2 <- v2[!v2 %in% past]
          for(i in seq_along(v2)) {
            nv <- v2[i]
            if (nv %in% keep) {
              edges <<- c(c(from, nv)$name, edges)
              find_next(nv, nv, past=c(nv, past))
            } else {
              find_next(nv, from, past=c(nv, past))
            }
          }
        }
        find_next(v, v, v)  
        make_graph(edges,directed = FALSE)
      }
      

      它似乎适用于您的示例数据

      g <- walk_thin(example_graph)
      plot(g) 
      

      【讨论】:

      • 哇,太棒了!它在合理的时间内处理大图。对于将来使用此方法的任何人:此方法不会捕获与顶点 1 相邻的度数为 2 的节点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-21
      相关资源
      最近更新 更多