在 igraph 中使用 contract_vertices() 和社区函数时,是否有更简单的方法来 return 边缘值?

Is there a simpler way to return edge values when using contract_vertices() and community functions in igraph?

我有一张社区图。我想要图中一个社区和所有其他节点之间的所有边的边权重。我需要单独的权重,因为我想对每个边缘权重进行计算(将它们平方,就其价值而言)。我和 and this 有点距离,但真的很尴尬。

这是我试过的:

library(igraph)

## create example graph
g1 <- graph.full(5)
V(g1)$name <- 1:5
g2 <- graph.full(5)
V(g2)$name <- 6:10
g3 <- graph.ring(5)
V(g3)$name <- 11:15
g <- g1 %du% g2 %du% g3 + edge('1', '6') + edge('1', '11')

E(g)$weight <- c(1:27)

# determine community structure
cl <- cluster_louvain(g)
V(g)$name <- membership(cl)

# contract the graph
cg <- contract.vertices(graph = g,
                        mapping = membership(cl))
cg2 <- simplify(cg)

contract.vertices() 保留边属性。要提取社区与所有其他节点(社区节点内除外)之间的边权重并对权重执行一些计算,我可以这样做:

# edges weights linking community 1 and community 2
E(cg)[ V(cg)[1] %--% V(cg)[2]]$weight
#> [1] 1 2 3 4

# edges weights linking community 1 and community 3
E(cg)[ V(cg)[1] %--% V(cg)[3]]$weight
#> [1] 26

bind_rows(
 tibble(one_two_edges = E(cg)[ V(cg)[2] %--% V(cg)[1]]$weight) %>%
  mutate(summed_square_edge_weight = one_two_edges^2) %>%
  summarize_all(sum) %>%
  select(-one_two_edges)
 ,
 tibble(one_three_edges = E(cg)[ V(cg)[1] %--% V(cg)[3]]$weight) %>%
  mutate(summed_square_edge_weight = one_three_edges^2) %>%
  summarize_all(sum) %>%
  select(-one_three_edges)
)
#> # A tibble: 2 × 1
#>   summed_square_edge_weight
#>                       <dbl>
#> 1                        30
#> 2                       676

我知道这很笨拙,但我不知道如何简化它。我正在寻找的是这样的东西:

tibble(
community_links = c("com_1_to_com_2", "com_1_to_com_3"),
summed_square_edge_weight = c(30, 676))
#> # A tibble: 2 × 2
#>   community_links summed_square_edge_weight
#>   <chr>                               <dbl>
#> 1 com_1_to_com_2                         30
#> 2 com_1_to_com_3                        676

关于如何更简单地获得这些结果的建议?

reprex package (v2.0.1)

于 2022-04-23 创建

你实际上正在接近它,我认为 combn 可以帮助你

do.call(
    rbind,
    combn(
        vcount(cg),
        2,
        function(k) {
            data.frame(
                community_links = paste0(paste0("com_", k), collapse = "_to_"),
                summed_square_edge_weight = sum((E(cg)[V(cg)[k[1]] %--% V(cg)[k[2]]]$weight)^2)
            )
        },
        simplify = FALSE
    )
)

这给出了

  community_links summed_square_edge_weight
1  com_1_to_com_2                        30
2  com_1_to_com_3                       676
3  com_2_to_com_3                         0

igraph 仔细研究之后,事实证明这是可能的:igraph::get.data.frame() returns 一个带有收缩顶点边权重的边列表(这里用 tibble::as_tibble()。结果 contract.vertices() 函数中的 vertex.attr.comb() 参数需要设置为保留先前分配的名称顶点属性的内容。我没有对平方求和只是为了显示返回值.

 cg <- contract.vertices(graph = g,
                    mapping = membership(cl),
                    vertex.attr.comb = "min")
 
 as_tibble(as_long_data_frame(cg),
          .name_repair = "universal") %>%
 select(from:weight) %>%
 filter(from != to) %>% 
 mutate(sq_weight = weight^2)
#> # A tibble: 5 × 4
#>    from    to weight sq_weight
#>   <dbl> <dbl>  <dbl>     <dbl>
#> 1     1     2      1         1
#> 2     1     2      2         4
#> 3     1     2      3         9
#> 4     1     2      4        16
#> 5     1     3     26       676