Akira Terui May 07, 2021
The package mcbrnet
is composed of two functions: brnet()
and
mcsim()
.
-
brnet
: Functionbrnet()
generates a random branching network with the specified number of patches and probability of branching. The function returns adjacency and distance matrices, hypothetical environmental values at each patch, and the number of patches upstream (akin to the watershed area in river networks). The output may be used in functionmcsim()
to simulate metacommunity dynamics in a branching network. -
mcsim
: Functionmcsim()
simulates metacommunity dynamics. By default, it produces a square-shaped landscape with randomly distributed habitat patches (x- and y-coordinates are drawn from a uniform distribution). If a distance matrix is given, the function simulates metacommunity dynamics in the specified landscape. Functionmcsim()
follows a general framework proposed by Thompson et al. (2020). However, it has several unique features that are detailed in the following sections.
The mcbrnet
package can be installed with the following script:
#install.packages("remotes")
remotes::install_github("aterui/mcbrnet")
library(mcbrnet)
The key arguments are the number of habitat patches (n_patch
) and the
probability of branching (p_branch
), which users must specify. With
these parameters, the function generates a branching network through the
following steps:
-
Draw the number of branches in the network. An individual branch is defined as a series of connected patches from one confluence (or outlet) to the next confluence upstream (or upstream terminal). The number of branches in a network BR is drawn from a binomial distribution as BR ~ Binomial(N, Pbr), where N is the number of patches and Pbr is the branching probability.
-
Draw the number of patches in each branch. The number of patches in each branch Nbr is drawn from a geometric distribution as Nbr ~ Ge(Pbr) but conditional on ΣNbr = N.
-
Organize branches into a bifurcating branching network.
Sample script:
net <- brnet(n_patch = 50, p_branch = 0.5)
The function returns:
-
adjacency_matrix
: adjacency matrix. -
distance_matrix
: distance matrix. Distance between patches is measured as the number of steps required to reach from the focal patch to the target patch through the network. -
weighted_distance_matrix
: weighted distance matrix. Upstream steps may be weighted (see Custom setting). -
df_patch
: a data frame (dplyr::tibble
) containing patch attributes.- patch_id: patch ID.
- branch_id: branch ID.
- environment: environmental value at each patch (see below for details)
- disturbance: disturbance level (i.e., proportional mortality) at each patch (see below for details)
- n_patch_upstream: the number of upstream contributing patches (including the focal patch itself; akin to the watershed area in river networks).
The following script produce a branching network with n_patch = 50
and
p_branch = 0.5
. By default, brnet()
visualizes the generated network
using functions in packages igraph
(Csardi and Nepusz 2006) and
plotfunctions
(van Rij 2020) (plot = FALSE
to disable):
net <- brnet(n_patch = 50, p_branch = 0.5)
Randomly generated environmental values color patches and patches’ size is proportional to the number of patches upstream. To view matrices, type the following script:
# adjacency matrix
# showing 10 patches for example
net$adjacency_matrix[1:10, 1:10]
## patch1 patch2 patch3 patch4 patch5 patch6 patch7 patch8 patch9 patch10
## patch1 0 0 0 0 0 0 0 0 0 0
## patch2 0 0 0 0 0 0 0 0 0 0
## patch3 0 0 0 1 0 0 0 0 0 0
## patch4 0 0 1 0 0 0 0 0 0 0
## patch5 0 0 0 0 0 0 0 0 0 0
## patch6 0 0 0 0 0 0 1 0 0 0
## patch7 0 0 0 0 0 1 0 0 0 0
## patch8 0 0 0 0 0 0 0 0 1 0
## patch9 0 0 0 0 0 0 0 1 0 1
## patch10 0 0 0 0 0 0 0 0 1 0
# distance matrix
# showing 10 patches for example
net$distance_matrix[1:10, 1:10]
## patch1 patch2 patch3 patch4 patch5 patch6 patch7 patch8 patch9 patch10
## patch1 0 9 3 4 3 12 13 9 10 11
## patch2 9 0 12 13 12 3 4 2 3 4
## patch3 3 12 0 1 2 15 16 12 13 14
## patch4 4 13 1 0 3 16 17 13 14 15
## patch5 3 12 2 3 0 15 16 12 13 14
## patch6 12 3 15 16 15 0 1 5 6 7
## patch7 13 4 16 17 16 1 0 6 7 8
## patch8 9 2 12 13 12 5 6 0 1 2
## patch9 10 3 13 14 13 6 7 1 0 1
## patch10 11 4 14 15 14 7 8 2 1 0
The following script lets you view branch ID, environmental values, and the number of upstream contributing patches for each patch:
net$df_patch
## # A tibble: 50 x 5
## patch_id branch_id environment disturbance n_patch_upstream
## <int> <dbl> <dbl> <dbl> <dbl>
## 1 1 1 -1.33 0.899 50
## 2 2 8 -0.693 0.899 9
## 3 3 6 -1.96 0.895 6
## 4 4 6 -1.93 0.895 5
## 5 5 23 -0.145 0.898 1
## 6 6 21 0.872 0.889 2
## 7 7 21 0.804 0.889 1
## 8 8 13 -0.890 0.889 5
## 9 9 13 -0.938 0.889 4
## 10 10 13 -0.967 0.889 3
## # ... with 40 more rows
Arguments: patch_label
, patch_scaling
, patch_size
Users may add patch labels using the argument patch_label
:
# patch ID
net <- brnet(n_patch = 50, p_branch = 0.5, patch_label = "patch")
# branch ID
net <- brnet(n_patch = 50, p_branch = 0.5, patch_label = "branch")
# number of upstream contributing patches
net <- brnet(n_patch = 50, p_branch = 0.5, patch_label = "n_upstream")
To remove patch size variation, set patch_scaling = FALSE
and specify
patch_size
:
# number of upstream contributing patches
net <- brnet(n_patch = 50, p_branch = 0.5, patch_scaling = FALSE, patch_size = 8)
Arguments: mean_env_source
, sd_env_source
, rho
, sd_env_lon
Some flexibility exists to simulate environmental values, which are determined through an autoregressive process, as detailed below:
-
Environmental values for upstream terminal patches (i.e., patches with no upstream patch) are drawn from a normal distribution as z1 ~ Normal(μsource, σsource2) (arguments
mean_env_source
andsd_env_source
). -
Downstream environmental values are determined by an autoregressive process as zx = ρzx-1 + εx (‘x-1’ means one patch upstream), where εx ~ Normal(0, σ2env) (argument
sd_env_lon
). At bifurcation patches (or confluence), the environmental value takes a weighted mean of the two contributing patches given the size of these patches s (the number of upstream contributing patches): zx = ω(ρz1,x-1 + ε1,x) + (1 - ω)(ρz2,x-1 + ε2,x), where ω = s1/(s1 + s2).
Users may change the values of μsource (default:
mean_env_source = 0
), σsource (sd_env_source = 1
), ρ
(rho = 1
), and σenv (sd_env_lon = 0.1
). Increasing the
value of sd_env_source
leads to greater variation in environmental
values at upstream terminals. The argument rho
(0 ≤ ρ ≤ 1) determines
the strength of longitudinal autocorrelation (the greater the stronger
autocorrelation). The argument sd_env_lon
(σenv > 0)
determines the strength of longitudinal environmental noise. The
following script produces a network with greater environmental variation
at upstream terminals (z1 ~ Normal(0, 32)),
weaker longitudinal autocorrelation (ρ = 0.5), and stronger local noises
(σenv = 0.5).
net <- brnet(n_patch = 50, p_branch = 0.5,
sd_env_source = 3, rho = 0.5, sd_env_lon = 0.5)
Arguments: mean_disturb_source
, sd_disturb_source
Some flexibility exists to simulate disturbance levels, as detailed below:
-
Disturbance levels for upstream terminal patches (i.e., patches with no upstream patch) are drawn from a normal distribution as m1 ~ Normal(μm, σm2). The argument
mean_disturb_source
controls the proportional mean of the disturbance level, which will be converted to a logit-scale value in the function (i.e., μm = logit(mean_disturb_source
)). The argumentsd_disturb_source
controls the variation in disturbance level among headwaters in a logit scale (i.e., σm =sd_disturb_source
) -
Downstream disturbance levels are identical to the adjacent upstream patch except at confluences. At bifurcation patches (or confluence), the disturbance value takes a weighted mean of the two contributing patches given the size of these patches s (the number of upstream contributing patches): mx = ωm1,x-1 + (1 - ω)m2,x-1, where ω = s1/(s1 + s2).
-
The logit-scale values will be back-transformed to the proportional values (return value = inv.logit(m))
Users may change the values of μm (default:
mean_disturb_source = 0.9
) and σm (sd_env_source = 0.1
).
Arguments: asymmetry_factor
Distance between patches is calculated as the number of steps from the origin to the target patch. Specifically, distance from patch x to y, dxy, is calculated as:
dxy = stepd + δstepu
where stepd the number of downstream steps, stepu
the number of upstream steps, and δ the asymmetry scaling factor
(asymmetry_factor
). Users may change δ to control the weight of
upstream steps. (1) δ = 1, upstream and dowstream steps have no
difference (default), (2) δ > 1, upstream steps have greater costs,
(3) δ < 1, downstream steps have greater costs. Changes to
asymmetry_factor
will be reflected in weighted_distance_matrix
.
The key arguments are the number of habitat patches (n_patch
) and the
number of species in a metacommunity (n_species
). The metacommunity
dynamics are simulated through (1) local dynamics (population growth and
competition among species), (2) immigration, and (3) emigration.
Sample script:
mc <- mcsim(n_patch = 5, n_species = 5)
The function returns:
-
df_dynamics
a data frame containing simulated metacommunity dynamics*.- timestep: time-step.
- patch_id: patch ID.
- mean_env: mean environmental condition at each patch.
- env: environmental condition at patch x and time-step t.
- carrying_capacity: carrying capacity at each patch.
- species: species ID.
- niche_optim: optimal environmental value for species i.
- r_xt: reproductive number of species i at patch x and time-step t.
- abundance: abundance of species i at patch x.
-
df_species
a data frame containing species attributes.- species: species ID.
- mean_abundance: mean abundance (arithmetic) of species i across sites and time-steps.
- r0: maximum reproductive number of species i.
- niche_optim: optimal environmental value for species i.
- sd_niche_width: niche width for species i.
- p_dispersal: dispersal probability of species i.
-
df_patch
a data frame containing patch attributes.- patch: patch ID.
- alpha_div: alpha diversity averaged across time-steps.
- mean_env: mean environmental condition at each patch.
- carrying_capacity: carrying capacity at each patch.
- connectivity: structural connectivity at each patch. See below for details.
-
df_diversity
a data frame containing diversity metrics (α, β, and γ). -
distance_matrix
a distance matrix used in the simulation. -
interaction_matrix
a species interaction matrix, in which species X (column) influences species Y (row).
*NOTE: The warm-up and burn-in periods will not be included in return values.
The following script simulates metacommunity dynamics with n_patch = 5
and n_species = 5
. By default, mcsim()
simulates metacommunity
dynamics with 200 warm-up (initialization with species introductions:
n_warmup
), 200 burn-in (burn-in period with no species introductions:
n_burnin
), and 1000 time-steps for records (n_timestep
).
mc <- mcsim(n_patch = 5, n_species = 5)
Users can visualize the simulated dynamics using plot = TRUE
, which
will show five sample patches and species that are randomly chosen:
mc <- mcsim(n_patch = 5, n_species = 5, plot = TRUE)
A named list of return values:
mc
## $df_dynamics
## # A tibble: 25,000 x 9
## timestep patch_id mean_env env carrying_capaci~ species niche_optim r_xt
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 1 0 -0.0494 100 1 -0.968 1.43
## 2 1 1 0 -0.0494 100 2 0.291 2.79
## 3 1 1 0 -0.0494 100 3 -0.562 1.29
## 4 1 1 0 -0.0494 100 4 -0.311 3.07
## 5 1 1 0 -0.0494 100 5 0.108 2.83
## 6 1 2 0 -0.0142 100 1 -0.968 1.35
## 7 1 2 0 -0.0142 100 2 0.291 2.85
## 8 1 2 0 -0.0142 100 3 -0.562 1.11
## 9 1 2 0 -0.0142 100 4 -0.311 2.97
## 10 1 2 0 -0.0142 100 5 0.108 2.86
## # ... with 24,990 more rows, and 1 more variable: abundance <dbl>
##
## $df_species
## # A tibble: 5 x 6
## species mean_abundance r0 niche_optim sd_niche_width p_dispersal
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 5.44 4 -0.968 0.752 0.1
## 2 2 61.0 4 0.291 0.696 0.1
## 3 3 0 4 -0.562 0.351 0.1
## 4 4 62.3 4 -0.311 0.536 0.1
## 5 5 60.6 4 0.108 0.807 0.1
##
## $df_patch
## # A tibble: 5 x 5
## patch_id alpha_div mean_env carrying_capacity connectivity
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 3.80 0 100 0.307
## 2 2 3.57 0 100 0.0674
## 3 3 3.68 0 100 0.0971
## 4 4 3.5 0 100 0.0388
## 5 5 3.81 0 100 0.281
##
## $df_diversity
## # A tibble: 1 x 3
## alpha_div beta_div gamma_div
## <dbl> <dbl> <dbl>
## 1 3.67 1.04 3.81
##
## $df_xy_coord
## # A tibble: 5 x 2
## x_coord y_coord
## <dbl> <dbl>
## 1 5.10 4.46
## 2 5.69 0.185
## 3 3.59 6.52
## 4 9.60 1.11
## 5 6.30 3.48
##
## $distance_matrix
## patch1 patch2 patch3 patch4 patch5
## patch1 0.000000 4.318499 2.546035 5.621133 1.550521
## patch2 4.318499 0.000000 6.670318 4.025012 3.352600
## patch3 2.546035 6.670318 0.000000 8.088696 4.065424
## patch4 5.621133 4.025012 8.088696 0.000000 4.072806
## patch5 1.550521 3.352600 4.065424 4.072806 0.000000
##
## $weighted_distance_matrix
## NULL
##
## $interaction_matrix
## sp1 sp2 sp3 sp4 sp5
## sp1 1 0 0 0 0
## sp2 0 1 0 0 0
## sp3 0 0 1 0 0
## sp4 0 0 0 1 0
## sp5 0 0 0 0 1
Return values of brnet()
are compatible with mcsim()
. For example,
df_patch$environment
, df_patch$n_patch_upstream
, and
df_patch$distance_matrix
may be used to inform parameters of
mcsim()
:
patch <- 100
net <- brnet(n_patch = patch, p_branch = 0.5, plot = F)
mc <- mcsim(n_patch = patch, n_species = 5,
mean_env = net$df_patch$environment,
carrying_capacity = net$df_patch$n_patch_upstream*10,
distance_matrix = net$distance_matrix,
plot = T)
Users may use the following arguments to custom metacommunity simulations regarding (1) species attributes, (2) competition, (3) patch attributes, and (4) landscape structure.
Arguments: r0
, niche_optim
OR min_optim
and max_optim
,
sd_niche_width
OR min_niche_width
and max_niche_width
,
niche_cost
, p_dispersal
Species attributes are determined based on the maximum reproductive rate
r0
, optimal environmental value niche_optim
(or min_optim
and
max_optim
for random generation of niche_optim
), niche width
sd_niche_width
(or min_niche_width
and max_niche_width
for random
generation of sd_niche_width
) and dispersal probability p_dispersal
(see Model description for details).
For optimal environmental values (niche optimum), the function by
default assigns random values to species as: μi ~
Uniform(minμ, maxμ), where users can set values of
minμ and maxμ using min_optim
and max_optim
arguments (default: min_optim = -1
and max_optim = 1
).
Alternatively, users may specify species niche optimums using the
argument niche_optim
(scalar or vector). If a single value or a vector
of niche_optim
is provided, the function ignores min_optim
and
max_optim
arguments.
Similarly, the function by default assigns random values of
σniche to species as: σniche,i ~
Uniform(minσ, maxσ), where users can set values of
minσ and maxσ using min_niche_width
and
max_niche_width
arguments (default: min_niche_width = 0.1
and
max_niche_width = 1
). If a single value or a vector of
sd_niche_width
is provided, the function ignores min_niche_width
and
max_niche_width
arguments.
The argument niche_cost
determines the cost of having wider niche.
Smaller values imply greater costs of wider niche (i.e., decreased
maximum reproductive rate; default: niche_cost = 1
). To disable (no
cost of wide niche), set niche_cost = Inf
.
For other parameters, users may specify species attributes by giving a
scalar (assume identical among species) or a vector of values whose
length must be one or equal to n_species
. Default values are r0 = 4
,
sd_niche_width = 1
, and p_dispersal = 0.1
.
Arguments: interaction_type
, alpha
OR min_alpha
and max_alpha
The argument interaction_type
determines whether interaction
coefficient alpha
is a constant or random variable. If
interaction_type = "constant"
, then the interaction coefficients
αij (i != j) for any pairs of species will be set as a
constant alpha
(i.e., off-diagonal elements of the interaction
matrix). If interaction_type = "random"
, αij will be drawn
from a uniform distribution as αij ~
Uniform(minα, maxα), where users can specify
minα and maxα using arguments min_alpha
and
max_alpha
. The argument alpha
is ignored under the scenario of
random interaction strength (i.e., interaction_type = "random"
). Note
that the diagonal elements of the interaction matrix (αii)
are always 1.0 regardless of interaction_type
, as alpha
is the
strength of interspecific competition relative to that of intraspecific
competition (see Model description). By default,
interaction_type = "constant"
and alpha = 0
.
Arguments: carrying_capacity
, mean_env
, sd_env
,
spatial_auto_cor
, phi
The arguments carrying_capacity
(default: carrying_capacity = 100
)
and mean_env
(default: mean_env = 0
) determines mean attributes of
habitat patches, which can be a scalar (assume identical among patches)
or a vector (length must be equal to n_patch
).
The arguments sd_env
(default: sd_env = 0.1
), spatial_auto_cor
(default: spatial_auto_cor = FALSE
) and phi
(default: phi = 1
)
determine spatio-temporal dynamics of environmental values. sd_env
determines the magnitude of temporal environmental fluctuations. If
spatial_auto_cor = TRUE
, the function models spatial autocorrelation
of temporal environmental fluctuation based on a multi-variate normal
distribution. The degree of spatial autocorrelation would be determined
by phi
, the parameter describing the strength of distance decay in
spatial autocorrelation (see Model description).
Arguments: xy_coord
OR distance_matrix
(+
weighted_distance_matrix
), landscape_size
, theta
These arguments define landscape structure. By default, the function
produces a square-shaped landscape (landscape_size = 10
on a side) in
which habitat patches are distributed randomly through a Poisson point
process (i.e., x- and y-coordinates of patches are drawn from a uniform
distribution). The parameter θ describes the shape of distance decay in
species dispersal (see Model description) and determines patches’
structural connectivity (default: theta = 1
). Users can define their
landscape by providing either xy_coord
or distance_matrix
(landscape_size
will be ignored if either of these arguments is
provided). If xy_coord
is provided (2-column data frame denoting x-
and y-coordinates of patches, respectively; NULL
by default), the
function calculates the distance between patches based on coordinates.
Alternatively, users may provide distance_matrix
(the object must be
matrix
), which describes the distance between habitat patches. The
argument distance_matrix
overrides xy_coord
.
weighted_distance_matrix
is the supplemental argument to account for
asymmetry in dispersal. For example, users may set an asymmetric
distance matrix (distance between patches differs by direction, e.g.,
upstream to downstream v.s. downstream to upstream). This argument is
enabled only if both weighted (weighted_distance_matrix
) and
unweighted distance matrix (distance_matrix
) are given. If both
arguments are given, weighted_distance_matrix
will be used to
calculate dispersal matrix while distance_matrix
being used to
calculate the spatial autocorrelation in temporal environmental
variation (see Dispersal and Local community dynamics in Model
description).
Arguments: n_warmup
, n_burnin
, n_timestep
The argument n_warmup
is the period during which species introductions
occur (default: n_warmup = 200
). The initial number of individuals
introduced follows a Poisson distribution with a mean of 0.5 and
independent across space and time. This random introduction events occur
multiple times over the n_warmup
period, in which propagule_interval
determines the timestep interval of the random introductions (default:
propagule_interval = ceiling(n_warmup / 10)
).
The argument n_burnin
is the period that will be discarded as
burn-in to remove the influence of initial values (default:
n_burnin = 200
). During the burn-in period, species introductions do
not occur.
The argument n_timestep
is the simulation peiord that is recorded in
the return df_dynamics
(default: n_timestep = 1000
). As a result,
with the default setting, the function simulates 1400 timesteps
(n_warmup
+ n_burnin
+ n_timestep
= 1400) but returns only the
last 1000 timesteps as the resulting metacommunity dynamics. All the
derived statistics (e.g., diversity metrics in df_diversity
and
df_patch
) will be calculated based on the results during n_timestep
.
The metacommunity dynamics are described as a function of local community dynamics and dispersal (Thompson et al. 2020). Specifically, the realized number of individuals Nix(t + 1) (species i at patch x and time t + 1) is given as:
where nix(t) is the expected number of individuals given the local community dynamics at time t, Iix(t) the expected number of immigrants to patch x, and Eix(t) the expected number of emigrants from patch x.
Local community dynamics are simulated based on the Beverton-Holt model:
where rix(t) is the reproductive rate of species i given the
environmental condition at patch x and time t, r0,i the
maximum reproductive rate of species i (argument r0
), Kx
the carrying capacity at patch x (argument carrying_capacity
), and
αij the interaction coefficient with species j (argument
alpha
). Note that αij is the strength of interspecific
competition relative to that of intraspecific competition (intraspecific
competition is greater than interspecific competition if αij
< 1; αii is set to be 1.0). The density-independent
reproductive rate rix(t) is affected by environments and
determined by a Gaussian function:
where μi is the optimal environmental value for species i
(argument niche_optim
), zx(t) the environmental value at
patch x and time t, and σniche the niche width of species i
(argument sd_niche_width
). The cost of having wider niche is expressed
by multiplying c (Chaianunporn and Hovestadt, 2015):
Smaller values of ν (argument niche_cost
) imply greater costs of wider
niche (i.e., decreased maximum reproductive rate). There is no cost of
wider niche if ν approaches infinity. The environmental value
zx(t), which may vary spatially and temporarily, is assumed
to follow a multivariate normal distribution:
μz is the vector of mean environmental conditions of
patches (argument mean_env
) and Ωz is the
variance-covariance matrix. If spatial_auto_cor = FALSE
, the
off-diagonal elements of the matrix are set to be zero while diagonal
elements are σz2 (σz; argument
sd_env
). If spatial_auto_cor = TRUE
, spatial autocorrelation is
considered by describing the off-diagonal elements as:
where Ωxy denotes the temporal covariance of environmental
conditions between patch x and y, which is assumed to decay
exponentially with increasing distance between the patches
dxy (randomly generated or specified by argument
distance_matrix
). The parameter φ (argument phi
) determines distance
decay (larger values lead to sharper declines).
The expected number of emigrants at time t Eix(t) is the
product of dispersal probability Pdispersal (argument
p_dispersal
) and nix(t). The immigration probability at
patch x, ξix, is calculated given the structural connectivity
of patch x, in which the model assumes the exponential decay of
successful immigration with the increasing separation distance between
habitat patches:
where dxy is the separation distance between patch x and y
(randomly generated or specified by argument distance_matrix
or
weighted_distance_matrix
). The parameter θ (argument theta
) dictates
the dispersal distance of species (θ-1 corresponds to the
expected dispersal distance) and is assumed to be constant across
species. The expected number of immigrants is calculated as:
This function converts an adjacency matrix into a distance matrix. Sample script:
net <- brnet(n_patch = 10, p_branch = 0) # linear network
x <- net$adjacency_matrix
# adjacency matrix
print(x)
## patch1 patch2 patch3 patch4 patch5 patch6 patch7 patch8 patch9 patch10
## patch1 0 1 0 0 0 0 0 0 0 0
## patch2 1 0 1 0 0 0 0 0 0 0
## patch3 0 1 0 1 0 0 0 0 0 0
## patch4 0 0 1 0 1 0 0 0 0 0
## patch5 0 0 0 1 0 1 0 0 0 0
## patch6 0 0 0 0 1 0 1 0 0 0
## patch7 0 0 0 0 0 1 0 1 0 0
## patch8 0 0 0 0 0 0 1 0 1 0
## patch9 0 0 0 0 0 0 0 1 0 1
## patch10 0 0 0 0 0 0 0 0 1 0
# covert an adjacency matrix into a distance matrix
adjtodist(x)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 0 1 2 3 4 5 6 7 8 9
## [2,] 1 0 1 2 3 4 5 6 7 8
## [3,] 2 1 0 1 2 3 4 5 6 7
## [4,] 3 2 1 0 1 2 3 4 5 6
## [5,] 4 3 2 1 0 1 2 3 4 5
## [6,] 5 4 3 2 1 0 1 2 3 4
## [7,] 6 5 4 3 2 1 0 1 2 3
## [8,] 7 6 5 4 3 2 1 0 1 2
## [9,] 8 7 6 5 4 3 2 1 0 1
## [10,] 9 8 7 6 5 4 3 2 1 0
- Chaianunporn T and Hovestadt T. (2015) Evolutionary responses to climate change in parasitic systems. Global Change Biology 21: 2905-2916.
- Csardi G, Nepusz T: The igraph software package for complex network research, InterJournal, Complex Systems 1695. 2006. http://igraph.org
- Jacolien van Rij (2020). plotfunctions: Various Functions to Facilitate Visualization of Data and Analysis. R package version 1.4. https://CRAN.R-project.org/package=plotfunctions
- Thompson, P.L., Guzman, L.M., De Meester, L., Horváth, Z., Ptacnik, R., Vanschoenwinkel, B., Viana, D.S. and Chase, J.M. (2020), A process‐based metacommunity framework linking local and regional scale community ecology. Ecol Lett, 23: 1314-1329. doi:10.1111/ele.13568