How to Make Grouped Layout in Igraph

How to make grouped layout in igraph?

To expand on Gabor's suggestion, I have created this function:

weight.community=function(row,membership,weigth.within,weight.between){
if(as.numeric(membership[which(names(membership)==row[1])])==as.numeric(membership[which(names(membership)==row[2])])){
weight=weigth.within
}else{
weight=weight.between
}
return(weight)
}

Simply apply it over the rows of the matrix of edges of your graph (given by get.edgelist(your_graph)) to set the new edge weights (membership is the membership vector from the result of any community detection algorithm):

E(g)$weight=apply(get.edgelist(g),1,weight.community,membership,10,1)

Then, simply use a layout algorithm that accepts edge weights such as the fruchterman.reingold as suggested by Gabor. You can tweak the weights arguments to obtain the graph you want. For instance:

E(g)$weight=apply(get.edgelist(g),1,weight.community,membership,10,1)
g$layout=layout.fruchterman.reingold(g,weights=E(g)$weight)
plot(g)

Sample Image

E(g)$weight=apply(get.edgelist(g),1,weight.community,membership,1000,1)
g$layout=layout.fruchterman.reingold(g,weights=E(g)$weight)
plot(g)

Sample Image

Note 1: the transparency/colors of the edges are other parameters of my graphs. I have colored nodes by community to shows that it indeed works.

Note 2: make sure to use membership(comm) and not comm$membership, where comm is the result of the community detection algorithm (e.g., comm=leading.eigenvector.community(g)). The reason is that in the first case, you get a numeric vector with names (what we want), and in the second case, the same vector without names.

To get consensus of multiple community detection algorithms, see this function.

How to create layout that will plot nodes in the same group close together?

Using a very minor change to your code, I get an understandable result (although I am only using the 100 points that you provided). Your code ran simplify after you ran cluster_walktrap. I ran simplify first. I also set the random seed so that the results would be reproducible.
I get.

library(igraph)
g = graph.data.frame(dat[,c('Var1','Var2')], directed = F) # coerces the data into a two-column matrix format that igraph likes
g <- simplify(g) # remove loops and multiple edges
cluster=cluster_walktrap(g)
list=groups (cluster)
g$value<-cluster$membership[as.character(g$Var1)]
set.seed(123)
plot(cluster,g, vertex.size = 5, edge.width = .1)

Cluster graph

This pretty clearly has two groups; blue nodes in one group, orange nodes in the other.
Links that connect nodes in the same group are black. Those links that connect nodes in
different groups are in red.

Change Layout Structure in IGraph Plot based on Community

You have to calculate the Kamada-Kawai layout with an artificial weight vector that assigns a high weight to edges within clusters and a low weight to edges that cross cluster boundaries:

> graph <- grg.game(100, 0.2)                 # example graph
> cl <- fastgreedy.community(graph)
> weights <- ifelse(crossing(cl, graph), 1, 100)
> layout <- layout_with_kk(graph, weights=weights)
> plot(graph, layout=layout)

The trick here is the ifelse(crossing(cl, graph), 1, 100) part -- crossing(cl, graph) takes a clustering and the graph that the clustering belongs to, and returns a Boolean vector that defines for each edge whether the edge is crossing cluster boundaries or not. The ifelse() call then simply replaces TRUE (i.e. edge crossing boundaries) in this vector with 1 and FALSE (i.e. edge stays within the cluster) with 0.

R, igraph: ordered layout

Since a layout in igraph is just a matrix of {x,y} coordinates, you can set the x-coordinates equal to your levels.

g <- make_graph(~A-C-B, C-D, E-D-F)
V(g)$level <- c(1,2,1,3,4,4)
l <- matrix(c(V(g)$level,1,2,3,2,3,1),nrow=length(V(g)$level),ncol=2)
plot(g, layout=l)

Sample Image

I just did the y-axis by hand, but you can construct it as you see fit.


Using Sugiyama layout

Sugiyama layout works by adding layers. There are a lot of options with the layout, but, basically, it tries to create a hierarchical representation of the graph.

l <- layout_with_sugiyama(g, layers = -V(g)$level)$layout
#note the "-", this ensures that the smaller level values get small x coordinates

plot(g,layout=l[,c(2,1)])

how to make concentric circles layout in igraph (R)

There is the layout_in_circle option if you only wanted one circle. You could apply that separately to each of your groups with something like this

layout_in_circles <- function(g, group=1) {
layout <- lapply(split(V(g), group), function(x) {
layout_in_circle(induced_subgraph(g,x))
})
layout <- Map(`*`, layout, seq_along(layout))
x <- matrix(0, nrow=vcount(g), ncol=2)
split(x, group) <- layout
x
}

Then you could plot with

plot(g, layout=layout_in_circles(g, group=V(g)>5))

It doesn't do anything special to try to make the edges pretty. But I guess the point is you can define whatever function you want to control the layout by returning a matrix of coordinates.

Sample Image

igraph group vertices based on community

I have implemented such a function in my package NetPathMiner, called layoutVertexByAttribute.

library(igraph)
library(NetPathMiner)

g <- graph.data.frame(message)
g <- setAttribute(g, "sender", sender_country)

l = layoutVertexByAttr(g, "sender", cluster.strength=10, layout=layout.kamada.kawai)

plotNetwork(g, vertex.color="sender",layout=l)

You can look at the source code here or view the vignette for more details.

Plot

EDIT:

Since installing the package seems a bit difficult if you don't use Bioconductor, I will write a simpler version of the function here.

layout.by.attr <- function(graph, wc, cluster.strength=1,layout=layout.auto) {  
g <- graph.edgelist(get.edgelist(graph)) # create a lightweight copy of graph w/o the attributes.
E(g)$weight <- 1

attr <- cbind(id=1:vcount(g), val=wc)
g <- g + vertices(unique(attr[,2])) + igraph::edges(unlist(t(attr)), weight=cluster.strength)

l <- layout(g, weights=E(g)$weight)[1:vcount(graph),]
return(l)
}

To use it with your example:

g <- graph.data.frame(message) 

l = layoutVertexByAttr(g, sender_country, cluster.strength=10, layout=layout.kamada.kawai)

plot.igraph(g, vertex.color=sender_country, layout=l)


Related Topics



Leave a reply



Submit