Reputation: 87
I am having some trouble extracting community membership after running community detection algorithms in igraph
. The membership
vector stored does not seem to correspond to community membership found by the algorithm. I suspect I am missing something but documentation is thin, any help appreciated.
My example:
Create a weighted graph with three communities and two components:
v1 <- c(1,1,2,3,4,4,6,7,8,9)
v2 <- c(2,3,3,4,5,6,5,8,9,7)
weight <- c(3,3,2,1,3,3,2,2,2,3)
graph <- data.frame(v1,v2)
g <- graph.data.frame(graph, directed=FALSE)
The communities in the above graph are vertices (1,2,3), (4,5,6), and (7,8,9). And indeed when we run a community detection algorithm, this is what it finds:
cd <- fastgreedy.community(g)
plot(cd,g, edge.width=weight)
str(cd)
Gives output:
IGRAPH clustering fast greedy, groups: 3, mod: 0.56
groups:
1
[1] "7" "8" "9"
2
[1] "4" "6" "5"
3
[1] "1" "2" "3"`
and this nice picture of the graph split up into communities.
However, when I try to access cd$membership
or cutat()
, it's a different picture:
cd$membership
cutat(cd, steps=which.max(cd$modularity)-1)
both give
[1] 3 3 3 2 2 1 1 1 2
Am I wrong in interpreting the above as indicating community membership of each vertex? It seems as though it is (correctly) assigning (1,2,3) to community 3, but incorrectly grouping (4,5,9) and (6,7,8) together.
Upvotes: 1
Views: 2117
Reputation: 1163
The seeming missmatch stems from the order igraph
reads and assigns vertex ids (see this answer for reference).
Let's take a look at the order of vertices as provided by the graph
-object:
> unlist(graph, use.names = F) # identical to c(v1, v2)
[1] 1 1 2 3 4 4 6 7 8 9 2 3 3 4 5 6 5 8 9 7
In this sequence the 5
appears only after 1,2,3,4,6,7,8,9
. This is the resulting vertex-sequence upon removing duplicate entries:
> unique(unlist(graph, use.names = F))
[1] 1 2 3 4 6 7 8 9 5
or using igraph
:
> V(g)
+ 9/9 vertices, named, from 3bae324:
[1] 1 2 3 4 6 7 8 9 5
Which aligns nicely with the communities found in your example:
> sort(membership(cd))
7 8 9 4 6 5 1 2 3 # vertex name
1 1 1 2 2 2 3 3 3 # community
Since the sequences match you could assign the membership as an vertex-attribute like this (as proposed by @chinsoon12):
V(g)$community <- membership(cd)
Upvotes: 1