代码之家  ›  专栏  ›  技术社区  ›  landau

多个源顶点的子组件(mode=“in”)

  •  7
  • landau  · 技术社区  · 7 年前

    问题

    在 igraph R包,是否有一个有效的实现 subcomponent()

    动机

    drake R package 公鸭 使用 igraph::subcomponent() v 参数必须是单个顶点,因此 公鸭

    编辑:2019-01-10

    公鸭 different approach that ultimately relies on sequential calls to adjacent_vertices() the speed improvement is actually quite nice . 仍然坚持要一些更优雅和复杂的东西。

    1 回复  |  直到 7 年前
        1
  •  2
  •   gfgm    7 年前

    我想你可以用 distances() 生成节点之间距离(无边)矩阵的函数。这似乎只执行一次搜索,比遍历每个顶点快得多。

    library(igraph)
    library(microbenchmark)
    
    # generate some random testing data
    set.seed(1234)
    g <- erdos.renyi.game(50, .01)
    
    # Here we make a function that iterates 
    # across the vector of IDs applying the function
    # and returns a list where each element is the
    # ids of the subcomponents
    sc_apply <- function(g) {
      vs <- V(g)
      res <- sapply(vs, function(v){as.numeric( # to facilitate comparison
        subcomponent(g, v, mode = "in")
        )})
      res
    }
    
    # Try it for testing
    t1 <- sc_apply(g)
    
    # Here we get the matrix of node distances. Infinite distance
    # implies a seperate component. We iterate through rows of
    # matrix to extract the set of nodes that are connected 
    sc_distmat <- function(g) {
      dmat <- distances(g, mode = "in")
      res <- apply(dmat, 1, function(row){which(is.finite(row))})
      res
    }
    
    # extract for testing
    t2 <- sc_distmat(g)
    
    # check that equal (we need to sort the 
    # subcomponent list elements first to facilitate comparison)
    all.equal(lapply(t1, sort), t2)
    #> [1] TRUE
    

    结果是相同的——尽管值得注意的是,如果图是一个巨大的组件,那么apply将返回一个矩阵而不是一个列表,因此您需要以稍微不同的方式进行比较。

    好的,现在让我们看看这有多快/是否更快:

    # generate graphs of different sizes (not too big because my
    # laptop is borderline antique!)
    set.seed(42)
    small_g <- erdos.renyi.game(10, .2)
    mid_g <- erdos.renyi.game(50, .1)
    big_g <- erdos.renyi.game(100, .1)
    
    # check speed improvement
    microbenchmark(sc_apply(small_g), sc_distmat(small_g))
    #> Unit: microseconds
    #>                 expr      min        lq      mean   median        uq
    #>    sc_apply(small_g) 2181.465 2243.4895 2734.7132 2313.005 2777.7135
    #>  sc_distmat(small_g)  451.333  471.8565  840.4742  521.865  598.0845
    #>        max neval cld
    #>   9152.262   100   b
    #>  27139.262   100  a
    microbenchmark(sc_apply(mid_g), sc_distmat(mid_g))
    #> Unit: microseconds
    #>               expr       min        lq       mean    median         uq
    #>    sc_apply(mid_g) 11006.113 11327.794 13590.9536 12919.492 15397.2510
    #>  sc_distmat(mid_g)   757.752   795.308   949.2551   841.834   965.4545
    #>        max neval cld
    #>  27068.296   100   b
    #>   2061.824   100  a
    microbenchmark(sc_apply(big_g), sc_distmat(big_g))
    #> Unit: milliseconds
    #>               expr      min        lq      mean    median        uq
    #>    sc_apply(big_g) 23.11678 26.696373 29.940675 29.191045 33.012796
    #>  sc_distmat(big_g)  1.67531  1.727873  2.156307  1.855994  2.244872
    #>        max neval cld
    #>  47.081647   100   b
    #>   7.576123   100  a
    

    如你所见 距离()

    创建于2019-01-10 reprex package