cjolley
cjolley

Reputation: 451

R igraph: Matching edges between two graphs

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

Answers (1)

Ma Ba
Ma Ba

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

Related Questions