Search code examples
rfor-loopmatrixnetwork-programmingigraph

Calculating network indexes for 1000 simulated null matrices in R


I am trying to calculate network indexes (clustering, modularity, edge density, degree, centrality etc) from 1000 simulated null matrices using the igraph package in R. The data I'm using is a mixed-species bird flock data that I've used to generate the null matrices.

Here's the code:

    ## Construct null matrices ##
    library(EcoSimR)
    library(igraph)
    # creating a 1000 empty matrices 
    fl_emp <- lapply(1:1000, function(i) data.frame()) 
    # simulating 1000 matrices by randomization 
    fl_wp_n <- replicate(1000, sim5(fl_wp[,3:ncol(fl_wp)]),simplify = FALSE) #fl_wp is the raw data
    #sim5 function is from the package 'EcoSimR'
    
    for(i in 1:length(fl_emp))
    {
      fl_wp_ig <- graph_from_incidence_matrix(fl_wp_n[[i]]) #Creating new igraph object to convert the null matrices to igraph objects to calculate network indexes
      fl_wp_cw <- cluster_walktrap(fl_wp_ig[[i]])
      fl_wp_mod <- modularity(fl_wp_cw[[i]]) ##Network index, this does not work
    }

Here's what the simulated matrices look like(fl_wp_n) : [1]: https://i.sstatic.net/1Q0Na.png

It is basically a list of 1000 elements, where each element is a simulated 133x74 matrix where the rows represent flock ID and the columns represent Species ID.

This is the error I'm getting when I run the loop:

> for(i in 1:length(fl_emp))
+ {
+   fl_wp_ig <- graph_from_incidence_matrix(fl_wp_n[[i]])
+   fl_wp_cw <- cluster_walktrap(fl_wp_ig[[i]])
+   fl_wp_mod <- modularity(fl_wp_cw[[i]])
+ }
Error in cluster_walktrap(fl_wp_ig[[i]]) : Not a graph object!

It seems to be not recognizing fl_wp_ig as an igraph object. Any idea why? Is there a better way to do calculate indices for a 1000 matrices in one loop? Sorry if this is a dumb question, I'm new to igraph and R in general

Thanks a lot in advance!


Solution

  • If you have a look at the documentation for 1. cluster_walktrap, you will see the function expects a graph object. As @Szabolcs pointed out, when you are index fl_wp_ig[[i]] in the for-loop, you are returning the vertices adjacent to vertex [[i]], but not the graph itself. You only should iterate over fl_wp_n[[i]] because you want to use every time a 'matrix' but not the other variables.

    So you could try:

    list_outputs = list()
    for(i in 1:length(fl_emp))
    {
      # fl_wp_n[[i]] gets 1 matrix each iteration. Output -> graph object
      fl_wp_ig <- graph_from_incidence_matrix(fl_wp_n[[i]])
      # Use the whole graph object fl_wp_ig
      fl_wp_cw <- cluster_walktrap(fl_wp_ig)
      # Use the whole fl_wp_cw output
      fl_wp_mod <- modularity(fl_wp_cw)
    
      # NOTE that you are not storing the result of each iteration in a variable to keep it, 
      # you are overwritting fl_wp_mod
      # You could have create a empty list before the for-loop and then fill it
    
      list_outputs = append(list_outputs, fl_wp_mod)
    }
    

    Also, if you find it difficult to see the whole picture, you could try to create a custom function and use apply methods instead of a for-loop.

    # Custom function
    cluster_modularity = function(graph_object){
      # takes only one graph_object at time
      fl_wp_ig <- graph_from_incidence_matrix(graph_object)
      fl_wp_cw <- cluster_walktrap(fl_wp_ig)
      fl_wp_mod <- modularity(fl_wp_cw)
    }
    
    # Iterate using lapply to store the outputs in a list - for example
    list_outputs = lapply(fl_wp_n, cluster_modularity)