Search code examples
rgraphigraphgraph-visualization

How to use a different input to draw community polygons in igraph for R?


Could you please help me?

I love plotting networks with igraph for R. One nice feature is drawing polygons around the communities detected by a given algorithm.

When you use one of the community detection algorithms built in igraph, that's pretty straightforward. Like in this example with a random bipartite graph:

library(igraph)
graph <- sample_bipartite(10, 10, p = 0.5)
graph
graph.lou = cluster_louvain(graph)
graph.lou$membership
length(graph.lou$membership)
plot(graph.lou, graph)

But how can I use another kind of input to draw those polygons?

For instance, I usually calculate modularity using the package bipartite for R, because it has other algorithms that are better suited for two-mode networks.

So I'm trying to use the output from bipartite as an input for drawing community polygons in igraph. As in the following example:

library(bipartite)
matrix <- as_incidence_matrix(graph)
matrix
matrix.bec = computeModules(matrix, method = "Beckett")
modules <- module2constraints(matrix.bec)
modules
length(modules)
plot(modules, graph)

From the output of the computeModules function I'm able to extract a vector with community memberships using the module2constraints function. When I try to use it as a plotting input, I get this error message:

Error in xy.coords(x, y, xlabel, ylabel, log) : 
  'x' and 'y' lengths differ

Is it possible to use this output from bipartite in igraph, so polygons are automatically drawn around the communities?

I've looked into the documentation, searched here on StackOverflow, experimented some tricks, but found no solution.

Thank you very much!


Solution

  • I've found a solution, with help given in another question!

    Actually, another way to draw polygons around communities in igraph for R is by using the argument mark.groups of the function plot.

    However, this argument accepts only lists of community membership. So, if you want to use an output of the package bipartite in the format of a vector together with an igraph object, you need to convert it to a list first.

    The info contained in the vector modules described in the original question needs to be complemented with vertex names and first become a data frame, then a list:

    number <- seq(1:10)
    row <- "row"
    rowlabels <- paste(row, number, sep = "")
    column <- "col"
    columnlabels <- paste(column, number, sep = "")
    
    matrix <- matrix(data = rbinom(100,size=1,prob=0.5), nrow = 10, ncol = 10,
                      dimnames = list(rowlabels, columnlabels))
    
    library(bipartite)
    matrix.bec <- computeModules(matrix, method = "Beckett")
    modules <- module2constraints(matrix.bec)
    
    df <- data.frame(c(rownames(matrix), colnames(matrix)), modules) 
    colnames(df) <- c("vertices", "modules")
    list <- split(df$vertices, df$modules)
    

    Now the object list can be used as a drawing input together with an igraph object:

    library(igraph)
    graph <- graph_from_incidence_matrix(matrix, directed = F)
    
    plot(graph,
         mark.groups = list)
    

    That's one way to make bipartite and igraph talk to one another!

    Thank you very much!