Using CONDOR for community detection in bipartite graphs

Introduction

COmplex Network Description Of Regulators (CONDOR) implements methods for clustering bipartite networks and estimating the contribution of each node to its community’s modularity. For an application of this method to identify diesease-associated single nucleotide polymorphisms, see (https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1005033).

Installation

CONDOR can be installed through netZooR as follows:

if(!requireNamespace("BiocManager", quietly = TRUE))
    install.packages("BiocManager")
BiocManager::install("netZooR")

Implementing the Bipartite Modularity Maximization

The code in condorModularityMax is an implementation of the method described in Michael Barber’s paper Modularity and community detection in bipartite networks (Phys. Rev. E 76, 066102 (2007)). A few general comments:

Workflow

library(netZooR)

condor works with an edgelist (elist in the code below) as its input.

r = c(1,1,1,2,2,2,3,3,3,4,4);
b = c(1,2,3,1,2,4,2,3,4,3,4);
reds <- c("Alice","Sue","Janine","Mary")
blues <- c("Bob","John","Ed","Hank")
elist <- data.frame(red=reds[r], blue=blues[b])

In elist, notice all nodes of the same type–women and men in this case–appear in the same column together. This is a requirement. createCondorObject will throw an error if a node appears in both columns.

condor.object <- createCondorObject(elist)

A condor.object is just a list. You can look at the different items using names

names(condor.object)
## [1] "G"          "edges"      "Qcoms"      "modularity" "red.memb"  
## [6] "blue.memb"  "qscores"

condorCluster will cluster the nodes and produce the overall modularity along with two community membership data.frames:

condor.object <- condorCluster(condor.object)
## [1] "modularity of projected graph 0"
## [1] "Q = 0"
## [1] "Q = 0.173553719008264"
## [1] "Q = 0.231404958677686"
## [1] "Q = 0.231404958677686"
print(condor.object$red.memb)
##   red.names com
## 1     Alice   2
## 2    Janine   1
## 3      Mary   1
## 4       Sue   2
print(condor.object$blue.memb)
##   blue.names com
## 1        Bob   2
## 2         Ed   1
## 3       Hank   1
## 4       John   2

Nodes in first community are {Alice, John, Bob, Sue}, nodes in second community are {Ed, Janine, Hank, Mary} based on the modularity maximization. Here’s a picture:

gtoy = graph.edgelist(as.matrix(elist),directed=FALSE)
set.graph.attribute(gtoy, "layout", layout.kamada.kawai(gtoy))
## IGRAPH 18b7086 UN-- 8 11 -- 
## + attr: layout (g/n), name (v/c)
## + edges from 18b7086 (vertex names):
##  [1] Alice--Bob    Alice--John   Alice--Ed     Bob  --Sue    John --Sue   
##  [6] Sue  --Hank   John --Janine Ed   --Janine Hank --Janine Ed   --Mary  
## [11] Hank --Mary
V(gtoy)[c(reds,blues)]$color <- c(rep("red",4),rep("blue",4))
plot(gtoy,vertex.label.dist=2)

To get each node’s modularity contribution (as a fraction of the community’s modularity), run

condor.object <- condorQscore(condor.object)

If you have a subset of nodes that you think are more likely to lie at the cores of your communities, you can test this using condorCoreEnrich:

q_women <- condor.object$qscores$red.qscore
core_stats <- condorCoreEnrich(test_nodes=c("Alice","Mary"),
                                 q=q_women,perm=TRUE,plot.hist=TRUE)

condor also works on weighted bipartite networks. The package comes with a quantitative pollination network data set (Small 1976) taken from the NCEAS interaction webs data base, containing interactions between 13 plants and 34 pollinators.

data(small1976)
condor.object <- createCondorObject(small1976)
condor.object <- condorCluster(condor.object, project=FALSE)
## [1] "modularity of projected graph 0.525346928655047"
## [1] "Q = 0.52666696475026"
## [1] "Q = 0.52666696475026"
condorPlotHeatmap(condor.object)

Session Information

sessionInfo()
## R version 4.4.1 (2024-06-14)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.1 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so;  LAPACK version 3.12.0
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=C              
##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## time zone: Etc/UTC
## tzcode source: system (glibc)
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] netZooR_1.11.0      matrixcalc_1.0-6    yarn_1.31.0        
## [4] pandaR_1.37.0       Biobase_2.67.0      BiocGenerics_0.53.0
## [7] reticulate_1.39.0   igraph_2.1.1       
## 
## loaded via a namespace (and not attached):
##   [1] STRINGdb_2.17.3             fs_1.6.4                   
##   [3] matrixStats_1.4.1           bitops_1.0-9               
##   [5] httr_1.4.7                  RColorBrewer_1.1-3         
##   [7] doParallel_1.0.17           Rgraphviz_2.49.1           
##   [9] repr_1.1.7                  tools_4.4.1                
##  [11] doRNG_1.8.6                 backports_1.5.0            
##  [13] utf8_1.2.4                  R6_2.5.1                   
##  [15] vegan_2.6-8                 HDF5Array_1.33.8           
##  [17] mgcv_1.9-1                  rhdf5filters_1.17.0        
##  [19] permute_0.9-7               prettyunits_1.2.0          
##  [21] base64_2.0.2                preprocessCore_1.67.1      
##  [23] cli_3.6.3                   penalized_0.9-52           
##  [25] sass_0.4.9                  readr_2.1.5                
##  [27] genefilter_1.87.0           askpass_1.2.1              
##  [29] Rsamtools_2.21.2            pbdZMQ_0.3-13              
##  [31] siggenes_1.79.0             illuminaio_0.47.0          
##  [33] rentrez_1.2.3               AnnotationForge_1.49.0     
##  [35] scrime_1.3.5                plotrix_3.8-4              
##  [37] limma_3.61.12               RSQLite_2.3.7              
##  [39] generics_0.1.3              GOstats_2.71.0             
##  [41] quantro_1.39.0              BiocIO_1.17.0              
##  [43] gtools_3.9.5                dplyr_1.1.4                
##  [45] GO.db_3.20.0                Matrix_1.7-1               
##  [47] fansi_1.0.6                 S4Vectors_0.43.2           
##  [49] abind_1.4-8                 lifecycle_1.0.4            
##  [51] yaml_2.3.10                 edgeR_4.3.21               
##  [53] SummarizedExperiment_1.35.5 gplots_3.2.0               
##  [55] rhdf5_2.49.0                SparseArray_1.5.45         
##  [57] BiocFileCache_2.15.0        grid_4.4.1                 
##  [59] blob_1.2.4                  crayon_1.5.3               
##  [61] lattice_0.22-6              GenomicFeatures_1.57.1     
##  [63] annotate_1.85.0             KEGGREST_1.45.1            
##  [65] sys_3.4.3                   maketools_1.3.1            
##  [67] pillar_1.9.0                knitr_1.48                 
##  [69] beanplot_1.3.1              GenomicRanges_1.57.2       
##  [71] rjson_0.2.23                codetools_0.2-20           
##  [73] glue_1.8.0                  downloader_0.4             
##  [75] data.table_1.16.2           vctrs_0.6.5                
##  [77] png_0.1-8                   gtable_0.3.6               
##  [79] assertthat_0.2.1            gsubfn_0.7                 
##  [81] cachem_1.1.0                xfun_0.48                  
##  [83] S4Arrays_1.5.11             survival_3.7-0             
##  [85] iterators_1.0.14            statmod_1.5.0              
##  [87] nlme_3.1-166                Category_2.73.0            
##  [89] bit64_4.5.2                 progress_1.2.3             
##  [91] filelock_1.0.3              GenomeInfoDb_1.41.2        
##  [93] bslib_0.8.0                 nor1mix_1.3-3              
##  [95] KernSmooth_2.23-24          colorspace_2.1-1           
##  [97] DBI_1.2.3                   nnet_7.3-19                
##  [99] tidyselect_1.2.1            bit_4.5.0                  
## [101] compiler_4.4.1              curl_5.2.3                 
## [103] chron_2.3-61                httr2_1.0.5                
## [105] graph_1.83.0                xml2_1.3.6                 
## [107] ggdendro_0.2.0              DelayedArray_0.33.1        
## [109] rtracklayer_1.65.0          scales_1.3.0               
## [111] caTools_1.18.3              hexbin_1.28.4              
## [113] quadprog_1.5-8              RBGL_1.81.0                
## [115] rappdirs_0.3.3              stringr_1.5.1              
## [117] digest_0.6.37               rmarkdown_2.28             
## [119] GEOquery_2.75.0             XVector_0.45.0             
## [121] htmltools_0.5.8.1           pkgconfig_2.0.3            
## [123] base64enc_0.1-3             sparseMatrixStats_1.17.2   
## [125] MatrixGenerics_1.17.1       highr_0.11                 
## [127] dbplyr_2.5.0                fastmap_1.2.0              
## [129] rlang_1.1.4                 UCSC.utils_1.1.0           
## [131] DelayedMatrixStats_1.29.0   jquerylib_0.1.4            
## [133] jsonlite_1.8.9              BiocParallel_1.41.0        
## [135] mclust_6.1.1                RCurl_1.98-1.16            
## [137] magrittr_2.0.3              GenomeInfoDbData_1.2.13    
## [139] Rhdf5lib_1.27.0             IRkernel_1.3.2             
## [141] munsell_0.5.1               Rcpp_1.0.13                
## [143] proto_1.0.0                 sqldf_0.4-11               
## [145] stringi_1.8.4               RJSONIO_1.3-1.9            
## [147] zlibbioc_1.51.2             MASS_7.3-61                
## [149] plyr_1.8.9                  bumphunter_1.49.0          
## [151] org.Hs.eg.db_3.20.0         minfi_1.51.0               
## [153] parallel_4.4.1              Biostrings_2.75.0          
## [155] IRdisplay_1.1               splines_4.4.1              
## [157] multtest_2.61.0             hash_2.2.6.3               
## [159] hms_1.1.3                   locfit_1.5-9.10            
## [161] uuid_1.2-1                  RUnit_0.4.33               
## [163] base64url_1.4               rngtools_1.5.2             
## [165] buildtools_1.0.0            reshape2_1.4.4             
## [167] biomaRt_2.63.0              stats4_4.4.1               
## [169] XML_3.99-0.17               evaluate_1.0.1             
## [171] tzdb_0.4.0                  foreach_1.5.2              
## [173] tidyr_1.3.1                 openssl_2.2.2              
## [175] purrr_1.0.2                 reshape_0.8.9              
## [177] ggplot2_3.5.1               xtable_1.8-4               
## [179] restfulr_0.0.15             viridisLite_0.4.2          
## [181] RCy3_2.25.2                 tibble_3.2.1               
## [183] memoise_2.0.1               AnnotationDbi_1.69.0       
## [185] GenomicAlignments_1.41.0    IRanges_2.39.2             
## [187] cluster_2.1.6               GSEABase_1.67.1