library(sbm)đ Block models for Multilayer networks
Tutorial based on the sbm package
This tutorial illustrates the use of the block models on multilayer networks.
0. Requirements
The only package required for the analysis is sbm.
1. From bipartite to multipartite network
First, we consider a Plantđ±-Antđ-Pollinatorđ -BirdđŠ network which can be seen as a multipartite network, as defined in the course.
1.A Dattilo dataset
The dataset âcompiled and conducted by DĂĄttilo et al. (2016) at Centro de Investigaciones Costeras La Mancha (CICOLMA), located on the central coast of the Gulf of Mexico, Veracruz, Mexicoâ involves three general types of plant-animal mutualistic interaction: pollination, seed dispersal by frugivorous birds, and protective mutualisms between ants and plants with extrafloral nectaries.
The dataset âwhich is one of the largest compiled so far with respect to species richness, number of interactions and sampling effortâ includes 4 functional groups (FG), namely plants, pollinator species (referred as floral visitors), ant species and frugivorous bird species. Three binary bipartite networks have been collected representing interactions between
- 1/ plants and florals visitor, đ± - đ
- 2/ plants and ants, đ± - đ
- 3/ plants and seed dispersal birds đ± - đŠ
resulting into three bipartite networks.
The FG are of respective sizes: \(n_1 = 141\) plant đ± species, \(n_2 = 173\) pollinator đ species, \(n_3 = 46\) frugivorous bird đŠ species and \(n_4 = 30\) ant đ species.
The 3 networks contain \(753\) observed interactions of which \(55\%\) are plant-pollinator đ± - đ interactions, \(17\%\) are plant-birds đ± - đŠ interactions and \(28\%\) are plant-ant đ± - đ interactions.
data(multipartiteEcologicalNetwork)
str(multipartiteEcologicalNetwork)
#> List of 3
#> $ Inc_plant_ant : int [1:141, 1:30] 0 1 0 0 1 0 1 0 1 0 ...
#> ..- attr(*, "dimnames")=List of 2
#> .. ..$ : chr [1:141] "Acacia_cornigera" "Acacia_macracantha" "Achatocarpus_nigricans" "Agave_angustifolia" ...
#> .. ..$ : chr [1:30] "Camponotus_planatus" "Camponotus_mucronatus" "Paratrechina_longicornis_" "Crematogaster_brevispinosa" ...
#> $ Inc_plant_bird : int [1:141, 1:46] 0 0 1 0 0 0 0 0 0 0 ...
#> ..- attr(*, "dimnames")=List of 2
#> .. ..$ : chr [1:141] "Acacia_cornigera" "Acacia_macracantha" "Achatocarpus_nigricans" "Agave_angustifolia" ...
#> .. ..$ : chr [1:46] "Cyanocorax_morio" "Tyrannus_forficatus" "Ortalis_vetula" "Myiozetetes_similis" ...
#> $ Inc_plant_flovis: int [1:141, 1:173] 0 0 0 0 0 0 0 1 1 0 ...
#> ..- attr(*, "dimnames")=List of 2
#> .. ..$ : chr [1:141] "Acacia_cornigera" "Acacia_macracantha" "Achatocarpus_nigricans" "Agave_angustifolia" ...
#> .. ..$ : chr [1:173] "Apis_melifera" "Lasioglossum_sp1" "Trigona_nigra" "Ascia_monuste" ...
names(multipartiteEcologicalNetwork)
#> [1] "Inc_plant_ant" "Inc_plant_bird" "Inc_plant_flovis"
Net <- multipartiteEcologicalNetwork1.B Inference of multipartite network
From bipartite to multipartite
As seen on Day 3, we could look for blocks of plants when they are interacting with ants, birds and pollinators separately and âcompareâ the blocks of plants?
Code
res_biSBM_plant_bird <- estimateBipartiteSBM(Net$Inc_plant_bird)
res_biSBM_plant_pollinator <- estimateBipartiteSBM(Net$Inc_plant_flovis)
res_biSBM_plant_ant <- estimateBipartiteSBM(Net$Inc_plant_ant)However, plants are in interactions with all of them, so we would like to consider all the interactions at the same time.
Formatting the data
We format the data to be able to use our functions i.e. we transform the matrices into an list containing
- the matrix itself,
- âmodelâ: the distribution you want to fit on the network
- âtypeâ :
simplefor simple network, âbipartiteâ if it is bipartite (it can be deduces from the size of the matrix) - âdimLabelsâ: the name of functional group in row and the name of functional group in column.
The three created objects are gathered in a list.
To do so, we use the function defineNetwork.
type = "bipartite"
model = "bernoulli"
PlantFlovis <- defineSBM(netMat=Net$Inc_plant_flovis, model=model, dimLabels = c("Plants",
"Flovis"))
PlantAnt <- defineSBM(netMat=Net$Inc_plant_ant, model=model, dimLabels = c("Plants",
"Ants"))
PlantBird <- defineSBM(netMat = Net$Inc_plant_bird, model = model, dimLabels = c("Plants",
"Birds"))To make it work, you must be sure to have exactly the same set of plants (in the same order) in each matrix. The dimLabels arguments specifies which group is in row or columns in the matrices you provide.
If one wants to keep a track of the names of the species, they should be used as rownames and colnames in the matrices.
PlantFlovis$networkData[1:2, 1:2]
#> Apis_melifera Lasioglossum_sp1
#> Acacia_cornigera 0 1
#> Acacia_macracantha 0 0A plot of the data can be obtained with following command.
plotMyMultipartiteMatrix(list(PlantFlovis, PlantAnt, PlantBird))Finding clusters in the 3 networks jointly
We are now ready to find block of species (based on Bar-Hen, Barbillon, and Donnet (2022)).
data(multipartiteEcologicalNetwork)
estimOptions = list(initBM = FALSE)
listSBM <- list(PlantFlovis, PlantAnt, PlantBird)
res_MSBM_dattilo <- estimateMultipartiteSBM(listSBM, estimOptions)As yesterday, we can plot the results.
plot(res_MSBM_dattilo) plot(res_MSBM_dattilo, type = "expected")2. Multiplex networks
Assume that you have two (or more) networks involving the same species, but representing different interactions. For instance
- Observations at different times (on the year, of the day or along time)
- Different types of interactions : mutualistic and co-occurrence.
These networks can be bipartite or simple. We provide here a synthetic dataset, maybe you have one in mind.
load(file='synthetic_multiplex.rda')
dim(X1)
#> [1] 70 150
dim(X2)
#> [1] 70 150We provide a function to plot such a multiplex data. First the data must be formatted.
SBM1 <-defineSBM(netMat = X1,model = "bernoulli",dimLabels =c('plant','polli') )
SBM2 <-defineSBM(netMat = X2,model = "bernoulli",dimLabels =c('plant','polli') )
plotMyMultiplexMatrix(list(SBM1,SBM2))The blocks can be discovered as follows.
res_Multiplex <- estimateMultiplexSBM(list(SBM1,SBM2), dependent = FALSE)The argument dependant = FALSE means that, conditionally on \(Z_i =k, W_j = \ell\), \(X^1_{ij}\) and \(X^2_{ij}\) are independent variables. As a consequent, the model is: \[\begin{eqnarray*}
Z_i &\sim& \mathcal{C}at_K(\pi_1,\dots, \pi_K)\\
W_j &\sim& \mathcal{C}at_L(\rho_1,\dots, \rho_L)\\
X^1_{ij} \sim Z_i=k, W_j = \ell&\sim & \mathcal{B}ern(\alpha^1_{k\ell})\\
X^2_{ij}\sim Z_i=k, W_j = \ell&\sim & \mathcal{B}ern(\alpha^2_{k\ell})
\end{eqnarray*}\] If you have two simple binary networks, you can relax the assumption of independence, relying on Barbillon et al. (2017).
You can plot the results as before by reordering the matrices
plot(res_Multiplex)
plot(res_Multiplex,type='expected')