Regardless of whether the stage classes of a matrix population model (MPM) are based on age, size, and/or ontogeny, it’s possible to obtain age-specific schedules of survivorship (lx) and reproduction (mx) using ‘age-from-stage’ methods, as described by Caswell (2001).
We’ll start by loading a few packages and a dataset that we’ll be using throughout this vignette.
library(Rage) # load Rage
data(mpm1) # load data object 'mpm1'
# display the contents
mpm1 #> $matU
#> seed small medium large dormant
#> seed 0.10 0.00 0.00 0.00 0.00
#> small 0.05 0.12 0.10 0.00 0.00
#> medium 0.00 0.35 0.12 0.23 0.12
#> large 0.00 0.03 0.28 0.52 0.10
#> dormant 0.00 0.00 0.16 0.11 0.17
#>
#> $matF
#> seed small medium large dormant
#> seed 0 0 17.9 45.6 0
#> small 0 0 0.0 0.0 0
#> medium 0 0 0.0 0.0 0
#> large 0 0 0.0 0.0 0
#> dormant 0 0 0.0 0.0 0
This MPM has 5 stage class, and it’s apparent from the dimnames
attribute that the stages are not based solely on age. Nonetheless, we can estimate age-schedules of survivorship and reproduction using the functions mpm_to_lx()
and mpm_to_mx()
from Rage
.
dimnames(mpm1$matU)
#> [[1]]
#> [1] "seed" "small" "medium" "large" "dormant"
#>
#> [[2]]
#> [1] "seed" "small" "medium" "large" "dormant"
# extract U and F matrices
<- mpm1$matU
mat_U <- mpm1$matF
mat_F
# calculate lx
<- mpm_to_lx(mat_U, start = 1, xmax = 30)
lx
# calculate mx
<- mpm_to_mx(mat_U, mat_F, start = 1, xmax = 30) mx
In addition to the relevant matrix components, the mpm_to_*
functions require two extra arguments. The first, start
, is an integer indicating which stage reflects the ‘start of life’. Usually this will be 1
, but sometimes we might want to skip over stages that are propagule (i.e. seed) or dormant. The MPM we selected begins with a seed stage, so we may want to start from the second stage, corresponding to start = 2
. The second argument, N
is the number of time steps to calculate over.
# calculate lx
<- mpm_to_lx(mat_U, start = 1, xmax = 30)
lx
# calculate mx
<- mpm_to_mx(mat_U, mat_F, start = 1, xmax = 30) mx
Let’s take a look at the trajectories.
plot(lx, ylim = c(0, 1), type = "l", xlab = "Age")
plot(mx, type = "l", xlab = "Age")
Now we’ll extend the basic approach above to many models. Specifically, we’ll examine trajectories of survivorship for all of the tree species in Compadre
. Compadre
is a database of matrix population models. You can read more about it here, and the associated R package here. The Rcompadre
package contains a subset of the database that we can use to demonstrate computations on many models simultaneously.
First, we’ll subset Compadre
to our group of interest (OrganismType == "Tree"
). We’ll also remove matrices with missing values, and limit our selection to matrices with a periodicity (i.e. transition interval) of 1 year.
library(Rcompadre)
data(Compadre)
# In older versions of Com(p)adre the ProjectionInterval column was called AnnualPeriodicity.
if ("AnnualPeriodicity" %in% names(Compadre)) {
$ProjectionInterval <- Compadre$AnnualPeriodicity
Compadre
}
<- cdb_flag(Compadre, "check_NA_U")
comp_flag
<- subset(comp_flag, OrganismType == "Tree" &
comp_use == FALSE &
check_NA_U == 1) ProjectionInterval
Let’s take a look at the species/populations that made the cut.
CompadreData(comp_use)[, c("SpeciesAccepted", "MatrixPopulation", "MatrixTreatment")]
#> # A tibble: 7 x 3
#> SpeciesAccepted MatrixPopulation MatrixTreatment
#> <chr> <chr> <chr>
#> 1 Phyllanthus indofis… Biligiri Rangaswamy Temple Wil… Fruit harvesting and no …
#> 2 Phyllanthus indofis… Biligiri Rangaswamy Temple Wil… Fruit harvesting and Mis…
#> 3 Castanea dentata Leelanau Unmanipulated
#> 4 Phyllanthus emblica Biligiri Rangaswamy Temple Wil… Time since last fire: 3 …
#> 5 Phyllanthus indofis… Biligiri Rangaswamy Temple Wil… Unmanipulated
#> 6 Manilkara zapota Central Veracruz state Unmanipulated
#> 7 Rhododendron pontic… Ockham Common Nature Reserve Unmanipulated
Notice that there are 3 matrices for the species Phyllanthus indofischeri, reflecting different treatment groups. Let’s collapse these replicates down to a single matrix per species, by averaging the relevant MPMs using cdb_collapse()
. We’ll also use the function cdb_id_stages()
, to make sure we’re only collapsing matrices that have the same stage class definitions.
# add column ID-ing matrices with same MatrixClassAuthor vector
$stage_id <- cdb_id_stages(comp_use)
comp_use
# collapse database to single matrix per species * MatrixClassAuthor
<- cdb_collapse(comp_use, "stage_id")
comp_collapse
# check species/populations again
CompadreData(comp_collapse)[, c("SpeciesAccepted", "MatrixPopulation", "MatrixTreatment")]
#> # A tibble: 5 x 3
#> SpeciesAccepted MatrixPopulation MatrixTreatment
#> <chr> <chr> <chr>
#> 1 Phyllanthus indof… Biligiri Rangaswamy Temp… Fruit harvesting and no cover; F…
#> 2 Castanea dentata Leelanau Unmanipulated
#> 3 Phyllanthus embli… Biligiri Rangaswamy Temp… Time since last fire: 3 years
#> 4 Manilkara zapota Central Veracruz state Unmanipulated
#> 5 Rhododendron pont… Ockham Common Nature Res… Unmanipulated
Next, let’s look at the organized stage classes for each MPM. If any of our MPMs include propagule or dormant stage classes, we may want to account for them when calculating lx.
MatrixClassOrganized(comp_collapse)
#> [[1]]
#> [1] "prop" "active" "active" "active" "active" "active" "active"
#>
#> [[2]]
#> [1] "active" "active" "active" "active" "active" "active" "active" "active"
#>
#> [[3]]
#> [1] "active" "active" "active" "active" "active" "active"
#>
#> [[4]]
#> [1] "active" "active" "active" "active" "active" "active" "active" "active"
#> [9] "active"
#>
#> [[5]]
#> [1] "active" "active" "active" "active"
Indeed, 1 MPM incudes a propagule stage. So let’s use the function mpm_first_active()
to determine the first ‘active’ stage class for each MPM, which we’ll use to define the start of life.
$start_life <- mpm_first_active(comp_collapse) comp_collapse
Finally, we’ll use lapply()
to apply the function mpm_to_lx
to each row of comp_collapse
. By default, lapply()
will return a vector for each row, and the length of which is xmax
. We can convert the output to an matrix, with columns representing each row from comp_collapse
using do.call
. After that, we’ll use the function matplot()
to plot age-trajectories of survivorship for each species.
<- lapply(seq_len(nrow(comp_collapse)),
lx_list function(x, comp_collapse) {
<- matU(comp_collapse$mat[[x]])
U
rownames(U) <- colnames(U) # ensure row and col names are present
mpm_to_lx(
matU = U,
start = comp_collapse$start_life[x],
xmax = 40
)
},comp_collapse = comp_collapse
)
<- do.call(cbind, lx_list)
lx_array #> Warning in (function (..., deparse.level = 1) : number of rows of result is not
#> a multiple of vector length (arg 3)
matplot(lx_array,
type = "l", lty = 1, log = "y", ylim = c(0.0001, 1),
lwd = 1.5, xlab = "Age (years)", ylab = "lx"
)
Caswell, H. (2001). Matrix Population Models: Construction, Analysis, and Interpretation. 2nd edition. Sinauer Associates, Sunderland, MA. ISBN-10: 0878930965