Reputation: 451
I'm working on a script to visualize communities in a large network. I'd like to select edges in a graph based on the community membership of their nodes, and then change their color attributes.
For example, I can construct a graph and give the nodes unique names like this:
library(igraph)
library(random)
g <- barabasi.game(100)
V(g)$name <- randomStrings(100,len=2,digits=FALSE,loweralpha=FALSE)
wt <- walktrap.community(g)
Then choose one community to visualize and create an induced subgraph:
v3 <- V(g)[membership(wt)==3]
g3 <- induced.subgraph(g,v3)
The best way I've found to get matching edges is like this:
matching_edge <- function(g1,e,g2) {
# given an edge e in g1, return the corresponding edge in g2
name1 <- V(g1)[get.edges(g1,e)[1,1]]$name
name2 <- V(g1)[get.edges(g1,e)[1,2]]$name
E(g2)[get.edge.ids(g2,c(name1,name2))]
}
E(g)$color = 'gray'
for (e in E(g3)) {
eg <- matching_edge(g3,e,g)
E(g)[eg]$color <- 'red'
}
And finally, my plot:
plot(g,
vertex.label=NA,
vertex.shape="none",
vertex.size=0,
edge.arrow.mode=0,
edge.width=1)
This works all right, but the loop with matching_edge()
gets painfully slow with large-ish graphs of a few thousand nodes. It seems like there should be a better way to do this, but I'm at a loss for what it is.
Any ideas?
Upvotes: 1
Views: 1382
Reputation: 168
You do not need to produce a subgraph for this.
constructing the graph:
library(igraph)
g <- barabasi.game(100)
wt <- walktrap.community(g)
making an array of colours and assigning it to the edges based on the community of their source node:
linkcolors<-rainbow(max(wt$membership))
E(g)$color <- linkcolors[membership(wt)[tail_of(g,E(g))]]
plot:
plot(g,
vertex.label=NA,
vertex.shape="none",
vertex.size=0,
edge.arrow.mode=0,
edge.width=1)
here's a longer, step by step version of the solution:
# the largest membership id equals the number of communities
numberofcommunities<- max(wt$membership)
# array of as many colours as there are communities
linkcolors<-rainbow(numberofcommunities)
# array with the source vertex of each edge
sourcenodes<-tail_of(g,E(g))
# array with community of the source vertex of each edge
linkmemberships<- membership(wt)[sourcenodes]
# array with colours corresponding to the
# community of the source vertex of each edge
linkcolors <- linkcolors[linkmemberships]
E(g)$color <- linkcolors
If you want to use the community of the target node instead, use head_of() instead of tail_of().
To only colour edges with the source and target node in the same community and to treat edges between communities differently (for example for undirected graphs), add this before plotting:
# get edges between communities:
between_communities_edges<-which(membership(wt)[tail_of(g,E(g))]!=membership(wt)[head_of(g,E(g))])
# do something with them:
E(g)[between_communities_edges]$color='grey95'
Upvotes: 2