I have a graph with communities. I would like edge weights for all the edges between one community and all other nodes in the graph. I need the individual weights because I'd like to perform calculations on each edge weight (square them, for what it's worth). I've gotten some distance with this and this but it's really awkward.
This is what I've tried:
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() retains edge attributes. To extract edge weights between a community and all other nodes (excluding within community nodes) and perform a bit of calculation on the weights, I can do this:
# 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
I know this is very clunky, but I'm stumped on how to simplify it. What I'm looking for is something like this:
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
Suggestions about how to get these results more simply?
Created on 2022-04-23 by the reprex package (v2.0.1)
You are actually approaching it, and I think combn
could help you out there
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
)
)
which gives
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