Chuck
Chuck

Reputation: 3852

Plot Collection of communities of sub-graphs on same Graph Igraph

I have a non-directed network in R which when plotted in igraph looks something like:

plot(g2)

enter image description here

From this main graph, I extract all clusters / sub-graphs with minimum vertices = 4:

modules <- decompose.graph(g2, min.vertices = 4)
out <- modules[order(sapply(modules, ecount), decreasing=T)]

Giving:

> head(modules)
[[1]]
IGRAPH UN-- 4 4 -- 
+ attr: name (v/c), value (e/n), sourceID (e/n), targetID (e/n)
+ edges (vertex names):
[1] 333--342 333--324 333--323 342--324

[[2]]
IGRAPH UN-- 4 4 -- 
+ attr: name (v/c), value (e/n), sourceID (e/n), targetID (e/n)
+ edges (vertex names):
[1] 27--25 27--20 25--20 25--21

[[3]]
IGRAPH UN-- 4 3 -- 
+ attr: name (v/c), value (e/n), sourceID (e/n), targetID (e/n)
+ edges (vertex names):
[1] 662--657 662--705 706--657

[[4]]
IGRAPH UN-- 4 3 -- 
+ attr: name (v/c), value (e/n), sourceID (e/n), targetID (e/n)
+ edges (vertex names):
[1] 793--792 793--795 793--794

[[5]]
IGRAPH UN-- 4 3 -- 
+ attr: name (v/c), value (e/n), sourceID (e/n), targetID (e/n)
+ edges (vertex names):
[1] 746--747 746--722 746--721

[[6]]
IGRAPH UN-- 4 3 -- 
+ attr: name (v/c), value (e/n), sourceID (e/n), targetID (e/n)
+ edges (vertex names):
[1] 285--284 285--286 287--284

I can plot these as one graph by doing:

vertexes <- character()
data_frames <- list()
for(i in 1:length(out)) {
  vertexes[i] <- list(vertex.attributes(out[[i]])$name)
  data_frames[[i]] <- get.data.frame(out[[i]])
}
sub_nodes = unlist(vertexes)
subv <- sub_nodes
g3 <- induced.subgraph(graph=g2,vids=subv)
plot(g3)

enter image description here

I can calculate the betweenness of this main graph and display the outcome:

wc <- edge.betweenness.community(g3, weights = NULL
                                 ,directed = FALSE,bridges = TRUE)
plot(wc, g3)

enter image description here

This splits up each sub cluster as a community.


What I want is the betweenness evaluated for each individual sub cluster:

I calculate the betweenness of each subgraph by doing:

betweenness_sub <- list()
for(i in 1:length(out)) {
  btws <- edge.betweenness.community(out[[i]], weights = NULL
                                                   ,directed = FALSE,bridges = TRUE)
  print(btws)
  betweenness_sub[[i]] <- btws
}

This gives:

> head(betweenness_sub)
[[1]]
IGRAPH clustering edge betweenness, groups: 2, mod: 0.17
+ groups:
  $`1`
  [1] "646" "647" "723"

  $`2`
  [1] "713" "714" "710"


[[2]]
IGRAPH clustering edge betweenness, groups: 1, mod: 0
+ groups:
  $`1`
  [1] "685" "684" "686" "691" "690"


[[3]]
IGRAPH clustering edge betweenness, groups: 1, mod: 0
+ groups:
  $`1`
  [1] "719" "718" "734" "753" "715"


[[4]]
IGRAPH clustering edge betweenness, groups: 1, mod: 0
+ groups:
  $`1`
  [1] "702" "757" "720" "735"


[[5]]
IGRAPH clustering edge betweenness, groups: 1, mod: 0
+ groups:
  $`1`
  [1] "83" "80" "88" "87" "81"


[[6]]
IGRAPH clustering edge betweenness, groups: 1, mod: 0
+ groups:
  $`1`
  [1] "333" "342" "324" "323"

I can plot these individually by doing:

plot(betweenness_sub[[1]], out[[1]])

Beautiful Butterfly

What I want to do now is plot the communities of each of these sub clusters but altogether like in the third plot.

This time the highlighted communities will be those as described in the above lists..

Is there any way to "regroup" "combine" or mesh these individual sub graph communities to a full graph?


As a further example, if we take minimum vertices = 7, and run the above code we get:

vertexes <- character()
data_frames <- list()
for(i in 1:length(out)) {
  vertexes[i] <- list(vertex.attributes(out[[i]])$name)
  data_frames[[i]] <- get.data.frame(out[[i]])
}
sub_nodes = unlist(vertexes)
subv <- sub_nodes
g3 <- induced.subgraph(graph=gg,vids=subv)
plot(g3)

wc <- edge.betweenness.community(g3, weights = E(out)$value
                                 ,directed = FALSE,bridges = TRUE)
# g3 <- delete.edges(g3, wc$removed.edges[seq(length=1)])
plot(wc, g3)

What I have

Whereas, if we consider the biggest cluster individually, we get:

plot(betweenness_sub[[1]], out[[1]])

enter image description here

I want the communities calculated on individual clusters in the second image, in the same arrangements as in the first image. Any ideas?


Edit 3. The data used to create the plots (min vertices=7) above is as follows:

> get.data.frame(g3)
   from   to  value sourceID targetID
1    74   80 0.2829   255609   262854
2    74   61 0.2880   255609   179585
3    80 1085 0.2997   262854  3055482
4   476  502 0.2714  1442372  1475074
5   476  524 0.2963  1442372  1532560
6   476  479 0.2214  1442372  1448436
7   476  497 0.2714  1442372  1466635
8   476  498 0.2714  1442372  1467171
9   476  500 0.2714  1442372  1468099
10  502  479 0.2714  1475074  1448436
11  502  497 0.1215  1475074  1466635
12  502  498 0.1215  1475074  1467171
13  502  500 0.1215  1475074  1468099
14  524  479 0.2963  1532560  1448436
15 1045 1046 0.1842  2970629  2971615
16 1046 1085 0.2963  2971615  3055482
17 1046 1154 0.2714  2971615  3087803
18 1047 1120 0.2886  2972434  3076314
19 1085 1154 0.2577  3055482  3087803
20 1085 1187 0.2850  3055482  3101131
21 1085 1209 0.2850  3055482  3110186
22 1097 1159 0.2922  3062163  3090708
23 1097 1087 0.2256  3062163  3058341
24 1097 1158 0.2922  3062163  3090707
25 1097 1160 0.2922  3062163  3090709
26 1097 1177 0.2577  3062163  3099199
27 1098 1159 0.2922  3062164  3090708
28 1098 1087 0.2256  3062164  3058341
29 1098 1158 0.2922  3062164  3090707
30 1098 1160 0.2922  3062164  3090709
31 1098 1177 0.2577  3062164  3099199
32 1118 1119 0.1587  3076246  3076248
33 1118 1090 0.2256  3076246  3058962
34 1119 1120 0.1736  3076248  3076314
35 1119 1144 0.2035  3076248  3085240
36 1119 1145 0.2035  3076248  3085241
37 1154 1243 0.2577  3087803  3130848
38 1154 1187 0.2305  3087803  3101131
39 1154 1209 0.2305  3087803  3110186
40 1154 1244 0.2577  3087803  3131379
41 1159 1087 0.2922  3090708  3058341
42 1243 1187 0.1488  3130848  3101131
43 1243 1209 0.1488  3130848  3110186
44 1243 1244 0.1215  3130848  3131379
45 1243 1281 0.2997  3130848  3255811
> g <- graph.data.frame(get.data.frame(g3), directed=FALSE)
> gg
IGRAPH UN-- 33 45 -- 
+ attr: name (v/c), value (e/n), sourceID (e/n), targetID (e/n)
+ edges (vertex names):
 [1] 74  --80   74  --61   80  --1085 476 --502  476 --524  476 --479  476 --497  476 --498  476 --500  502 --479  502 --497  502 --498 
[13] 502 --500  524 --479  1045--1046 1046--1085 1046--1154 1047--1120 1085--1154 1085--1187 1085--1209 1097--1159 1097--1087 1097--1158
[25] 1097--1160 1097--1177 1098--1159 1098--1087 1098--1158 1098--1160 1098--1177 1118--1119 1118--1090 1119--1120 1119--1144 1119--1145
[37] 1154--1243 1154--1187 1154--1209 1154--1244 1159--1087 1243--1187 1243--1209 1243--1244 1243--1281

Edit 2:

It is possible to plot multiple clusters using the plotly package:

par(mfrow=c(2,3))
par(mar = rep(2, 2))
for(i in 1:length(out)) {
  plot(betweenness_sub[[i]], out[[i]])
}

enter image description here

But I want to know how to do this specifically using igraph in order to maintain the circular structure as in the figures described.

Upvotes: 2

Views: 1894

Answers (1)

Consistency
Consistency

Reputation: 2922

Below is my algorithm, it is not very elegant, but it seems to work. The basic idea is to get the group information from your betweenness_sub and concatenate them into a big list, for example, subs, and use plot(g3, mark.groups = subs) to plot the whole graph with the group information from subs, i.e. betweenness-sub. Note that in my code, graph is the graph data.frame as your posted.

g2 <- graph.data.frame(graph, directed=FALSE)

modules <- decompose.graph(g2, min.vertices = 7)
out <- modules[order(sapply(modules, ecount), decreasing=T)]

vertexes <- character()
data_frames <- list()
for(i in 1:length(out)) {
    vertexes[i] <- list(vertex.attributes(out[[i]])$name)
    data_frames[[i]] <- get.data.frame(out[[i]])
}
sub_nodes = unlist(vertexes)
subv <- sub_nodes
g3 <- induced.subgraph(graph=g2,vids=subv)
plot(g3)

wc <- edge.betweenness.community(g3, weights = NULL
                                 ,directed = FALSE,bridges = TRUE)
plot(wc, g3)

betweenness_sub <- list()
for(i in 1:length(out)) {
    btws <- edge.betweenness.community(out[[i]], weights = NULL
                                       ,directed = FALSE,bridges = TRUE)
    print(btws)
    betweenness_sub[[i]] <- btws
}

subs <- list()
k <- 1
for (sub in betweenness_sub) {
    for (i in 1:length(sub)) {
        subs[[k]] <- sub[[i]]
        k = k + 1
    }
}

plot(g3, mark.groups = subs)

Upvotes: 3

Related Questions