This document was built in Markdown in R 4.0.2, and covers package lefko3
version 2.4.1.
Lathyrus vernus (family Fabaceae) is a long-lived forest herb, native to Europe and large parts of northern Asia. Individuals increase slowly in size and usually flower only after 10-15 years of vegetative growth. Flowering individuals have an average conditional life span of 44.3 years (Ehrlén and Lehtilä 2002). Lathyrus vernus lacks organs for vegetative spread and individuals are well delimited (Ehrlén 2002). One or several erect shoots of up to 40 cm height emerge from a subterranean rhizome in March-April. Flowering occurs about four weeks after shoot emergence. Shoot growth is determinate, and the number of flowers is determined in the previous year (Ehrlén and Van Groenendael 2001). Individuals may not produce above-ground structures every year but can remain dormant in one season. Lathyrus vernus is self-compatible but requires visits from bumble-bees to produce seeds. Individuals produce few, large seeds and establishment from seeds is relatively frequent (Ehrlén and Eriksson 1996,). The pre-dispersal seed predator Bruchus atomarius often consumes a large fraction of developing seeds, and roe deer (Capreolus capreolus) sometimes consume the shoots (Ehrlén and Münzbergová 2009).
Data for this study were collected from six permanent plots in a population of L. vernus located in a deciduous forest in the Tullgarn area, SE Sweden (58.9496 N, 17.6097 E), during 1988–1991 (Ehrlén 1995). The six plots were relatively similar with regard to soil type, elevation, slope, and canopy cover. Within each plot, all individuals were marked with numbered tags that remained over the study period, and their locations were carefully mapped. New individuals were included in the study in each year. Individuals were recorded at least three times every growth season. At the time of shoot emergence, we recorded whether individuals were alive and produced above-ground shoots, and if shoots had been grazed. During flowering, we recorded flower number and the height and diameter of all shoots. At fruit maturation, we counted the number of intact and damaged seeds. To derive a measure of above-ground size for each individual, we calculated the volume of each shoot as \(\pi\) × (\(\frac{1}{2}\)diameter)2 × height, and summed the volumes of all shoots. This measure is closely correlated with the dry mass of aboveground tissues (r2 = 0.924, P < 0.001, n = 50, log-transformed values; Ehrlen 1995). Size of individuals that had been grazed was estimated based on measures of shoot diameter in grazed shoots, and the relationship between shoot diameter and shoot height in non-grazed individuals. Only individuals with an aboveground volume of more than 230 mm3 flowered and produced fruits during this study. Individuals that lacked aboveground structures in one season but reappeared in the following year were considered dormant. Individuals that lacked aboveground structures in two subsequent seasons were considered dead from the year in which they first lacked aboveground structures. Probabilities of seeds surviving to the next year, and of being present as seedlings or seeds in the soil seed bank, were derived from separate yearly sowing experiments in separate plots adjacent to each subplot (Ehrlén and Eriksson 1996).
We will analyze these data in three different ways to illustrate the ways in which package lefko3
can be used:
through the estimation of raw MPMs, with the intention of producing matrices similar to those published in Ehrlén (2000);
through the estimation of function-based MPMs using a stage classification different from Ehrlén (2000), developed using the natural logarithm of the size measure used in that study; and
through the construction of a complex integral projection model.
Here we will estimate matrices similar to and based on the dataset used in Ehrlén (2000). These matrices will not be the same, as the dataset included in this package includes more individuals for those years as well as an extra year of data. It also includes differences in classification due to different assumptions regarding transitions to and from vegetative dormancy, which is an unobservable life history stage. However, the matrices will be very similar.
The dataset that we have provided is organized in horizontal format, meaning that rows correspond to unique individuals and columns correspond to individual condition in particular years. Looking at the original Excel spreadsheet, you will note a repeating pattern in the names of the columns. Package lefko3
includes functions to handle data in horizontal format based on these patterns, as well as functions to handle vertically formatted data (i.e. data for individuals is broken up across rows, where each row is a unique combination of individual and year in time t).
This dataset includes information on 1119 individuals, so there are 1119 rows with data (not counting the header). There are 38 columns. The first two columns are variables giving identifying information about each individual, with each individual’s data entirely restricted to one row. This is followed by four sets of nine columns, each named VolumeXX
, lnVolXX
, FCODEXX
, FlowXX
, IntactseedXX
, Dead19XX
, DormantXX
, Missing19XX
, and SeedlingXX
, with the XX
in each case corresponding to the year of observation and with years organized consecutively. Thus, columns 3-11 refer to year 1988, columns 12-20 refer to year 1989, etc. To properly conduct this exercise, we need to know the exact number of years used, which is 4 years here (includes all years from and including 1988 to 1991), we need the columns to be repeated in the same order in each year, and we need the years in consecutive order with no extra columns between them.
First, we load the dataset, and note its dimensions.
After looking over the dataset, we need to create a stageframe describing the life history of the species and linking it to the data. A stageframe is a data frame that describes all stages in the life history of the organism, in a way usable by the functions in this package and using stage names and classifications that match the data. It needs to include complete descriptions of all stages that occur in the dataset, with each stage defined uniquely. Since this object can be used for automated classification of individuals, all sizes, reproductive states, and other characteristics defining each stage in the dataset need to be accounted for explicitly. This can be difficult if a few data points exist outside the range of sizes specified in the stageframe, so great care must be taken to include all size values and values of other descriptor variables occurring within the dataset. The final description of each stage occurring in the dataset may not overlap completely with any other stage also found in the dataset, although partial overlap is expected.
Here, we create a stageframe named lathframe
based on the classification used in Ehrlén (2000). We build this by creating vectors of the values describing each stage, always in the same order. Of particular note are the vectors input as sizes
and binhalfwidth
in the sf_create
function. In the case where sizes are binned, the values input in the former are the central values of each bin, while the latter represents one-half of the width of the bin. If size values are not to be binned, then narrow binwidths can be used. For example, in this dataset, vegetatively dormant individuals necessarily have a size of 0, and so we can set the halfbinwidth
for this stage to 0.5.
sizevector <- c(0, 100, 13, 127, 3730, 3800, 0)
stagevector <- c("Sd", "Sdl", "VSm", "Sm", "VLa", "Flo", "Dorm")
repvector <- c(0, 0, 0, 0, 0, 1, 0)
obsvector <- c(0, 1, 1, 1, 1, 1, 0)
matvector <- c(0, 0, 1, 1, 1, 1, 1)
immvector <- c(1, 1, 0, 0, 0, 0, 0)
propvector <- c(1, 0, 0, 0, 0, 0, 0)
indataset <- c(0, 1, 1, 1, 1, 1, 1)
binvec <- c(0, 100, 11, 103, 3500, 3800, 0.5)
lathframe <- sf_create(sizes = sizevector, stagenames = stagevector, repstatus = repvector,
obsstatus = obsvector, matstatus = matvector, immstatus = immvector,
indataset = indataset, binhalfwidth = binvec, propstatus = propvector)
To be useful to others reading your work, or to yourself in the future, it helps to add text descriptions of the stages. Here, we also add some descriptions to this stageframe as comments. Type lathframe
after running the following to see the structure.
lathframe$comments <- c("Dormant seed", "Seedling", "Very small vegetative adult",
"Small vegetative adult", "Very large vegetative adult",
"Flowering adult", "Vegetatively dormant adult")
A further important point has to do with the meaning of 0 sizes. In most cases, a size of 0 will mean that the individual is alive but unobservable. However, a size of 0 may have different meanings in other cases, such as when the size metric used is a logarithm and so values of 0 and lower are possible in observable individuals in the dataset. The dataset should be explored carefully for these situations, particularly in the case of the creation of a function-based matrix, such as an IPM, in order to make sure that the stageframe accurately describes and matches the values actually occurring in the dataset.
Once the stageframe is created, we can reorganize the dataset into vertical format. Here, vertical format is a way of organizing demogaphic data in which each row corresponds to the state of a single individual in two (if ahistorical) or three (if historical) consecutive time steps. We use the verticalize3()
function to handle this and create a historical vertical dataset, as below.
lathvert <- verticalize3(lathyrus, noyears = 4, firstyear = 1988, patchidcol = "SUBPLOT",
individcol = "GENET", blocksize = 9, juvcol = "Seedling1988",
size1col = "Volume88", repstr1col = "FCODE88",
fec1col = "Intactseed88", dead1col = "Dead1988",
nonobs1col = "Dormant1988", stageassign = lathframe,
stagesize = "sizea", censorcol = "Missing1988",
censorkeep = NA, censor = TRUE)
summary(lathvert)
#> rowid popid patchid individ year2 firstseen lastseen obsage obslifespan
#> Min. : 1.0 :2527 1:673 Length:2527 Min. :1988 Min. : 0 Min. : 0 Min. :0.0000 Min. :0.000
#> 1st Qu.: 237.0 2:202 Class :character 1st Qu.:1988 1st Qu.:1988 1st Qu.:1991 1st Qu.:0.0000 1st Qu.:2.000
#> Median : 522.0 3:556 Mode :character Median :1989 Median :1988 Median :1991 Median :1.0000 Median :3.000
#> Mean : 537.3 4:469 Mean :1989 Mean :1979 Mean :1981 Mean :0.8219 Mean :2.437
#> 3rd Qu.: 820.5 5:308 3rd Qu.:1990 3rd Qu.:1988 3rd Qu.:1991 3rd Qu.:1.0000 3rd Qu.:3.000
#> Max. :1118.0 6:319 Max. :1990 Max. :1990 Max. :1991 Max. :2.0000 Max. :3.000
#>
#> sizea1 repstra1 feca1 fec1added juvgiven1 obsstatus1 repstatus1
#> Min. : 0.0 Min. :0.0000 Min. : 0.000 Min. : 0.0000 Min. :0.00000 Min. :0.0000 Min. :0.0000
#> 1st Qu.: 0.0 1st Qu.:0.0000 1st Qu.: 0.000 1st Qu.: 0.0000 1st Qu.:0.00000 1st Qu.:0.0000 1st Qu.:0.0000
#> Median : 9.0 Median :0.0000 Median : 0.000 Median : 0.0000 Median :0.00000 Median :1.0000 Median :0.0000
#> Mean : 387.3 Mean :0.2161 Mean : 2.145 Mean : 0.9889 Mean :0.06292 Mean :0.5548 Mean :0.1805
#> 3rd Qu.: 624.6 3rd Qu.:0.0000 3rd Qu.: 0.000 3rd Qu.: 0.0000 3rd Qu.:0.00000 3rd Qu.:1.0000 3rd Qu.:0.0000
#> Max. :7032.0 Max. :1.0000 Max. :66.000 Max. :66.0000 Max. :1.00000 Max. :1.0000 Max. :1.0000
#> NA's :417 NA's :1362
#> fecstatus1 matstatus1 alive1 stage1 stage1index sizea2 repstra2
#> Min. :0.00000 Min. :0.0000 Min. :0.0000 Length:2527 Min. :0.000 Min. : 0.0 Min. :0.0000
#> 1st Qu.:0.00000 1st Qu.:0.0000 1st Qu.:0.0000 Class :character 1st Qu.:0.000 1st Qu.: 12.6 1st Qu.:0.0000
#> Median :0.00000 Median :1.0000 Median :1.0000 Mode :character Median :3.000 Median : 105.6 Median :0.0000
#> Mean :0.08983 Mean :0.5204 Mean :0.5833 Mean :2.718 Mean : 480.8 Mean :0.2508
#> 3rd Qu.:0.00000 3rd Qu.:1.0000 3rd Qu.:1.0000 3rd Qu.:5.000 3rd Qu.: 732.5 3rd Qu.:1.0000
#> Max. :1.00000 Max. :1.0000 Max. :1.0000 Max. :7.000 Max. :7032.0 Max. :1.0000
#> NA's :139
#> feca2 fec2added juvgiven2 obsstatus2 repstatus2 fecstatus2 matstatus2 alive2
#> Min. : 0.000 Min. : 0.00 Min. :0.0000 Min. :0.0000 Min. :0.000 Min. :0.0000 Min. :0.0000 Min. :1
#> 1st Qu.: 0.000 1st Qu.: 0.00 1st Qu.:0.0000 1st Qu.:1.0000 1st Qu.:0.000 1st Qu.:0.0000 1st Qu.:1.0000 1st Qu.:1
#> Median : 0.000 Median : 0.00 Median :0.0000 Median :1.0000 Median :0.000 Median :0.0000 Median :1.0000 Median :1
#> Mean : 4.802 Mean : 1.14 Mean :0.1112 Mean :0.9454 Mean :0.237 Mean :0.1053 Mean :0.8888 Mean :1
#> 3rd Qu.: 6.000 3rd Qu.: 0.00 3rd Qu.:0.0000 3rd Qu.:1.0000 3rd Qu.:0.000 3rd Qu.:0.0000 3rd Qu.:1.0000 3rd Qu.:1
#> Max. :66.000 Max. :66.00 Max. :1.0000 Max. :1.0000 Max. :1.000 Max. :1.0000 Max. :1.0000 Max. :1
#> NA's :1927
#> stage2 stage2index sizea3 repstra3 feca3 fec3added juvgiven3 obsstatus3
#> Length:2527 Min. :2.000 Min. : 0.0 Min. :0.0000 Min. : 0.000 Min. : 0.00 Min. :0 Min. :0.0000
#> Class :character 1st Qu.:3.000 1st Qu.: 10.0 1st Qu.:0.0000 1st Qu.: 0.000 1st Qu.: 0.00 1st Qu.:0 1st Qu.:1.0000
#> Mode :character Median :4.000 Median : 72.0 Median :0.0000 Median : 2.000 Median : 0.00 Median :0 Median :1.0000
#> Mean :4.424 Mean : 389.7 Mean :0.2614 Mean : 5.969 Mean : 1.29 Mean :0 Mean :0.8346
#> 3rd Qu.:6.000 3rd Qu.: 543.4 3rd Qu.:1.0000 3rd Qu.: 9.000 3rd Qu.: 0.00 3rd Qu.:0 3rd Qu.:1.0000
#> Max. :7.000 Max. :6645.8 Max. :1.0000 Max. :66.000 Max. :66.00 Max. :0 Max. :1.0000
#> NA's :419 NA's :1981
#> repstatus3 fecstatus3 matstatus3 alive3 stage3 stage3index
#> Min. :0.000 Min. :0.0000 Min. :1 Min. :0.0000 Length:2527 Min. :0.00
#> 1st Qu.:0.000 1st Qu.:0.0000 1st Qu.:1 1st Qu.:1.0000 Class :character 1st Qu.:3.00
#> Median :0.000 Median :0.0000 Median :1 Median :1.0000 Mode :character Median :4.00
#> Mean :0.218 Mean :0.1116 Mean :1 Mean :0.9224 Mean :4.32
#> 3rd Qu.:0.000 3rd Qu.:0.0000 3rd Qu.:1 3rd Qu.:1.0000 3rd Qu.:6.00
#> Max. :1.000 Max. :1.0000 Max. :1 Max. :1.0000 Max. :7.00
#>
dim(lathvert)
#> [1] 2527 45
It generally pays to explore a dataset thoroughly prior to full analysis, and summaries can certainly help to do that. Looking at the output above, for example, reveals that the verticalize3()
function has automatically subset the data to only those instances in which the individual is alive in time t (please take a look at the variable alive2
). Noting the mean value for alive3
suggests very high survival, and the minimum values for all size variables are 0, even in the case of sizea2
, suggesting that unbserveable stages are certainly occurring within the dataset (these are instances of vegetative dormancy, which is treated as a separate life history stage in this example).
Further subset summaries may help understand these data even better. For example, after subsetting to only cases in which individuals are vegetatively dormant in time t, we can see that this particular stage is actually designated by a size of 0. We can also see, looking at the stage designations and at the dimensions of the aforementioned subset, that vegetative dormancy is reasonably plentiful in this dataset.
summary(lathvert[which(lathvert$stage2 == "Dorm"),])
#> rowid popid patchid individ year2 firstseen lastseen obsage obslifespan
#> Min. : 1.0 :138 1:29 Length:138 Min. :1989 Min. : 0 Min. : 0 Min. :0.000 Min. :0.000
#> 1st Qu.: 303.2 2:14 Class :character 1st Qu.:1989 1st Qu.:1988 1st Qu.:1991 1st Qu.:1.000 1st Qu.:2.000
#> Median : 493.5 3:42 Mode :character Median :1989 Median :1988 Median :1991 Median :1.000 Median :3.000
#> Mean : 526.7 4:13 Mean :1989 Mean :1815 Mean :1818 Mean :1.239 Mean :2.551
#> 3rd Qu.: 861.8 5:31 3rd Qu.:1990 3rd Qu.:1988 3rd Qu.:1991 3rd Qu.:2.000 3rd Qu.:3.000
#> Max. :1079.0 6: 9 Max. :1990 Max. :1989 Max. :1991 Max. :2.000 Max. :3.000
#>
#> sizea1 repstra1 feca1 fec1added juvgiven1 obsstatus1 repstatus1
#> Min. : 0.00 Min. :0.0000 Min. : 0.000 Min. : 0.000 Min. :0.0000 Min. :0.0000 Min. :0.0000
#> 1st Qu.: 87.45 1st Qu.:0.0000 1st Qu.: 0.000 1st Qu.: 0.000 1st Qu.:0.0000 1st Qu.:1.0000 1st Qu.:0.0000
#> Median : 477.20 Median :0.0000 Median : 0.000 Median : 0.000 Median :0.0000 Median :1.0000 Median :0.0000
#> Mean : 595.48 Mean :0.3178 Mean : 4.561 Mean : 1.355 Mean :0.0942 Mean :0.9348 Mean :0.2971
#> 3rd Qu.: 732.50 3rd Qu.:1.0000 3rd Qu.: 7.000 3rd Qu.: 0.000 3rd Qu.:0.0000 3rd Qu.:1.0000 3rd Qu.:1.0000
#> Max. :2941.00 Max. :1.0000 Max. :30.000 Max. :30.000 Max. :1.0000 Max. :1.0000 Max. :1.0000
#> NA's :9 NA's :97
#> fecstatus1 matstatus1 alive1 stage1 stage1index sizea2 repstra2 feca2
#> Min. :0.0000 Min. :0.0000 Min. :1 Length:138 Min. :2.000 Min. :0 Min. : NA Min. : NA
#> 1st Qu.:0.0000 1st Qu.:1.0000 1st Qu.:1 Class :character 1st Qu.:4.000 1st Qu.:0 1st Qu.: NA 1st Qu.: NA
#> Median :0.0000 Median :1.0000 Median :1 Mode :character Median :5.000 Median :0 Median : NA Median : NA
#> Mean :0.1232 Mean :0.9058 Mean :1 Mean :4.833 Mean :0 Mean :NaN Mean :NaN
#> 3rd Qu.:0.0000 3rd Qu.:1.0000 3rd Qu.:1 3rd Qu.:6.000 3rd Qu.:0 3rd Qu.: NA 3rd Qu.: NA
#> Max. :1.0000 Max. :1.0000 Max. :1 Max. :7.000 Max. :0 Max. : NA Max. : NA
#> NA's :138 NA's :138
#> fec2added juvgiven2 obsstatus2 repstatus2 fecstatus2 matstatus2 alive2 stage2 stage2index
#> Min. :0 Min. :0 Min. :0 Min. :0 Min. :0 Min. :1 Min. :1 Length:138 Min. :7
#> 1st Qu.:0 1st Qu.:0 1st Qu.:0 1st Qu.:0 1st Qu.:0 1st Qu.:1 1st Qu.:1 Class :character 1st Qu.:7
#> Median :0 Median :0 Median :0 Median :0 Median :0 Median :1 Median :1 Mode :character Median :7
#> Mean :0 Mean :0 Mean :0 Mean :0 Mean :0 Mean :1 Mean :1 Mean :7
#> 3rd Qu.:0 3rd Qu.:0 3rd Qu.:0 3rd Qu.:0 3rd Qu.:0 3rd Qu.:1 3rd Qu.:1 3rd Qu.:7
#> Max. :0 Max. :0 Max. :0 Max. :0 Max. :0 Max. :1 Max. :1 Max. :7
#>
#> sizea3 repstra3 feca3 fec3added juvgiven3 obsstatus3 repstatus3 fecstatus3
#> Min. : 0.00 Min. :0.0000 Min. : 0 Min. : 0.0000 Min. :0 Min. :0.0000 Min. :0.0000 Min. :0.00000
#> 1st Qu.: 16.02 1st Qu.:0.0000 1st Qu.: 0 1st Qu.: 0.0000 1st Qu.:0 1st Qu.:1.0000 1st Qu.:0.0000 1st Qu.:0.00000
#> Median : 88.45 Median :0.0000 Median : 0 Median : 0.0000 Median :0 Median :1.0000 Median :0.0000 Median :0.00000
#> Mean : 242.33 Mean :0.1111 Mean : 3 Mean : 0.2826 Mean :0 Mean :0.8478 Mean :0.0942 Mean :0.02899
#> 3rd Qu.: 300.90 3rd Qu.:0.0000 3rd Qu.: 4 3rd Qu.: 0.0000 3rd Qu.:0 3rd Qu.:1.0000 3rd Qu.:0.0000 3rd Qu.:0.00000
#> Max. :2637.60 Max. :1.0000 Max. :17 Max. :17.0000 Max. :0 Max. :1.0000 Max. :1.0000 Max. :1.00000
#> NA's :21 NA's :125
#> matstatus3 alive3 stage3 stage3index
#> Min. :1 Min. :1 Length:138 Min. :3.000
#> 1st Qu.:1 1st Qu.:1 Class :character 1st Qu.:4.000
#> Median :1 Median :1 Mode :character Median :4.000
#> Mean :1 Mean :1 Mean :4.746
#> 3rd Qu.:1 3rd Qu.:1 3rd Qu.:5.000
#> Max. :1 Max. :1 Max. :7.000
#>
dim(lathvert[which(lathvert$stage2 == "Dorm"),])
#> [1] 138 45
The fact that vegetatively dormant individuals have been assigned 0 for size does not require us to exercise any extra steps, because the construction of raw matrices depends on the stage designations rather than on the size classifications. In this case, the verticalize3()
function has made these assignments, and this can be observed in the above summary output by looking at the stabe2index
column, which shows all individuals that are alive and have a size of 0 in time t to be in the 7th stage. Typing lathframe
and enter at the prompt can show us the stageframe being used, at which point we can check to make sure that the 7th stage is really vegetative dormancy. However, if we wished to build function-based matrices, as in Analyses 2 and 3, then we would need to change any NAs to 0 to proceed as NAs within size variables are not allowed in vital rate model estimation.
Voilá! Now we will move on to creating a few extra objects that will help us estimate full population projection matrices.
For our next step, we need to create a reproductive matrix. This matrix shows which stages are reproductive, which stages they lead to the production of, and at what level reproduction occurs. This matrix is mostly composed of 0s, but fecundity is noted as non-zero entries equal to a scalar multiplier to the full fecundity estimated by lefko3
. This matrix has rows and columns equal to the number of stages described in the stageframe for this dataset, and the rows and columns refer to these stages in the same order as in the stageframe. In many ways, this matrix looks like a nearly empty population matrix, but notes the per-individual mean modifiers on fecundity for each stage that actually reproduces.
First, we create a 0 matrix with dimensions equal to the number of rows in lathframe
. Then we modify elements corresponding to fecundity by the expected mean seed dormancy probability (row 1), and by the germination rate (row 2). Since only stage 6 (flowering adult, or Flo) is reproductive, and since reproduction leads to the production of individuals in stage 1 (dormant seed, or Sd) and stage 2 (seedlings, or Sdl), we will alter matrix elements [1, 6] and [2, 6]. After entering the lines of code in the next block, type lathrepm
at the prompt to see the structure of this object.
Next we will provide some given transitions via an overwrite table. In this case, we are providing the seed dormancy probability and germination rate, which in this case are provided as transitions from the dormant seed stage to another year of seed dormancy or a germinated seedling, respectively. Let’s start with the ahistorical case. As before, type lathover2
at the prompt after entering the lines of code below to see the structure of the object that you have creaed.
lathover2 <- overwrite(stage3 = c("Sd", "Sdl"), stage2 = c("Sd", "Sd"),
givenrate = c(0.345, 0.054))
And now the historical case. Here we need to show the stages in time step t-1 for this to work properly. Note the use of the "rep"
designation for Stage1
- this is shorthand telling R to use all reproductive stages for the time interval. Here, there is only one reproductive stage, but in other cases, such as in an IPM, this shorthand notation can represent many stages in a single statement.
lathover3 <- overwrite(stage3 = c("Sd", "Sd", "Sdl"), stage2 = c("Sd", "Sd", "Sd"),
stage1 = c("Sd", "rep", "rep"), givenrate = c(0.345, 0.345, 0.054))
These two overwrite tables show us that we have survival-transition probabilities (convtype = 1
), that the given transitions originate from the dormant seed stage (Sd) in time t (and reproductive stages in time t-1 in the historical case), and the specific values to be used in overwriting: 0.345 and 0.054. If we wished, we could have used the values of transitions to be estimated within this matrix as proxies for these values, in which case the eststageX
columns would have entries and the givenrate
column would be blank (see the Cypripedium candidum vignette for examples).
Now we are read to create some MPMs!
Now let’s create some raw Lefkovitch MPMs starting with the ahistorical case, based on Ehrlén (2000). That study shows a mean matrix covering years 1989 and 1990 as time t. We will utilize the entire dataset instead, covering 1988 to 1991, as follows.
ehrlen2 <- rlefko2(data = lathvert, stageframe = lathframe, year = "all",
stages = c("stage3", "stage2"), repmatrix = lathrepm,
overwrite = lathover2, yearcol = "year2",
indivcol = "individ")
ehrlen2
#> $A
#> $A$`1`
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 0.345 0.00000000 0.00000 0.00000000 0.0000000 1.02941848 0
#> [2,] 0.054 0.00000000 0.00000 0.00000000 0.0000000 0.16112637 0
#> [3,] 0.000 0.61855670 0.78125 0.07692308 0.0000000 0.00000000 0
#> [4,] 0.000 0.03092784 0.12500 0.67307692 0.2044199 0.07024793 0
#> [5,] 0.000 0.00000000 0.00000 0.03205128 0.3535912 0.21487603 0
#> [6,] 0.000 0.00000000 0.00000 0.03846154 0.2928177 0.61983471 0
#> [7,] 0.000 0.10309278 0.03125 0.12179487 0.1160221 0.09090909 0
#>
#> $A$`2`
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 0.345 0.00000000 0.00000000 0.00000000 0.00000000 2.83876712 0.00000000
#> [2,] 0.054 0.00000000 0.00000000 0.00000000 0.00000000 0.44432877 0.00000000
#> [3,] 0.000 0.70085470 0.78461538 0.17592593 0.02205882 0.00000000 0.15068493
#> [4,] 0.000 0.02564103 0.06923077 0.61574074 0.32352941 0.18721461 0.50684932
#> [5,] 0.000 0.00000000 0.00000000 0.02314815 0.29411765 0.28767123 0.09589041
#> [6,] 0.000 0.00000000 0.00000000 0.02314815 0.21323529 0.42922374 0.12328767
#> [7,] 0.000 0.02564103 0.01538462 0.08333333 0.10294118 0.08675799 0.12328767
#>
#> $A$`3`
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 0.345 0.00000000 0.000000000 0.00000000 0.00000000 0.86750000 0.00000000
#> [2,] 0.054 0.00000000 0.000000000 0.00000000 0.00000000 0.13578261 0.00000000
#> [3,] 0.000 0.67164179 0.606299213 0.03533569 0.00000000 0.00000000 0.09230769
#> [4,] 0.000 0.00000000 0.173228346 0.45229682 0.05785124 0.04347826 0.29230769
#> [5,] 0.000 0.00000000 0.003937008 0.17667845 0.28925620 0.19565217 0.36923077
#> [6,] 0.000 0.00000000 0.000000000 0.15901060 0.52892562 0.66666667 0.06153846
#> [7,] 0.000 0.05970149 0.039370079 0.12367491 0.09917355 0.07971014 0.18461538
#>
#>
#> $U
#> $U$`1`
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 0.345 0.00000000 0.00000 0.00000000 0.0000000 0.00000000 0
#> [2,] 0.054 0.00000000 0.00000 0.00000000 0.0000000 0.00000000 0
#> [3,] 0.000 0.61855670 0.78125 0.07692308 0.0000000 0.00000000 0
#> [4,] 0.000 0.03092784 0.12500 0.67307692 0.2044199 0.07024793 0
#> [5,] 0.000 0.00000000 0.00000 0.03205128 0.3535912 0.21487603 0
#> [6,] 0.000 0.00000000 0.00000 0.03846154 0.2928177 0.61983471 0
#> [7,] 0.000 0.10309278 0.03125 0.12179487 0.1160221 0.09090909 0
#>
#> $U$`2`
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 0.345 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000
#> [2,] 0.054 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000
#> [3,] 0.000 0.70085470 0.78461538 0.17592593 0.02205882 0.00000000 0.15068493
#> [4,] 0.000 0.02564103 0.06923077 0.61574074 0.32352941 0.18721461 0.50684932
#> [5,] 0.000 0.00000000 0.00000000 0.02314815 0.29411765 0.28767123 0.09589041
#> [6,] 0.000 0.00000000 0.00000000 0.02314815 0.21323529 0.42922374 0.12328767
#> [7,] 0.000 0.02564103 0.01538462 0.08333333 0.10294118 0.08675799 0.12328767
#>
#> $U$`3`
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 0.345 0.00000000 0.000000000 0.00000000 0.00000000 0.00000000 0.00000000
#> [2,] 0.054 0.00000000 0.000000000 0.00000000 0.00000000 0.00000000 0.00000000
#> [3,] 0.000 0.67164179 0.606299213 0.03533569 0.00000000 0.00000000 0.09230769
#> [4,] 0.000 0.00000000 0.173228346 0.45229682 0.05785124 0.04347826 0.29230769
#> [5,] 0.000 0.00000000 0.003937008 0.17667845 0.28925620 0.19565217 0.36923077
#> [6,] 0.000 0.00000000 0.000000000 0.15901060 0.52892562 0.66666667 0.06153846
#> [7,] 0.000 0.05970149 0.039370079 0.12367491 0.09917355 0.07971014 0.18461538
#>
#>
#> $F
#> $F$`1`
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 0 0 0 0 0 1.0294185 0
#> [2,] 0 0 0 0 0 0.1611264 0
#> [3,] 0 0 0 0 0 0.0000000 0
#> [4,] 0 0 0 0 0 0.0000000 0
#> [5,] 0 0 0 0 0 0.0000000 0
#> [6,] 0 0 0 0 0 0.0000000 0
#> [7,] 0 0 0 0 0 0.0000000 0
#>
#> $F$`2`
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 0 0 0 0 0 2.8387671 0
#> [2,] 0 0 0 0 0 0.4443288 0
#> [3,] 0 0 0 0 0 0.0000000 0
#> [4,] 0 0 0 0 0 0.0000000 0
#> [5,] 0 0 0 0 0 0.0000000 0
#> [6,] 0 0 0 0 0 0.0000000 0
#> [7,] 0 0 0 0 0 0.0000000 0
#>
#> $F$`3`
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 0 0 0 0 0 0.8675000 0
#> [2,] 0 0 0 0 0 0.1357826 0
#> [3,] 0 0 0 0 0 0.0000000 0
#> [4,] 0 0 0 0 0 0.0000000 0
#> [5,] 0 0 0 0 0 0.0000000 0
#> [6,] 0 0 0 0 0 0.0000000 0
#> [7,] 0 0 0 0 0 0.0000000 0
#>
#>
#> $hstages
#> NULL
#>
#> $ahstages
#> new_stage_id orig_stage_id original_size bin_size_ctr bin_size_min bin_size_max repstatus obsstatus propstatus immstatus matstatus
#> 1 1 Sd 0 0 0.0 0.0 0 0 1 1 0
#> 2 2 Sdl 100 100 0.0 200.0 0 1 0 1 0
#> 3 3 VSm 13 13 2.0 24.0 0 1 0 0 1
#> 4 4 Sm 127 127 24.0 230.0 0 1 0 0 1
#> 5 5 VLa 3730 3730 230.0 7230.0 0 1 0 0 1
#> 6 6 Flo 3800 3800 0.0 7600.0 1 1 0 0 1
#> 7 7 Dorm 0 0 -0.5 0.5 0 0 0 0 1
#> indataset bin_size_width bin_raw_halfwidth alive min_age max_age comments stageno
#> 1 0 0 0.0 1 NA NA Dormant seed 1
#> 2 1 200 100.0 1 NA NA Seedling 2
#> 3 1 22 11.0 1 NA NA Very small vegetative adult 3
#> 4 1 206 103.0 1 NA NA Small vegetative adult 4
#> 5 1 7000 3500.0 1 NA NA Very large vegetative adult 5
#> 6 1 7600 3800.0 1 NA NA Flowering adult 6
#> 7 1 1 0.5 1 NA NA Vegetatively dormant adult 7
#>
#> $labels
#> pop patch year2
#> 1 NA NA 1988
#> 2 NA NA 1989
#> 3 NA NA 1990
#>
#> $matrixqc
#> [1] 74 6 3
#>
#> $dataqc
#> [1] 276 2527
#>
#> attr(,"class")
#> [1] "lefkoMat"
The output from this analysis includes is a lefkoMat
object, which is a list object with the following elements:
A: a list of full population projection matrices, in order of population, patch, and year (order given in $labels
)
U: a list of matrices showing only survival-transition elements, in the same order as A
F: a list of matrices showing only fecundity elements, in the same order as A
hstages: a data frame showing the order of paired stages (given if matrices are historical, otherwise NA)
ahstages: this is the stageframe used in analysis, with stages reordered and edited as they occur in the matrix
labels: a table showing the order of matrices, according to population, patch, and year
matrixqc: a short vector used in summary
statements to describe the overall quality of each matrix (used in summary()
calls)
dataqc: a short vector used in summary
statements to describe key sampling aspects of the dataset (used in summary()
calls)
The input for the rlefko2()
function includes year = "all"
, which can be changed to year = c(1989, 1990)
to focus just on years 1989 and 1990, as in the paper, or year = 1989
to focus exclusively on the transition from 1989 to 1990 (the year entered is the year in time t). Please note, though, that lefko3
has a default behavior of creating a matrix for each year in the dataset, rather than lumping years. Package lefko3
includes a great deal of flexibility here, and can quickly estimate many matrices covering all of the populations, patches, and years occurring in a specific dataset. The function-based matrix approach in the next section will showcase more of this flexibility.
We can understand lefkoMat
objects in greater detail through the summary summary
function.
summary(ehrlen2)
#>
#> This lefkoMat object contains 3 matrices.
#>
#> Each matrix is a square matrix with 7 rows and columns, and a total of 49 elements.
#> A total of 74 survival transitions were estimated, with 24.6666666666667 per matrix.
#> A total of 6 fecundity transitions were estimated, with 2 per matrix.
#>
#> The dataset contains a total of 276 unique individuals and 2527 unique transitions.
#> NULL
We start off learning that 3 matrices were estimated, which is expected given that there are 4 consecutive years of data and an ahistorical matrix requires two consecutive years to estimate transitions. The following line notes the dimensionality of those matrices. The third, fourth, and fifth lines of the summary are particularly important: they show how many survival transition and fecundity elements were actually estimated, both overall and per matrix, and the number of individuals and transitions the matrices are based on. Matrices are often overparameterized in population ecology, meaning that the number of elements estimated is quite high given the size of the dataset. It is typical for population ecologists to consider the total number of transitions in a dataset as an indication of the statistical power going into the creation of the MPM. However, the number of individuals used is just as important because each transition that an individual experiences is dependent on the other transitions that it also experiences. Indeed, this is the fundamental point that led to the development of historical matrices and of this package - the assumption that the status of an individual in the next time step is dependent only on its current state is too simplistic and leads to pseudoreplication, among other problems. So, this output can be very helpful to understand the degree to which estimated matrices might be overparameterized or pseudoreplicated. With roughly 27 elements estimated per matrix (approximately 25 survival transitions and 2 fecundity), and the dataset containing 276 individuals long-lived enough to yield over 2500 transitions, overparameterization does not appear to be a problem, although pseudoreplication might certainly be.
Now let’s look at historical matrices. Because of the size of historical matrices, we will only show the summary.
ehrlen3 <- rlefko3(data = lathvert, stageframe = lathframe, year = c(1989, 1990),
stages = c("stage3", "stage2", "stage1"), repmatrix = lathrepm,
overwrite = lathover3, yearcol = "year2",
indivcol = "individ")
summary(ehrlen3)
#>
#> This lefkoMat object contains 2 matrices.
#>
#> Each matrix is a square matrix with 49 rows and columns, and a total of 2401 elements.
#> A total of 151 survival transitions were estimated, with 75.5 per matrix.
#> A total of 14 fecundity transitions were estimated, with 7 per matrix.
#>
#> The dataset contains a total of 276 unique individuals and 2527 unique transitions.
#> NULL
The summary output shows a number of fundamental differences here. First, there is one less matrix estimated in the historical case than in the ahistorical case because, in the case of raw historical matrices, three consecutive time steps of data are needed to estimate each transition instead of two. Second, these matrices are quite a bit bigger than ahistorical matrices, with the number of rows and columns generally equaling the number of ahistorical rows and columns squared (although this number is sometimes smaller). Finally, a much greater proportion of each matrix is composed of 0s in the historical case than in the ahistorical case. This is because historical matrices are primarily composed of structural 0s, which works against overparameterization and helps make more realistic matrices. The result is that the typical historical matrix in this example has non-zero entries in 82.5 / 2401 = 3.4% of matrix elements, while the equivalent ahistorical matrix has non-zero entries in 26.667 / 49 = 54.45% of matrix elements.
We can see the impact of structural zeroes by eliminating some of them in the process of matrix estimation. The easy way to do that is to set reduce = TRUE
within the rlefko3()
call, which eliminates stage pairs in which both column and row are zero vectors. This will end up giving us matrices with 19 fewer rows and columns, and with 82.5 / 900 = 9.2% of the resulting matrix elements estimated.
ehrlen3red <- rlefko3(data = lathvert, stageframe = lathframe, year = c(1989, 1990),
stages = c("stage3", "stage2", "stage1"), repmatrix = lathrepm,
overwrite = lathover3, yearcol = "year2",
indivcol = "individ", reduce = TRUE)
summary(ehrlen3red)
#>
#> This lefkoMat object contains 2 matrices.
#>
#> Each matrix is a square matrix with 30 rows and columns, and a total of 900 elements.
#> A total of 151 survival transitions were estimated, with 75.5 per matrix.
#> A total of 14 fecundity transitions were estimated, with 7 per matrix.
#>
#> The dataset contains a total of 276 unique individuals and 2527 unique transitions.
#> NULL
Next we will create a mean ahistorical matrix.
ehrlen2mean <- lmean(ehrlen2)
ehrlen2mean
#> $A
#> $A[[1]]
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 0.345 0.00000000 0.000000000 0.00000000 0.000000000 1.57856187 0.00000000
#> [2,] 0.054 0.00000000 0.000000000 0.00000000 0.000000000 0.24707925 0.00000000
#> [3,] 0.000 0.66368440 0.724054866 0.09606156 0.007352941 0.00000000 0.08099754
#> [4,] 0.000 0.01885629 0.122486372 0.58037149 0.195266847 0.10031360 0.26638567
#> [5,] 0.000 0.00000000 0.001312336 0.07729263 0.312321669 0.23273315 0.15504039
#> [6,] 0.000 0.00000000 0.000000000 0.07354010 0.344992865 0.57190837 0.06160871
#> [7,] 0.000 0.06281177 0.028668231 0.10960104 0.106045610 0.08579241 0.10263435
#>
#> $A[[2]]
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 0.345 0.00000000 0.000000000 0.00000000 0.000000000 1.57856187 0.00000000
#> [2,] 0.054 0.00000000 0.000000000 0.00000000 0.000000000 0.24707925 0.00000000
#> [3,] 0.000 0.66368440 0.724054866 0.09606156 0.007352941 0.00000000 0.08099754
#> [4,] 0.000 0.01885629 0.122486372 0.58037149 0.195266847 0.10031360 0.26638567
#> [5,] 0.000 0.00000000 0.001312336 0.07729263 0.312321669 0.23273315 0.15504039
#> [6,] 0.000 0.00000000 0.000000000 0.07354010 0.344992865 0.57190837 0.06160871
#> [7,] 0.000 0.06281177 0.028668231 0.10960104 0.106045610 0.08579241 0.10263435
#>
#>
#> $U
#> $U[[1]]
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 0.345 0.00000000 0.000000000 0.00000000 0.000000000 0.00000000 0.00000000
#> [2,] 0.054 0.00000000 0.000000000 0.00000000 0.000000000 0.00000000 0.00000000
#> [3,] 0.000 0.66368440 0.724054866 0.09606156 0.007352941 0.00000000 0.08099754
#> [4,] 0.000 0.01885629 0.122486372 0.58037149 0.195266847 0.10031360 0.26638567
#> [5,] 0.000 0.00000000 0.001312336 0.07729263 0.312321669 0.23273315 0.15504039
#> [6,] 0.000 0.00000000 0.000000000 0.07354010 0.344992865 0.57190837 0.06160871
#> [7,] 0.000 0.06281177 0.028668231 0.10960104 0.106045610 0.08579241 0.10263435
#>
#> $U[[2]]
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 0.345 0.00000000 0.000000000 0.00000000 0.000000000 0.00000000 0.00000000
#> [2,] 0.054 0.00000000 0.000000000 0.00000000 0.000000000 0.00000000 0.00000000
#> [3,] 0.000 0.66368440 0.724054866 0.09606156 0.007352941 0.00000000 0.08099754
#> [4,] 0.000 0.01885629 0.122486372 0.58037149 0.195266847 0.10031360 0.26638567
#> [5,] 0.000 0.00000000 0.001312336 0.07729263 0.312321669 0.23273315 0.15504039
#> [6,] 0.000 0.00000000 0.000000000 0.07354010 0.344992865 0.57190837 0.06160871
#> [7,] 0.000 0.06281177 0.028668231 0.10960104 0.106045610 0.08579241 0.10263435
#>
#>
#> $F
#> $F[[1]]
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 0 0 0 0 0 1.5785619 0
#> [2,] 0 0 0 0 0 0.2470792 0
#> [3,] 0 0 0 0 0 0.0000000 0
#> [4,] 0 0 0 0 0 0.0000000 0
#> [5,] 0 0 0 0 0 0.0000000 0
#> [6,] 0 0 0 0 0 0.0000000 0
#> [7,] 0 0 0 0 0 0.0000000 0
#>
#> $F[[2]]
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 0 0 0 0 0 1.5785619 0
#> [2,] 0 0 0 0 0 0.2470792 0
#> [3,] 0 0 0 0 0 0.0000000 0
#> [4,] 0 0 0 0 0 0.0000000 0
#> [5,] 0 0 0 0 0 0.0000000 0
#> [6,] 0 0 0 0 0 0.0000000 0
#> [7,] 0 0 0 0 0 0.0000000 0
#>
#>
#> $hstages
#> NULL
#>
#> $ahstages
#> new_stage_id orig_stage_id original_size bin_size_ctr bin_size_min bin_size_max repstatus obsstatus propstatus immstatus matstatus
#> 1 1 Sd 0 0 0.0 0.0 0 0 1 1 0
#> 2 2 Sdl 100 100 0.0 200.0 0 1 0 1 0
#> 3 3 VSm 13 13 2.0 24.0 0 1 0 0 1
#> 4 4 Sm 127 127 24.0 230.0 0 1 0 0 1
#> 5 5 VLa 3730 3730 230.0 7230.0 0 1 0 0 1
#> 6 6 Flo 3800 3800 0.0 7600.0 1 1 0 0 1
#> 7 7 Dorm 0 0 -0.5 0.5 0 0 0 0 1
#> indataset bin_size_width bin_raw_halfwidth alive min_age max_age comments stageno
#> 1 0 0 0.0 1 NA NA Dormant seed 1
#> 2 1 200 100.0 1 NA NA Seedling 2
#> 3 1 22 11.0 1 NA NA Very small vegetative adult 3
#> 4 1 206 103.0 1 NA NA Small vegetative adult 4
#> 5 1 7000 3500.0 1 NA NA Very large vegetative adult 5
#> 6 1 7600 3800.0 1 NA NA Flowering adult 6
#> 7 1 1 0.5 1 NA NA Vegetatively dormant adult 7
#>
#> $labels
#> pop patch
#> 1 1 1
#> 2 1 All
#>
#> $matrixqc
#> [1] 56 4 2
#>
#> $dataqc
#> [1] 276 2527
#>
#> attr(,"class")
#> [1] "lefkoMat"
First of all, let’s take a look at the structure of the above output. Function lmean()
creates a lefkoMat
object, just as rlefko()
does, and so we have the main composite mean matrix (shown in element A
), as well as the mean survival-transition matrix (U
) and the mean fecundity matrix (F
), followed by a section outlining the definitions and order of historical paired stages (hstages
, shown here as NA
because the matrices are ahistorical), a section outlining the actual stages as outlined in the stageframe
object used to create these matrices (ahstages
), a section outlining the definitions and order of the matrices (labels
), and then two quality control sections used in output for the summary()
function (matrixqc
and dataqc
). So, all necessary information is retained for ease of use, and to focus in on just the main mean matrix itself, we can call the first matrix of object A
.
ehrlen2mean$A[[1]]
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#> [1,] 0.345 0.00000000 0.000000000 0.00000000 0.000000000 1.57856187 0.00000000
#> [2,] 0.054 0.00000000 0.000000000 0.00000000 0.000000000 0.24707925 0.00000000
#> [3,] 0.000 0.66368440 0.724054866 0.09606156 0.007352941 0.00000000 0.08099754
#> [4,] 0.000 0.01885629 0.122486372 0.58037149 0.195266847 0.10031360 0.26638567
#> [5,] 0.000 0.00000000 0.001312336 0.07729263 0.312321669 0.23273315 0.15504039
#> [6,] 0.000 0.00000000 0.000000000 0.07354010 0.344992865 0.57190837 0.06160871
#> [7,] 0.000 0.06281177 0.028668231 0.10960104 0.106045610 0.08579241 0.10263435
Matrix designations make an impact on what we see in the output to lmean
. Here, we see two matrices: the first matrix is the mean matrix for the first patch, and the second matrix is a grand mean of patch-level means. Since there is only one patch analyzed, the patch-level mean matrix and the grand mean matrix are equal. We would see additional matrices if we had split our data by population and/or patch and asked for means for each. To see the exact specifications for each matrix, we can look at the labels
component of our mean lefkoMat
object.
The 1 designation is the default symbol used for population and patch, respectively, when no designations are supplied. This scenario is typical when no such division is made in the dataset.
We may wish to check for errors by assessing the survival of ahistorical stages. We can try the following, which shows us stage survival as the column sum for the main survival-transition matrix.
colSums(ehrlen2mean$U[[1]])
#> [1] 0.3990000 0.7453525 0.8765218 0.9368668 0.9659799 0.9907475 0.6666667
All of these values are within the realm of possibility for probabilities, and they are also reasonably similar to values published in Ehrlén (2000), so this matrix appears to be fine. Additional approaches to error-checking can include checks of specific elements within the matrix to see if they match the expected values. This is the fine-scale approach that we take to make sure that we, the maintainers of package lefko3
, are not causing new bugs when we make improvements to core matrix estimation functions.
And now the historical mean matrix. We will use the reduced matrix to simplify later analyses, and show only the top-left corner of the rather large matrix.
ehrlen3mean <- lmean(ehrlen3red)
ehrlen3mean$A[[1]][1:20,1:8]
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#> [1,] 0.345 0 0.00000000 0.0000000 0 0.000000000 0.0000000 0
#> [2,] 0.000 0 0.00000000 0.0000000 0 0.000000000 0.0000000 0
#> [3,] 0.000 0 0.00000000 0.0000000 0 0.000000000 0.0000000 0
#> [4,] 0.000 0 0.00000000 0.0000000 0 0.000000000 0.0000000 0
#> [5,] 0.000 0 0.00000000 0.0000000 0 0.000000000 0.0000000 0
#> [6,] 0.000 0 0.68796296 0.0000000 0 0.793737374 0.0000000 0
#> [7,] 0.000 0 0.03302469 0.0000000 0 0.075555556 0.0000000 0
#> [8,] 0.000 0 0.00000000 0.0000000 0 0.000000000 0.0000000 0
#> [9,] 0.000 0 0.02685185 0.0000000 0 0.005050505 0.0000000 0
#> [10,] 0.000 0 0.00000000 0.3333333 0 0.000000000 0.5416667 0
#> [11,] 0.000 0 0.00000000 0.4166667 0 0.000000000 0.4583333 0
#> [12,] 0.000 0 0.00000000 0.0000000 0 0.000000000 0.0000000 0
#> [13,] 0.000 0 0.00000000 0.0000000 0 0.000000000 0.0000000 0
#> [14,] 0.000 0 0.00000000 0.0000000 0 0.000000000 0.0000000 0
#> [15,] 0.000 0 0.00000000 0.0000000 0 0.000000000 0.0000000 0
#> [16,] 0.000 0 0.00000000 0.0000000 0 0.000000000 0.0000000 0
#> [17,] 0.000 0 0.00000000 0.0000000 0 0.000000000 0.0000000 0
#> [18,] 0.000 0 0.00000000 0.0000000 0 0.000000000 0.0000000 0
#> [19,] 0.000 0 0.00000000 0.0000000 0 0.000000000 0.0000000 0
#> [20,] 0.000 0 0.00000000 0.0000000 0 0.000000000 0.0000000 0
Do not fear the prevalence of 0s in this matrix - this is normal, both because most elements are structural 0s and so cannot equal anything else, and because this is a raw matrix, meaning that transitions that do not actually occur in the dataset cannot equal anything other than 0.
To understand the dominance of structural 0s in the historical case, let’s take a look at the hstages
object associated with this mean matrix.
ehrlen3mean$hstages
#> stcod3 stcod2 stage3 stage2n
#> 1 Sd Sd 1 1
#> 2 Sdl Sd 2 1
#> 11 VSm Sdl 3 2
#> 12 Sm Sdl 4 2
#> 15 Dorm Sdl 7 2
#> 19 VSm VSm 3 3
#> 20 Sm VSm 4 3
#> 21 VLa VSm 5 3
#> 23 Dorm VSm 7 3
#> 27 VSm Sm 3 4
#> 28 Sm Sm 4 4
#> 29 VLa Sm 5 4
#> 30 Flo Sm 6 4
#> 31 Dorm Sm 7 4
#> 35 VSm VLa 3 5
#> 36 Sm VLa 4 5
#> 37 VLa VLa 5 5
#> 38 Flo VLa 6 5
#> 39 Dorm VLa 7 5
#> 41 Sd Flo 1 6
#> 42 Sdl Flo 2 6
#> 44 Sm Flo 4 6
#> 45 VLa Flo 5 6
#> 46 Flo Flo 6 6
#> 47 Dorm Flo 7 6
#> 51 VSm Dorm 3 7
#> 52 Sm Dorm 4 7
#> 53 VLa Dorm 5 7
#> 54 Flo Dorm 6 7
#> 55 Dorm Dorm 7 7
There are 30 pairs of ahistorical stages. These pairs correspond to the rows and columns of the historical matrices output by rlefko3
in this case. The pairs are interpreted so that matrix columns represent the states of individual in times t-1 and t, and the rows represent states in times t and t+1. For an element in the matrix to contain a number other than 0, it must represent the same stage at time t in both the column stage pairs and the row stage pairs. The element [1, 1], for example, represents the transition probability from dormant seed at times t-1 and t (column pair), to dormant seed at times t and t+1 (row pair) - the time t stages match, and so this element is possible. However, element [1, 2] represents the transition probability from seedling in time t-1 and very small adult in time t (column pair), to dormant seed in time t and in time t+1 (row pair). Clearly [1, 2] is a structural 0 because it is impossible for an individual to be both a dormant seed and a very small adult at once in time t.
Error-checking is more difficult with historical matrices because they are typically one or two orders of magnitude bigger than their ahistorical counterparts, but the same basic strategy can be used here as with ahistorical matrices. Take a look at the column sums here to see the difficulty.
colSums(ehrlen3mean$U[[1]])
#> [1] 0.3450000 0.0000000 0.7478395 0.7500000 1.0000000 0.8743434 1.0000000 0.0000000 1.0000000 0.9057018 0.9391775 1.0000000
#> [13] 1.0000000 1.0000000 0.5000000 0.9722222 0.9677419 0.9638907 1.0000000 0.3990000 0.0000000 1.0000000 0.9822596 0.9946809
#> [25] 1.0000000 0.5000000 0.4459459 0.4285714 0.5000000 0.5000000
While not too bad here, other historical matrices often have more than 100 columns, sometimes many, many more (some historical matrices used in Shefferson et al. (2014) had dimensions of over 2500 x 2500!). In these cases we can use summary()
to assess the distribution of survival estimates for historical stages, which is given as the set of column sums in the survival-transition matrix, as below.
summary(colSums(ehrlen3mean$U[[1]]))
#> Min. 1st Qu. Median Mean 3rd Qu. Max.
#> 0.0000 0.5000 0.9224 0.7239 1.0000 1.0000
As long as all of the numbers are between 0 and 1, then all is probably well. Fine-scale error-checking would require outputting the matrix into a spreadsheet and assessing it using the hstages
output as a guide to what the elements refer to. Non-zero elements should only exist where biologically and logically possible.
We may wish to analyze population dynamics with these matrices, and some population analyses are possible with lefko3
itself. Let’s estimate the deterministic population growth rate in each case via Eigen analysis. We will start by estimating the annual population growth rate from the ahistorical analyses, followed by the population growth rate associated with the mean matrix from that analysis. Note that each lambda estimate also includes a data frame describing the matrices in order (this is the labels
object within the output list). Here is the set of ahistorical annual lambda estimates.
lambda3(ehrlen2)
#> pop patch year2 lambda
#> 1 NA NA 1988 0.8952585
#> 2 NA NA 1989 0.9235493
#> 3 NA NA 1990 1.0096490
Here is the lambda associated with the mean matrix.
Readers may be surprised to see that lambda for the mean matrix is on the high side relative to the annual matrices. This is most likely a result of the fact that some elements in annual matrices are 0s due simply to a lack of individuals transitioning through them. Such a situation becomes more and more likely to happen as sample size decreases.
We will now look at the same numbers for the historical analyses. First the annual matrices.
Now the mean matrix.
Readers will likely observe both that there are fewer lambda estimates in the historical case, and that the mean lambda is lower. First, because there are 4 years of data, there are three ahistorical transitions possible for estimation: year 1 to 2, year 2 to 3, and year 3 to 4. However, in the historical case, only two are possible: from years 1 and 2 to years 2 and 3, and from years 2 and 3 to years 3 and 4. Second, historical matrices integrate temporal autocorrelation in vital rates in ways that ahistorical matrices generally cannot, and these autocorrelations are likely to be most strongly impacted by trade-offs operating across years (Shefferson and Roach 2010). One particularly common such trade-off is the cost of growth: an individual that grows a great deal in one time step due to great environmental conditions in that year might pay a large cost of survival, growth, or reproduction in the next if those environmental conditions deteriorate (Shefferson, Warren II, and Pulliam 2014). While we do not argue that the drop in lambda must be due to this specific trade-off, and it is certainly possible for historical matrix analysis to lead to higher lambda estimates, we do believe that this lambda is likely to be more realistic than the higher lambda estimated in the ahistorical case.
We can also take a peek at the stable stage distributions, as follows for the ahistorical case. Our numbers here match those produced by package popbio
’s stable.stage()
function.
stablestage3(ehrlen2mean)
#> matrix new_stage_id orig_stage_id original_size ss_prop
#> 1 1 1 Sd 0 0.29261073
#> 2 1 2 Sdl 100 0.04579994
#> 3 1 3 VSm 13 0.22875634
#> 4 1 4 Sm 127 0.18625615
#> 5 1 5 VLa 3730 0.07716890
#> 6 1 6 Flo 3800 0.11352079
#> 7 1 7 Dorm 0 0.05588714
#> 8 2 1 Sd 0 0.29261073
#> 9 2 2 Sdl 100 0.04579994
#> 10 2 3 VSm 13 0.22875634
#> 11 2 4 Sm 127 0.18625615
#> 12 2 5 VLa 3730 0.07716890
#> 13 2 6 Flo 3800 0.11352079
#> 14 2 7 Dorm 0 0.05588714
The data frame output shows us the stages themselves, which matrix they refer to, and the stable stage distribution (in the ss_prop
column). We can do this for the historical case as well. Because historical output for the stablestage3()
function is a list with two data frames, let’s take a look at each of these data frames. The first will be the stage-pair output.
ehrlen3mss <- stablestage3(ehrlen3mean)
ehrlen3mss$hist[,c(1,2,3,6)]
#> matrix orig_stage_id_2 orig_stage_id_1 ss_prop
#> 1 1 Sd Sd 1.276316e-01
#> 2 1 Sdl Sd 1.235747e-02
#> 3 1 VSm Sdl 0.000000e+00
#> 4 1 Sm Sdl 0.000000e+00
#> 5 1 Dorm Sdl 0.000000e+00
#> 6 1 VSm VSm 1.461200e-01
#> 7 1 Sm VSm 2.415823e-02
#> 8 1 VLa VSm 4.099566e-05
#> 9 1 Dorm VSm 1.868573e-03
#> 10 1 VSm Sm 2.856575e-02
#> 11 1 Sm Sm 1.119221e-01
#> 12 1 VLa Sm 1.643359e-02
#> 13 1 Flo Sm 1.518009e-02
#> 14 1 Dorm Sm 2.044845e-02
#> 15 1 VSm VLa 2.225618e-04
#> 16 1 Sm VLa 1.691729e-02
#> 17 1 VLa VLa 2.496102e-02
#> 18 1 Flo VLa 2.900608e-02
#> 19 1 Dorm VLa 1.007120e-02
#> 20 1 Sd Flo 2.069917e-01
#> 21 1 Sdl Flo 3.239869e-02
#> 22 1 Sm Flo 1.722032e-02
#> 23 1 VLa Flo 2.850957e-02
#> 24 1 Flo Flo 6.631266e-02
#> 25 1 Dorm Flo 1.086871e-02
#> 26 1 VSm Dorm 4.009221e-03
#> 27 1 Sm Dorm 2.516956e-02
#> 28 1 VLa Dorm 1.127899e-02
#> 29 1 Flo Dorm 4.153450e-03
#> 30 1 Dorm Dorm 7.182175e-03
#> 31 2 Sd Sd 1.276316e-01
#> 32 2 Sdl Sd 1.235747e-02
#> 33 2 VSm Sdl 0.000000e+00
#> 34 2 Sm Sdl 0.000000e+00
#> 35 2 Dorm Sdl 0.000000e+00
#> 36 2 VSm VSm 1.461200e-01
#> 37 2 Sm VSm 2.415823e-02
#> 38 2 VLa VSm 4.099566e-05
#> 39 2 Dorm VSm 1.868573e-03
#> 40 2 VSm Sm 2.856575e-02
#> 41 2 Sm Sm 1.119221e-01
#> 42 2 VLa Sm 1.643359e-02
#> 43 2 Flo Sm 1.518009e-02
#> 44 2 Dorm Sm 2.044845e-02
#> 45 2 VSm VLa 2.225618e-04
#> 46 2 Sm VLa 1.691729e-02
#> 47 2 VLa VLa 2.496102e-02
#> 48 2 Flo VLa 2.900608e-02
#> 49 2 Dorm VLa 1.007120e-02
#> 50 2 Sd Flo 2.069917e-01
#> 51 2 Sdl Flo 3.239869e-02
#> 52 2 Sm Flo 1.722032e-02
#> 53 2 VLa Flo 2.850957e-02
#> 54 2 Flo Flo 6.631266e-02
#> 55 2 Dorm Flo 1.086871e-02
#> 56 2 VSm Dorm 4.009221e-03
#> 57 2 Sm Dorm 2.516956e-02
#> 58 2 VLa Dorm 1.127899e-02
#> 59 2 Flo Dorm 4.153450e-03
#> 60 2 Dorm Dorm 7.182175e-03
This is hard to read because it is by stage pair. It may make more sense if we look at the $ahist
portion, which shows us the stable stage distribtuion according to the original stages given in our stageframe.
ehrlen3mss$ahist
#> matrix new_stage_id ss_prop
#> 1 1 1 0.33462326
#> 2 1 2 0.04475616
#> 3 1 3 0.17891752
#> 4 1 4 0.19538751
#> 5 1 5 0.08122417
#> 6 1 6 0.11465228
#> 7 1 7 0.05043911
#> 8 2 1 0.33462326
#> 9 2 2 0.04475616
#> 10 2 3 0.17891752
#> 11 2 4 0.19538751
#> 12 2 5 0.08122417
#> 13 2 6 0.11465228
#> 14 2 7 0.05043911
Notice that this stable stage distribution is different from the ahistorical case, suggesting a strong influence of individual history.
Let’s take a look at the reproductive values now, in similar order to the stable stage distribution case.
repvalue3(ehrlen2mean)
#> matrix new_stage_id orig_stage_id original_size left_vector rep_value
#> 1 1 1 Sd 0 0.0165109 1.00000
#> 2 1 2 Sdl 100 0.1872506 11.34103
#> 3 1 3 VSm 13 0.2331356 14.12010
#> 4 1 4 Sm 127 0.3734467 22.61819
#> 5 1 5 VLa 3730 0.5124378 31.03633
#> 6 1 6 Flo 3800 0.6561831 39.74242
#> 7 1 7 Dorm 0 0.2787137 16.88059
#> 8 2 1 Sd 0 0.0165109 1.00000
#> 9 2 2 Sdl 100 0.1872506 11.34103
#> 10 2 3 VSm 13 0.2331356 14.12010
#> 11 2 4 Sm 127 0.3734467 22.61819
#> 12 2 5 VLa 3730 0.5124378 31.03633
#> 13 2 6 Flo 3800 0.6561831 39.74242
#> 14 2 7 Dorm 0 0.2787137 16.88059
These values are also the same as those produced by popbio
’s reproductive.value()
function. But there are differences when we look at the historical case. Note that popbio
may fail in the historical case, as that package is not generally made to handle extremely large matrices.
ehrlen3mrv <- repvalue3(ehrlen3mean)
ehrlen3mrv$hist[,c(1,2,3,6,7)]
#> matrix orig_stage_id_2 orig_stage_id_1 left_vector rep_value
#> 1 1 Sd Sd 0.0000000 0.000000000
#> 2 1 Sdl Sd 0.0000000 0.000000000
#> 3 1 VSm Sdl 0.1211539 0.000000000
#> 4 1 Sm Sdl 0.1575277 0.000000000
#> 5 1 Dorm Sdl 0.0942968 0.000000000
#> 6 1 VSm VSm 0.1452644 0.979216089
#> 7 1 Sm VSm 0.2058943 0.210123830
#> 8 1 VLa VSm 0.0000000 0.000000000
#> 9 1 Dorm VSm 0.1061292 0.032451907
#> 10 1 VSm Sm 0.1685702 0.222144838
#> 11 1 Sm Sm 0.2071118 0.979234173
#> 12 1 VLa Sm 0.2708996 0.452395497
#> 13 1 Flo Sm 0.3209769 0.350774425
#> 14 1 Dorm Sm 0.1128908 0.377758396
#> 15 1 VSm VLa 0.0758763 0.000779052
#> 16 1 Sm VLa 0.2517637 0.179924205
#> 17 1 VLa VLa 0.2827789 0.717276514
#> 18 1 Flo VLa 0.3061106 0.639215633
#> 19 1 Dorm VLa 0.1172431 0.193225239
#> 20 1 Sd Flo 0.0000000 0.000000000
#> 21 1 Sdl Flo 0.0000000 0.000000000
#> 22 1 Sm Flo 0.2627826 0.191162869
#> 23 1 VLa Flo 0.2983678 0.864410360
#> 24 1 Flo Flo 0.3455908 1.649827425
#> 25 1 Dorm Flo 0.1300279 0.231264874
#> 26 1 VSm Dorm 0.0848390 0.015691528
#> 27 1 Sm Dorm 0.1068625 0.113623120
#> 28 1 VLa Dorm 0.1221476 0.140001422
#> 29 1 Flo Dorm 0.1669090 0.049907829
#> 30 1 Dorm Dorm 0.0633956 0.074509265
#> 31 2 Sd Sd 0.0000000 0.000000000
#> 32 2 Sdl Sd 0.0000000 0.000000000
#> 33 2 VSm Sdl 0.1211539 0.000000000
#> 34 2 Sm Sdl 0.1575277 0.000000000
#> 35 2 Dorm Sdl 0.0942968 0.000000000
#> 36 2 VSm VSm 0.1452644 0.979216089
#> 37 2 Sm VSm 0.2058943 0.210123830
#> 38 2 VLa VSm 0.0000000 0.000000000
#> 39 2 Dorm VSm 0.1061292 0.032451907
#> 40 2 VSm Sm 0.1685702 0.222144838
#> 41 2 Sm Sm 0.2071118 0.979234173
#> 42 2 VLa Sm 0.2708996 0.452395497
#> 43 2 Flo Sm 0.3209769 0.350774425
#> 44 2 Dorm Sm 0.1128908 0.377758396
#> 45 2 VSm VLa 0.0758763 0.000779052
#> 46 2 Sm VLa 0.2517637 0.179924205
#> 47 2 VLa VLa 0.2827789 0.717276514
#> 48 2 Flo VLa 0.3061106 0.639215633
#> 49 2 Dorm VLa 0.1172431 0.193225239
#> 50 2 Sd Flo 0.0000000 0.000000000
#> 51 2 Sdl Flo 0.0000000 0.000000000
#> 52 2 Sm Flo 0.2627826 0.191162869
#> 53 2 VLa Flo 0.2983678 0.864410360
#> 54 2 Flo Flo 0.3455908 1.649827425
#> 55 2 Dorm Flo 0.1300279 0.231264874
#> 56 2 VSm Dorm 0.0848390 0.015691528
#> 57 2 Sm Dorm 0.1068625 0.113623120
#> 58 2 VLa Dorm 0.1221476 0.140001422
#> 59 2 Flo Dorm 0.1669090 0.049907829
#> 60 2 Dorm Dorm 0.0633956 0.074509265
The final column is the reproductive value of the stage pair. Once again, this is hard to interpret, so we can take a look at the ahistorical summary.
ehrlen3mrv$ahist
#> matrix new_stage_id rep_value
#> 1 1 1 0.0000000
#> 2 1 2 0.0000000
#> 3 1 3 1.0000000
#> 4 1 4 1.3746304
#> 5 1 5 1.7852090
#> 6 1 6 2.2086186
#> 7 1 7 0.7465808
#> 8 2 1 0.0000000
#> 9 2 2 0.0000000
#> 10 2 3 1.0000000
#> 11 2 4 1.3746304
#> 12 2 5 1.7852090
#> 13 2 6 2.2086186
#> 14 2 7 0.7465808
Notice that the reproductive values are quite different here, once again suggesting a strong importance to individual history.
Further analytical tools are being planned for lefko3
, but packages that handle projection matrices can typically handle the individual matrices produced and saved in lefkoMat
objects in this package. Differences, obscure results, and errors sometimes arise when packages are not made to handle large and/or sparse matrices - historical matrices are both, and so care must be taken with their analysis.
In this analysis, we will build function-based MPMs using the Lathyrus dataset. To spice things up, we will use a slightly different approach to size classification, using the natural log of size instead of the normal size shown in the dataset. This has to do with the fact that volume is used as the size metric here, and so should have an allometric relationship to some vital rates (note that all size metrics have allometric relationships by default, but this is clearer when size is based on something more strongly related to mass, as is volume). We will also categorize individuals as reproductive vs. non-reproductive.
First, we will create a stageframe for the dataset. For this purpose, let’s look back at a summary of the main dataset, focusing at the distribution of log sizes.
summary(c(lathyrus$Volume88, lathyrus$Volume89, lathyrus$Volume90, lathyrus$Volume91))
#> Min. 1st Qu. Median Mean 3rd Qu. Max.
#> 0.0 0.0 27.2 349.2 479.6 7032.0
summary(c(lathyrus$lnVol88, lathyrus$lnVol89, lathyrus$lnVol90, lathyrus$lnVol91))
#> Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
#> 0.600 2.700 4.800 4.777 6.600 8.900 1248
It is important to note the size minima and maxima, because we have been using 0 as the size of vegetatively dormant individuals. What we note here is that apart from the many NAs that occur in the log sizes in the dataset, the smallest log sizes are still above 0, meaning that we are still able to use the value 0 as an indicator of vegetative dormancy. This would not be the case if the smallest size were negative, as might happen when the volume (not log volume) is between 0 and 1.
It can also help to take a look at plots of these distributions. First we will look at the raw volume data.
plot(density(c(lathyrus$Volume88, lathyrus$Volume89, lathyrus$Volume90, lathyrus$Volume91),
na.rm = TRUE), main = "Volume")
plot of chunk Ch2an2st1ln333
Next we will look at the log volume data.
plot(density(c(lathyrus$lnVol88, lathyrus$lnVol89, lathyrus$lnVol90, lathyrus$lnVol91),
na.rm = TRUE), main = "Log volume")
plot of chunk Ch2an2st1ln339
We see two very differently shaped distributions. The log volume distribution looks ‘better’ than the volume distribution, in the sense that it is closer to some semblance of a Gaussian distribution. This is helpful since our size metrics are decimals, and so cannot be treated as integers (in the latter case, we could try modeling them as either Poisson- or negative binomial-distributed). We will work with log volume in this example, and treat it as Gaussian-distributed.
We need to cover all log volumes actually occurring in the dataset, because our approach will include developing estimates of vital rates given inputs including all possible sizes, reproductive status, and so forth. We will build this by creating vectors of the values describing each stage, always in the same order.
sizevector <- c(0, 4.6, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9)
stagevector <- c("Sd", "Sdl", "Dorm", "Sz1nr", "Sz2nr", "Sz3nr", "Sz4nr", "Sz5nr",
"Sz6nr", "Sz7nr", "Sz8nr", "Sz9nr", "Sz1r", "Sz2r", "Sz3r", "Sz4r",
"Sz5r", "Sz6r", "Sz7r", "Sz8r", "Sz9r")
repvector <- c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1)
obsvector <- c(0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
matvector <- c(0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
immvector <- c(1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
propvector <- c(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
indataset <- c(0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
binvec <- c(0, 4.6, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5)
lathframeln <- sf_create(sizes = sizevector, stagenames = stagevector, repstatus = repvector,
obsstatus = obsvector, matstatus = matvector, immstatus = immvector,
indataset = indataset, binhalfwidth = binvec, propstatus = propvector)
To be useful to others trying to understand your work, or to yourself in the future, it helps to add text descriptions of the stages. Here, we also add some descriptions to this stageframe as comments.
lathframeln$comments <- c("Dormant seed", "Seedling", "Dormant", "Size 1 Non-reprod", "Size 2 Non-reprod",
"Size 3 Non-reprod", "Size 4 Non-reprod", "Size 5 Non-reprod", "Size 6 Non-reprod",
"Size 7 Non-reprod", "Size 8 Non-reprod", "Size 9 Non-reprod", "Size 1 Reprod",
"Size 2 Reprod", "Size 3 Reprod", "Size 4 Reprod", "Size 5 Reprod", "Size 6 Reprod",
"Size 7 Reprod", "Size 8 Reprod", "Size 9 Reprod")
Once the stageframe is created, we can reorganize the dataset into vertical format. Here, ‘vertical’ format is a way of organizing demographic data in which each row corresponds to the state of a single individual in two (if ahistorical) or three (if historical) consecutive time steps. To handle this, we use the verticalize3()
function, which creates historically-formatted vertical datasets, as below. We also need to get rid of NAs in size and fecundity variables for modelsearch
to work properly when we actually build models of vital rates, so we will now use the NAas0 = TRUE
option.
lathvertln <- verticalize3(lathyrus, noyears = 4, firstyear = 1988, patchidcol = "SUBPLOT",
individcol = "GENET", blocksize = 9, juvcol = "Seedling1988",
size1col = "lnVol88", repstr1col = "FCODE88",
fec1col = "Intactseed88", dead1col = "Dead1988",
nonobs1col = "Dormant1988", stageassign = lathframeln,
stagesize = "sizea", censorcol = "Missing1988",
censorkeep = NA, NAas0 = TRUE, censor = TRUE)
Something to note here is that fecundity is typically but not always an integer. We can see this below, where we show each non-integer in the dataset. These are not errors - they are due to the fact that fecundity was estimated in two ways in this dataset, one way leading to integers, and one leading to decimals.
lathvertln$feca2[which(lathvertln$feca2 != round(lathvertln$feca2))]
#> [1] 12.500000 3.818182 26.600000 23.333333 5.333333 24.500000
length(lathvertln$feca2)
#> [1] 2527
In this case, we can either treat fecundity as a continuous variable, or round the values and treat them as count variables. The choice of which approach to take will have major repercussions on the analysis, and may severely alter projected population dynamics. In this dataset, fecundity is mostly counts of intact seeds, and only differs in a few cases where the seed output was estimated based on other models. Indeed, only 6 of 2527 entries are not integers. So, we will round fecundity so that we can assume count variables in the analysis, as below.
lathvertln$feca2 <- round(lathvertln$feca2)
lathvertln$feca1 <- round(lathvertln$feca1)
lathvertln$feca3 <- round(lathvertln$feca3)
All set! Now to move on to supplemental descriptive information.
Next we need to create a reproductive matrix, which describes which stages are reproductive, which stages they lead to the reproduction of, and at what level they reproduce. This matrix is mostly composed of 0s, but fecundity is noted as non-zero entries equal to a scalar multiplier to the full fecundity estimated by lefko3
. This matrix has rows and columns equal to the number of stages described in the stageframe for this dataset, and the rows and columns refer to these stages in the same order as in the stageframe. In many ways, it looks like a nearly empty population matrix, but notes the per-individual mean modifiers on fecundity for each stage that actually reproduces. Here, we first create a 0 square matrix with dimensions equal to the number of rows in lathframeln
. Then we modify elements corresponding to fecundity by the expected mean seed dormancy probability (row 1), and by the germination rate (row 2).
Next we need to provide some given transitions. We will use the same overwrite tables as in the last example (objects lathover2
and lathover3
), because these relate only to stages that are the same in both analyses. Here they are again.
lathover2 <- overwrite(stage3 = c("Sd", "Sdl"), stage2 = c("Sd", "Sd"),
givenrate = c(0.345, 0.054))
lathover3 <- overwrite(stage3 = c("Sd", "Sd", "Sdl"), stage2 = c("Sd", "Sd", "Sd"),
stage1 = c("Sd", "rep", "rep"), givenrate = c(0.345, 0.345, 0.054))
Next, we move to a new step: modeling vital rates.
Here, we will run the modelsearch
function with the new vertical dataset, first for the ahistorical model set and then for the historical model set. This function will develop our models for us, provided we tell the function how this should all be handled. This function looks simple, but it is actually quite complicated in that it automates several crucial portions of demographic analysis. Specifically, it automates 1) the building of global models for each vital rate requested, 2) the exhaustive construction of all reduced models, and 3) the evaluation of models leading to the determination of the best-fit model. Let’s look at some of the options that we will utilize for this purpose (please note that this list includes only some of the options actually offered by the function - further options are shown in the documentation for modelsearch()
, and further theoretical details are shown in the Basic theory vignette).
historical: Setting this to TRUE or FALSE tells R whether to include state in time t-1 in the global models.
approach: This option tells R whether to use generalized linear models (glm
), in which all factors are treated as fixed, or mixed effects models (lme4
), in which factors are treated as either fixed or random, most notably time, patch, and individual identity. We encourage users to use the latter option, as it accounts for pseudoreplication, but the former approach is more common.
suite: This tells R which factors to include in the global model. Possible values include size
, which includes size only; rep
, which includes reproductive status only; main
, which includes both size and reproductive status as main effects only; full
, which includes both size and reproductive status and all two-way interactions; and const
, which includes only an intercept. These factors are in addition to individual identity and time.
vitalrates: This option tells R which vital rates to model. The default is to model survival, size, and fecundity, but users can also model observation status and reproduction status.
juvestimate: This optional term tells R the name of the juvenile stage transitioning to maturity, in cases where the dataset includes data on juveniles.
juvsize: This optional term denotes whether size should be used as an independent term in models involving transition from the juvenile stage.
bestfit: This describes whether the best-fit model should be chosen as the model with the lowest AICc (AICc
) or as the most parsimonious model (AICc&k
), where the latter is the model that has the fewest estimated parameters and is within 2 AICc units of the model with the lowest AICc. We encourage users to choose the latter, although many, perhaps most situations will lead to the same model.
sizedist: This designates the distribution used for size. The options include gaussian
, poisson
, and negbin
, the last of which refers to the negative binomial distribution.
fecdist: This designates the distribution used for fecundity. The options include gaussian
, poisson
, and negbin
, the last of which refers to the negative binomial distribution.
fectime: This designates whether fecundity is estimated within time t (the default) or time t+1. Plant ecologists are likely to choose the former, since fecundity is typically estimated via a proxy such as flowers, fruit, or seed produced. Wildlife ecologists might choose the latter, since fecundity may be best estimated as a count of actual juveniles within nests, burrows, or other family structures.
indiv: This should include the name of the variable corresponding to individual identity in the vertical dataset.
patch: This should include the name of the variable corresponding to patch identity in the vertical dataset.
year: This should include the name of the variable corresponding to time t in the vertical dataset.
year.as.random: This tells R whether to treat year as a random factor, and is only used when approach = "lme4"
.
patch.as.random: This tells R whether to treat patch identity as a random factor, and is only used when approach = "lme4"
.
show.model.tables: This tells R to include the full dredge model tables showing all models developed and their associated AICc values.
In addition, there are other options that provide flexibility in handling datasets with different designations for key variables, and allowing manual designation of stages.
Here we create the ahistorical model set.
lathmodelsln2 <- modelsearch(lathvertln, historical = FALSE, approach = "lme4", suite = "full",
vitalrates = c("surv", "obs", "size", "repst", "fec"), juvestimate = "Sdl",
bestfit = "AICc&k", sizedist = "gaussian", fecdist = "poisson",
indiv = "individ", patch = "patchid", year = "year2",
year.as.random = TRUE, patch.as.random = TRUE, quiet = TRUE)
#> Warning in modelsearch(lathvertln, historical = FALSE, approach = "lme4", : WARNING: Fecundity in time t cannot be Poisson-distributed and include 0s. Will develop fecundity models excluding all 0s. Consider adding a reproductive status variable to absorb 0 values.
#>
#> Developing global model of survival probability...
#>
#>
#> Developing global model of observation probability...
#> boundary (singular) fit: see ?isSingular
#>
#> Developing global model of size (Gaussian)...
#>
#>
#> Developing global model of the probability of reproduction...
#>
#>
#> Developing global model of fecundity (Poisson)...
#> fixed-effect model matrix is rank deficient so dropping 2 columns / coefficients
#>
#> Developing global model of juvenile survival probability...
#> boundary (singular) fit: see ?isSingular
#>
#> Developing global model of juvenile observation probability...
#> boundary (singular) fit: see ?isSingular
#>
#> Developing global model of juvenile size (Gaussian)...
#> boundary (singular) fit: see ?isSingular
#>
#> Juvenile reproduction response is constant so will not model it.
#>
#> All global models developed.
#>
#>
#> Commencing dredge of survival probability...
#>
#>
#> Commencing dredge of observation probability...
#>
#>
#> Commencing dredge of size...
#>
#>
#> Commencing dredge of reproduction probability...
#>
#>
#> Commencing dredge of fecundity...
#>
#>
#> Commencing dredge of juvenile survival probability...
#>
#>
#> Commencing dredge of juvenile observation probability...
#>
#>
#> Commencing dredge of juvenile size...
#>
#>
#> Finished dredging all vital rates.
The output can be rather verbose, and so we have limited it with the quiet = TRUE
option. The function was developed to provide text marker posts of what the function is doing and what it has accomplished, as well as to show all warnings from all workhorse functions used. Because we used the lme4
approach here, this includes warnings originating from estimating mixed linear models with package lme4
(Bates et al. 2015). It also shows warnings originating from the dredge()
function of package MuMIn
(Bartoń 2014), which is the core function used in model building and AICc estimation. We encourage users to get familiar with interpreting these warnings and assessing the degree to which they impact their own analyses.
In developing these linear models, the modelsearch()
function set up a series of nested datasets for use in estimating vital rates as conditional rates and probabilities. The exact subsets created depend on which parameters are called for. It is rather important to consider which are required, and particular attention needs to be paid if there are size classes with sizes of 0. In these situations, it is best to consider a size of 0 as unobservable, and so to introduce observation status as a vital rate. This sets up datasets for size estimation that do not include 0 in the response term, because all 0 responses are already absorbed by observation status.
A further important point is in the style of model selection allowed. Package lefko3
differs from many other approaches in that it allows a more intelligent approach to model selection. Indeed, instead of simply selecting the model with the lowest AICc, the reader can set modelsearch()
to choose the model with fewest parameters within 2.0 AICc units of the model with the lowest AICc. This is the default setting, and is more in-line with model selection protocols preferred by information theorists (Burnham and Anderson 2002).
Let’s take a peek at the summary for the model selection output. This condenses the output to the necessities.
summary(lathmodelsln2)
#> This LefkoMod object includes 8 linear models.
#> Best-fit model criterion used: AICc&k
#>
#> ────────────────────────────────────────────────────────────────────────────────
#> Survival model:
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: binomial ( logit )
#> Formula: alive3 ~ repstatus2 + sizea2 + (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: surv.data
#> AIC BIC logLik deviance df.resid
#> 916.4218 950.7233 -452.2109 904.4218 2240
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 0.4844333
#> patchid (Intercept) 0.2554894
#> year2 (Intercept) 0.0008752
#> Number of obs: 2246, groups: individ, 257; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept) repstatus2 sizea2
#> 2.0461 1.7264 0.1469
#>
#> ────────────────────────────────────────
#>
#> Observation model:
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: binomial ( logit )
#> Formula: obsstatus3 ~ (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: obs.data
#> AIC BIC logLik deviance df.resid
#> 1342.9524 1365.5910 -667.4762 1334.9524 2117
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 6.46e-05
#> patchid (Intercept) 3.61e-01
#> year2 (Intercept) 0.00e+00
#> Number of obs: 2121, groups: individ, 254; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept)
#> 2.24
#> convergence code 0; 0 optimizer warnings; 1 lme4 warnings
#>
#> ────────────────────────────────────────
#>
#> Size model:
#> Linear mixed model fit by REML ['lmerMod']
#> Formula: sizea3 ~ repstatus2 + sizea2 + (1 | individ) + (1 | year2) + (1 | patchid) + repstatus2:sizea2
#> Data: size.data
#> REML criterion at convergence: 5986.416
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 0.6378
#> patchid (Intercept) 0.1651
#> year2 (Intercept) 0.3511
#> Residual 1.0576
#> Number of obs: 1916, groups: individ, 254; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept) repstatus2 sizea2 repstatus2:sizea2
#> 2.6531 -1.5411 0.4095 0.2967
#>
#> ────────────────────────────────────────
#>
#> Reproductive status model:
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: binomial ( logit )
#> Formula: repstatus3 ~ repstatus2 + sizea2 + (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: repst.data
#> AIC BIC logLik deviance df.resid
#> 1613.2218 1646.5698 -800.6109 1601.2218 1910
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 5.404e-05
#> patchid (Intercept) 3.292e-01
#> year2 (Intercept) 6.737e-01
#> Number of obs: 1916, groups: individ, 254; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept) repstatus2 sizea2
#> -5.9116 0.6675 0.8264
#> convergence code 0; 0 optimizer warnings; 1 lme4 warnings
#>
#> ────────────────────────────────────────
#>
#> Fecundity model:
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: poisson ( log )
#> Formula: feca2 ~ sizea2 + (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: fec.data
#> AIC BIC logLik deviance df.resid
#> 2036.563 2054.462 -1013.282 2026.563 260
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 0.5422
#> patchid (Intercept) 0.1372
#> year2 (Intercept) 0.1573
#> Number of obs: 265, groups: individ, 101; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept) sizea2
#> -2.4599 0.6374
#>
#> ────────────────────────────────────────────────────────────────────────────────
#> Juvenile survival model:
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: binomial ( logit )
#> Formula: alive3 ~ (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: juvsurv.data
#> AIC BIC logLik deviance df.resid
#> 323.9167 338.4701 -157.9583 315.9167 277
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 0.0000
#> patchid (Intercept) 0.3623
#> year2 (Intercept) 0.0000
#> Number of obs: 281, groups: individ, 187; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept)
#> 1.07
#> convergence code 0; 0 optimizer warnings; 1 lme4 warnings
#>
#> ────────────────────────────────────────
#>
#> Juvenile observation model:
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: binomial ( logit )
#> Formula: obsstatus3 ~ (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: juvobs.data
#> AIC BIC logLik deviance df.resid
#> 93.4925 106.8809 -42.7462 85.4925 206
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 16.009
#> patchid (Intercept) 0.000
#> year2 (Intercept) 1.221
#> Number of obs: 210, groups: individ, 154; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept)
#> 10.39
#> convergence code 0; 0 optimizer warnings; 1 lme4 warnings
#>
#> ────────────────────────────────────────
#>
#> Juvenile size model:
#> Linear mixed model fit by REML ['lmerMod']
#> Formula: sizea3 ~ (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: juvsize.data
#> REML criterion at convergence: 243.3232
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 0.08956
#> patchid (Intercept) 0.00000
#> year2 (Intercept) 0.09066
#> Residual 0.43789
#> Number of obs: 193, groups: individ, 144; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept)
#> 2.29
#> convergence code 0; 0 optimizer warnings; 1 lme4 warnings
#>
#> ────────────────────────────────────────
#>
#> Juvenile reproduction model:
#> [1] 0
#>
#>
#> ────────────────────────────────────────────────────────────────────────────────
#>
#> Number of models in survival table:5
#>
#> Number of models in observation table:5
#>
#> Number of models in size table:5
#>
#> Number of models in reproduction status table:5
#>
#> Number of models in fecundity table:5
#>
#> Number of models in juvenile survival table:1
#>
#> Number of models in juvenile observation table:1
#>
#> Number of models in juvenile size table:1
#>
#> Number of models in juvenile reproduction table: 1
#>
#>
#> ────────────────────────────────────────────────────────────────────────────────
#>
#> General model parameter names (column 1), and specific names used in these models (column 2):
#> mainparams modelparams
#> 1 year2 year2
#> 2 individ individ
#> 3 patch patchid
#> 4 surv3 alive3
#> 5 obs3 obsstatus3
#> 6 size3 sizea3
#> 7 repst3 repstatus3
#> 8 fec3 feca3
#> 9 fec2 feca2
#> 10 size2 sizea2
#> 11 size1 <NA>
#> 12 repst2 repstatus2
#> 13 repst1 <NA>
#> 14 age <NA>
#>
#>
#> ────────────────────────────────────────────────────────────────────────────────
#>
#> Quality control:
#>
#> Survival estimated with 257 individuals and 2246 individual transitions.
#> Observation estimated with 254 individuals and 2121 individual transitions.
#> Size estimated with 254 individuals and 1916 individual transitions.
#> Reproductive status estimated with 254 individuals and 1916 individual transitions.
#> Fecundity estimated with 101 individuals and 265 individual transitions.
#> Juvenile survival estimated with 187 individuals and 281 individual transitions.
#> Juvenile observation estimated with 154 individuals and 210 individual transitions.
#> Juvenile size estimated with 144 individuals and 193 individual transitions.
#> Juvenile reproduction probability not estimated.
#> NULL
The best-fit models vary a bit in complexity. For example, survival is influenced by size and reproductive status in the current year, as well as by patch, individual identity, and year, while observation status is not influenced by size and reproductive status. We can see these models explicitly, as well as the model tables developed, by calling them directly from the lefkoMod object. Here is the best-fit model for survival.
lathmodelsln2$survival_model
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: binomial ( logit )
#> Formula: alive3 ~ repstatus2 + sizea2 + (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: surv.data
#> AIC BIC logLik deviance df.resid
#> 916.4218 950.7233 -452.2109 904.4218 2240
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 0.4844333
#> patchid (Intercept) 0.2554894
#> year2 (Intercept) 0.0008752
#> Number of obs: 2246, groups: individ, 257; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept) repstatus2 sizea2
#> 2.0461 1.7264 0.1469
And now we move on to the historical model set. Note that this search will take more time, because the inclusion of status in time t-1 (and all two-way interactions when suite = "full"
) increases the number of models that the dredge
function will build and compare. The inclusion of these terms may also create more warnings as the function proceeds. Please also note that we include quiet = TRUE
here, which prevents the model selection protocol from issuing warnings and diagnostic messages. We do this only because model selection generates a particularly verbose list of warnings in this case. Normally it is best to stick with the default, quiet = FALSE
.
lathmodelsln3 <- modelsearch(lathvertln, historical = TRUE, approach = "lme4", suite = "full",
vitalrates = c("surv", "obs", "size", "repst", "fec"), juvestimate = "Sdl",
bestfit = "AICc&k", sizedist = "gaussian", fecdist = "poisson",
indiv = "individ", patch = "patchid", year = "year2",
year.as.random = TRUE, patch.as.random = TRUE,
show.model.tables = TRUE, quiet = TRUE)
#> Warning in modelsearch(lathvertln, historical = TRUE, approach = "lme4", : WARNING: Fecundity in time t cannot be Poisson-distributed and include 0s. Will develop fecundity models excluding all 0s. Consider adding a reproductive status variable to absorb 0 values.
#>
#> Developing global model of survival probability...
#> Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, : Model failed to converge with max|grad| = 0.00425259
#> (tol = 0.002, component 1)
#> Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, : Model is nearly unidentifiable: large eigenvalue ratio
#> - Rescale variables?
#>
#> Developing global model of observation probability...
#> Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, : Model failed to converge with max|grad| = 0.00529388
#> (tol = 0.002, component 1)
#>
#> Developing global model of size (Gaussian)...
#>
#>
#> Developing global model of the probability of reproduction...
#> Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, : Model failed to converge with max|grad| = 0.00814052
#> (tol = 0.002, component 1)
#>
#> Developing global model of fecundity (Poisson)...
#> fixed-effect model matrix is rank deficient so dropping 4 columns / coefficients
#> boundary (singular) fit: see ?isSingular
#>
#> Developing global model of juvenile survival probability...
#> boundary (singular) fit: see ?isSingular
#>
#> Developing global model of juvenile observation probability...
#> boundary (singular) fit: see ?isSingular
#>
#> Developing global model of juvenile size (Gaussian)...
#> boundary (singular) fit: see ?isSingular
#>
#> Juvenile reproduction response is constant so will not model it.
#>
#> All global models developed.
#>
#>
#> Commencing dredge of survival probability...
#>
#>
#> Commencing dredge of observation probability...
#>
#>
#> Commencing dredge of size...
#>
#>
#> Commencing dredge of reproduction probability...
#>
#>
#> Commencing dredge of fecundity...
#>
#>
#> Commencing dredge of juvenile survival probability...
#>
#>
#> Commencing dredge of juvenile observation probability...
#>
#>
#> Commencing dredge of juvenile size...
#>
#>
#> Finished dredging all vital rates.
summary(lathmodelsln3)
#> This LefkoMod object includes 8 linear models.
#> Best-fit model criterion used: AICc&k
#>
#> ────────────────────────────────────────────────────────────────────────────────
#> Survival model:
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: binomial ( logit )
#> Formula: alive3 ~ repstatus1 + repstatus2 + sizea1 + sizea2 + (1 | individ) +
#> (1 | year2) + (1 | patchid) + repstatus2:sizea2 + sizea1:sizea2
#> Data: surv.data
#> AIC BIC logLik deviance df.resid
#> 877.4442 934.6133 -428.7221 857.4442 2236
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 0.1830
#> patchid (Intercept) 0.2496
#> year2 (Intercept) 0.3926
#> Number of obs: 2246, groups: individ, 257; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept) repstatus1 repstatus2 sizea1 sizea2 repstatus2:sizea2 sizea1:sizea2
#> 1.02667 1.84052 11.69226 0.46047 0.27446 -1.43729 -0.06948
#> convergence code 0; 0 optimizer warnings; 1 lme4 warnings
#>
#> ────────────────────────────────────────
#>
#> Observation model:
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: binomial ( logit )
#> Formula: obsstatus3 ~ (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: obs.data
#> AIC BIC logLik deviance df.resid
#> 1342.9524 1365.5910 -667.4762 1334.9524 2117
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 6.46e-05
#> patchid (Intercept) 3.61e-01
#> year2 (Intercept) 0.00e+00
#> Number of obs: 2121, groups: individ, 254; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept)
#> 2.24
#> convergence code 0; 0 optimizer warnings; 1 lme4 warnings
#>
#> ────────────────────────────────────────
#>
#> Size model:
#> Linear mixed model fit by REML ['lmerMod']
#> Formula: sizea3 ~ repstatus1 + repstatus2 + sizea1 + sizea2 + (1 | individ) +
#> (1 | year2) + (1 | patchid) + repstatus1:repstatus2 + repstatus1:sizea1 + sizea1:sizea2
#> Data: size.data
#> REML criterion at convergence: 5210.081
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 0.1645
#> patchid (Intercept) 0.1144
#> year2 (Intercept) 0.4532
#> Residual 0.9168
#> Number of obs: 1916, groups: individ, 254; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept) repstatus1 repstatus2 sizea1 sizea2
#> 0.53719 -3.17885 0.46813 0.60500 0.77221
#> repstatus1:repstatus2 repstatus1:sizea1 sizea1:sizea2
#> -0.37342 0.56141 -0.09019
#>
#> ────────────────────────────────────────
#>
#> Reproductive status model:
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: binomial ( logit )
#> Formula: repstatus3 ~ repstatus1 + repstatus2 + sizea1 + sizea2 + (1 |
#> individ) + (1 | year2) + (1 | patchid) + repstatus1:sizea1 + repstatus1:sizea2 + sizea1:sizea2
#> Data: repst.data
#> AIC BIC logLik deviance df.resid
#> 1531.1029 1592.2409 -754.5515 1509.1029 1905
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 0.0001398
#> patchid (Intercept) 0.3568577
#> year2 (Intercept) 0.5723020
#> Number of obs: 1916, groups: individ, 254; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept) repstatus1 repstatus2 sizea1 sizea2 repstatus1:sizea1 repstatus1:sizea2
#> -8.21273 -0.12981 0.61747 0.39809 1.15700 0.57077 -0.55968
#> sizea1:sizea2
#> -0.05781
#>
#> ────────────────────────────────────────
#>
#> Fecundity model:
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: poisson ( log )
#> Formula: feca2 ~ repstatus1 + sizea1 + sizea2 + (1 | individ) + (1 | year2) + (1 | patchid) + repstatus1:sizea2 + sizea1:sizea2
#> Data: fec.data
#> AIC BIC logLik deviance df.resid
#> 2019.045 2051.262 -1000.522 2001.045 256
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 5.171e-01
#> patchid (Intercept) 1.316e-01
#> year2 (Intercept) 5.944e-05
#> Number of obs: 265, groups: individ, 101; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept) repstatus1 sizea1 sizea2 repstatus1:sizea2 sizea1:sizea2
#> -3.0773 -4.9828 0.7626 0.7020 0.7300 -0.1051
#> convergence code 0; 0 optimizer warnings; 1 lme4 warnings
#>
#> ────────────────────────────────────────────────────────────────────────────────
#> Juvenile survival model:
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: binomial ( logit )
#> Formula: alive3 ~ (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: juvsurv.data
#> AIC BIC logLik deviance df.resid
#> 323.9167 338.4701 -157.9583 315.9167 277
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 0.0000
#> patchid (Intercept) 0.3623
#> year2 (Intercept) 0.0000
#> Number of obs: 281, groups: individ, 187; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept)
#> 1.07
#> convergence code 0; 0 optimizer warnings; 1 lme4 warnings
#>
#> ────────────────────────────────────────
#>
#> Juvenile observation model:
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: binomial ( logit )
#> Formula: obsstatus3 ~ (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: juvobs.data
#> AIC BIC logLik deviance df.resid
#> 93.4925 106.8809 -42.7462 85.4925 206
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 16.009
#> patchid (Intercept) 0.000
#> year2 (Intercept) 1.221
#> Number of obs: 210, groups: individ, 154; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept)
#> 10.39
#> convergence code 0; 0 optimizer warnings; 1 lme4 warnings
#>
#> ────────────────────────────────────────
#>
#> Juvenile size model:
#> Linear mixed model fit by REML ['lmerMod']
#> Formula: sizea3 ~ (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: juvsize.data
#> REML criterion at convergence: 243.3232
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 0.08956
#> patchid (Intercept) 0.00000
#> year2 (Intercept) 0.09066
#> Residual 0.43789
#> Number of obs: 193, groups: individ, 144; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept)
#> 2.29
#> convergence code 0; 0 optimizer warnings; 1 lme4 warnings
#>
#> ────────────────────────────────────────
#>
#> Juvenile reproduction model:
#> [1] 0
#>
#>
#> ────────────────────────────────────────────────────────────────────────────────
#>
#> Number of models in survival table:113
#>
#> Number of models in observation table:113
#>
#> Number of models in size table:113
#>
#> Number of models in reproduction status table:113
#>
#> Number of models in fecundity table:113
#>
#> Number of models in juvenile survival table:1
#>
#> Number of models in juvenile observation table:1
#>
#> Number of models in juvenile size table:1
#>
#> Number of models in juvenile reproduction table: 1
#>
#>
#> ────────────────────────────────────────────────────────────────────────────────
#>
#> General model parameter names (column 1), and specific names used in these models (column 2):
#> mainparams modelparams
#> 1 year2 year2
#> 2 individ individ
#> 3 patch patchid
#> 4 surv3 alive3
#> 5 obs3 obsstatus3
#> 6 size3 sizea3
#> 7 repst3 repstatus3
#> 8 fec3 feca3
#> 9 fec2 feca2
#> 10 size2 sizea2
#> 11 size1 sizea1
#> 12 repst2 repstatus2
#> 13 repst1 repstatus1
#> 14 age <NA>
#>
#>
#> ────────────────────────────────────────────────────────────────────────────────
#>
#> Quality control:
#>
#> Survival estimated with 257 individuals and 2246 individual transitions.
#> Observation estimated with 254 individuals and 2121 individual transitions.
#> Size estimated with 254 individuals and 1916 individual transitions.
#> Reproductive status estimated with 254 individuals and 1916 individual transitions.
#> Fecundity estimated with 101 individuals and 265 individual transitions.
#> Juvenile survival estimated with 187 individuals and 281 individual transitions.
#> Juvenile observation estimated with 154 individuals and 210 individual transitions.
#> Juvenile size estimated with 144 individuals and 193 individual transitions.
#> Juvenile reproduction probability not estimated.
#> NULL
The summary will no doubt reveal some similarities, but also many differences. Historical models incorporate a further time step back in the global model, so some of the best-fit models will have these historical terms in them. Here, we see some of these historical terms in the models of survival, size, reproduction status, and fecundity. Note that model sets that include historical terms should not be used to create ahistorical matrices, since the coefficients in the best-fit models are estimated assuming a specific model structure. Historical vital rate models may yield biased results if used to construct ahistorical matrices.
Now we are ready to estimate matrices.
We will start by estimating the ahistorical set of matrices. Notice that we are matching the ahistorical matrix creation function, flefko2()
, with the appropriate ahistorical input, including the ahistorical lefkoMod object lathmodelsln2
.
lathmat2ln <- flefko2(stageframe = lathframeln, modelsuite = lathmodelsln2,
data = lathvertln, repmatrix = lathrepmln, overwrite = lathover2,
year.as.random = FALSE, patch.as.random = FALSE)
summary(lathmat2ln)
#>
#> This lefkoMat object contains 18 matrices.
#>
#> Each matrix is a square matrix with 21 rows and columns, and a total of 441 elements.
#> A total of 6732 survival transitions were estimated, with 374 per matrix.
#> A total of 324 fecundity transitions were estimated, with 18 per matrix.
#>
#> Vital rate modeling quality control:
#>
#> Survival estimated with 257 individuals and 2246 individual transitions.
#> Observation estimated with 254 individuals and 2121 individual transitions.
#> Size estimated with 254 individuals and 1916 individual transitions.
#> Reproductive status estimated with 254 individuals and 1916 individual transitions.
#> Fecundity estimated with 101 individuals and 265 individual transitions.
#> Juvenile survival estimated with 187 individuals and 281 individual transitions.
#> Juvenile observation estimated with 154 individuals and 210 individual transitions.
#> Juvenile size estimated with 144 individuals and 193 individual transitions.
#> Juvenile reproductive status estimated with 0 individuals and 0 individual transitions.
#> NULL
Let’s take a look at the first of these matrices.
lathmat2ln$A[[1]]
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#> [1,] 0.345 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00
#> [2,] 0.054 5.993212e-06 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00
#> [3,] 0.000 5.275532e-05 6.660145e-02 6.747293e-02 6.824391e-02 6.892390e-02 6.952198e-02 7.004678e-02 7.050631e-02 7.090794e-02
#> [4,] 0.000 9.911766e-03 7.319529e-02 3.536696e-02 1.462172e-02 5.145454e-03 1.523697e-03 3.710044e-04 7.137884e-05 1.032250e-05
#> [5,] 0.000 6.010009e-01 2.357008e-01 1.642418e-01 9.792480e-02 4.969653e-02 2.122312e-02 7.452427e-03 2.067742e-03 4.312410e-04
#> [6,] 0.000 1.979810e-01 3.104284e-01 3.119553e-01 2.682313e-01 1.963138e-01 1.209044e-01 6.122643e-02 2.449885e-02 7.368474e-03
#> [7,] 0.000 3.543206e-04 1.672185e-01 2.423391e-01 3.005029e-01 3.171746e-01 2.817071e-01 2.057324e-01 1.187183e-01 5.149412e-02
#> [8,] 0.000 3.445035e-09 3.684087e-02 7.699759e-02 1.376926e-01 2.095889e-01 2.684578e-01 2.827411e-01 2.352946e-01 1.471839e-01
#> [9,] 0.000 1.819765e-16 3.319693e-03 1.000583e-02 2.580447e-02 5.664490e-02 1.046349e-01 1.589271e-01 1.907344e-01 1.720622e-01
#> [10,] 0.000 5.222294e-26 1.223456e-04 5.318046e-04 1.977888e-03 6.261464e-03 1.668015e-02 3.653669e-02 6.323660e-02 8.226841e-02
#> [11,] 0.000 8.142014e-38 1.844173e-06 1.156041e-05 6.200564e-05 2.830828e-04 1.087541e-03 3.435446e-03 8.574931e-03 1.608805e-02
#> [12,] 0.000 6.896467e-52 1.136939e-08 1.027820e-07 7.950294e-07 5.234481e-06 2.900106e-05 1.321173e-04 4.755709e-04 1.286756e-03
#> [13,] 0.000 0.000000e+00 1.951182e-04 2.154427e-04 2.035411e-04 1.636804e-04 1.107621e-04 6.162984e-05 2.709573e-05 8.954389e-06
#> [14,] 0.000 0.000000e+00 6.283125e-04 1.000502e-03 1.363158e-03 1.580881e-03 1.542772e-03 1.237969e-03 7.849242e-04 3.740856e-04
#> [15,] 0.000 0.000000e+00 8.275154e-04 1.900319e-03 3.733903e-03 6.244878e-03 8.788904e-03 1.017070e-02 9.299875e-03 6.391878e-03
#> [16,] 0.000 0.000000e+00 4.457579e-04 1.476242e-03 4.183139e-03 1.008954e-02 2.047813e-02 3.417548e-02 4.506600e-02 4.466924e-02
#> [17,] 0.000 0.000000e+00 9.820747e-05 4.690415e-04 1.916744e-03 6.667168e-03 1.951500e-02 4.696788e-02 8.931892e-02 1.276766e-01
#> [18,] 0.000 0.000000e+00 8.849375e-06 6.095192e-05 3.592100e-04 1.801913e-03 7.606225e-03 2.640036e-02 7.240365e-02 1.492575e-01
#> [19,] 0.000 0.000000e+00 3.261393e-07 3.239561e-06 2.753312e-05 1.991815e-04 1.212530e-03 6.069336e-03 2.400490e-02 7.136479e-02
#> [20,] 0.000 0.000000e+00 4.916050e-09 7.042185e-08 8.631471e-07 9.005059e-06 7.905660e-05 5.706832e-04 3.255083e-03 1.395578e-02
#> [21,] 0.000 0.000000e+00 3.030763e-11 6.261109e-10 1.106718e-08 1.665124e-07 2.108174e-06 2.194682e-05 1.805289e-04 1.116213e-03
#> [,11] [,12] [,13] [,14] [,15] [,16] [,17] [,18] [,19]
#> [1,] 0.000000e+00 0.000000e+00 4.685856e-02 8.863230e-02 1.676468e-01 3.171015e-01 5.997931e-01 1.1345001737 2.145891e+00
#> [2,] 0.000000e+00 0.000000e+00 7.334383e-03 1.387288e-02 2.624036e-02 4.963328e-02 9.388065e-02 0.1775739402 3.358786e-01
#> [3,] 7.125841e-02 7.156380e-02 7.239488e-02 7.255136e-02 7.268701e-02 7.280453e-02 7.290631e-02 0.0729944162 7.307066e-02
#> [4,] 1.088316e-06 8.500752e-08 2.225850e-01 9.511002e-02 2.553657e-02 4.220822e-03 4.140165e-04 0.0000229322 6.910093e-07
#> [5,] 6.556894e-05 7.385989e-06 3.398051e-01 2.730113e-01 1.378279e-01 4.283432e-02 7.900103e-03 0.0008227751 4.661649e-05
#> [6,] 1.615712e-03 2.624717e-04 2.121713e-01 3.205218e-01 3.042527e-01 1.777908e-01 6.165530e-02 0.0120736633 1.286227e-03
#> [7,] 1.628366e-02 3.814862e-03 5.418335e-02 1.539065e-01 2.746972e-01 3.018209e-01 1.968025e-01 0.0724635368 1.451505e-02
#> [8,] 6.712168e-02 2.267764e-02 5.659364e-03 3.022589e-02 1.014370e-01 2.095616e-01 2.569292e-01 0.1778781219 6.699489e-02
#> [9,] 1.131608e-01 5.513651e-02 2.417641e-04 2.427860e-03 1.532009e-02 5.951095e-02 1.371888e-01 0.1785862781 1.264700e-01
#> [10,] 7.802827e-02 5.482811e-02 4.224144e-06 7.976101e-05 9.463430e-04 6.912011e-03 2.996033e-02 0.0733324475 9.764631e-02
#> [11,] 2.200546e-02 2.229923e-02 3.018618e-08 1.071717e-06 2.390884e-05 3.283482e-04 2.676067e-03 0.0123159188 3.083520e-02
#> [12,] 2.538232e-03 3.709360e-03 8.822670e-11 5.889691e-09 2.470534e-07 6.379509e-06 9.776195e-05 0.0008459798 3.982540e-03
#> [13,] 2.157374e-06 3.850767e-07 2.643274e-03 2.581024e-03 1.583609e-03 5.981386e-04 1.340732e-04 0.0000169703 1.168549e-06
#> [14,] 1.299776e-04 3.345789e-05 4.035305e-03 7.408776e-03 8.547175e-03 6.070112e-03 2.558333e-03 0.0006088704 7.883203e-05
#> [15,] 3.202832e-03 1.188974e-03 2.519608e-03 8.698080e-03 1.886773e-02 2.519498e-02 1.996617e-02 0.0089347573 2.175108e-03
#> [16,] 3.227918e-02 1.728099e-02 6.434461e-04 4.176600e-03 1.703489e-02 4.277146e-02 6.373161e-02 0.0536244963 2.454605e-02
#> [17,] 1.330556e-01 1.027277e-01 6.720691e-05 8.202474e-04 6.290450e-03 2.969727e-02 8.320274e-02 0.1316334408 1.132935e-01
#> [18,] 2.243192e-01 2.497636e-01 2.871033e-06 6.588543e-05 9.500501e-04 8.433379e-03 4.442659e-02 0.1321574909 2.138704e-01
#> [19,] 1.546758e-01 2.483666e-01 5.016318e-08 2.164495e-06 5.868591e-05 9.795108e-04 9.702213e-03 0.0542675079 1.651273e-01
#> [20,] 4.362152e-02 1.010136e-01 3.584714e-10 2.908346e-08 1.482667e-06 4.653067e-05 8.666050e-04 0.0091140313 5.214467e-02
#> [21,] 5.031549e-03 1.680308e-02 1.047723e-12 1.598300e-10 1.532061e-08 9.040491e-07 3.165877e-05 0.0006260423 6.734779e-03
#> [,20] [,21]
#> [1,] 4.058923e+00 7.677396e+00
#> [2,] 6.353097e-01 1.201679e+00
#> [3,] 7.313661e-02 7.319365e-02
#> [4,] 1.140410e-08 1.077605e-10
#> [5,] 1.446561e-06 2.570135e-08
#> [6,] 7.504732e-05 2.507117e-06
#> [7,] 1.592415e-03 1.000267e-04
#> [8,] 1.381973e-02 1.632223e-03
#> [9,] 4.905301e-02 1.089346e-02
#> [10,] 7.121218e-02 2.973546e-02
#> [11,] 4.228297e-02 3.319756e-02
#> [12,] 1.026831e-02 1.515863e-02
#> [13,] 4.407005e-08 9.516163e-10
#> [14,] 5.590097e-06 2.269645e-07
#> [15,] 2.900132e-04 2.213995e-05
#> [16,] 6.153735e-03 8.833197e-04
#> [17,] 5.340504e-02 1.441391e-02
#> [18,] 1.895607e-01 9.619843e-02
#> [19,] 2.751927e-01 2.625892e-01
#> [20,] 1.633985e-01 2.931624e-01
#> [21,] 3.968092e-02 1.338635e-01
The number of elements estimated is vastly greater now than in the previous case, because each matrix element must be estimated based on the vital rate linear models supplied. And the matrix is overwhelmingly composed of elements that are to be estimated, whereas in the raw matrix case, elements would only be estimated if individuals actually passed through that transition. These are interesting and important differences between raw and function-based matrices.
Now we will estimate the historical matrices.
lathmat3ln <- flefko3(stageframe = lathframeln, modelsuite = lathmodelsln3,
data = lathvertln, repmatrix = lathrepmln, overwrite = lathover3,
year.as.random = FALSE, patch.as.random = FALSE)
summary(lathmat3ln)
#>
#> This lefkoMat object contains 18 matrices.
#>
#> Each matrix is a square matrix with 441 rows and columns, and a total of 194481 elements.
#> A total of 130500 survival transitions were estimated, with 7250 per matrix.
#> A total of 6804 fecundity transitions were estimated, with 378 per matrix.
#>
#> Vital rate modeling quality control:
#>
#> Survival estimated with 257 individuals and 2246 individual transitions.
#> Observation estimated with 254 individuals and 2121 individual transitions.
#> Size estimated with 254 individuals and 1916 individual transitions.
#> Reproductive status estimated with 254 individuals and 1916 individual transitions.
#> Fecundity estimated with 101 individuals and 265 individual transitions.
#> Juvenile survival estimated with 187 individuals and 281 individual transitions.
#> Juvenile observation estimated with 154 individuals and 210 individual transitions.
#> Juvenile size estimated with 144 individuals and 193 individual transitions.
#> Juvenile reproductive status estimated with 0 individuals and 0 individual transitions.
#> NULL
Once again, the matrices are vastly bigger. Indeed, the ahistorical matrices here are 21 x 21, so contain 441 elements each. The historical matrices are 212 x 212 (441 x 441), or 194,481 elements large. However, because of the prevalence of structural 0s in the latter, only 7,628 elements are actually estimated. Another point of interest here is that the number of A matrices estimated is 18, which is the same as the number of ahistorical matrices. In the raw matrix case, there would actually only be 12 historical matrices estimated, because of the lack of information for the time step previous to the start of the dataset in each of the 6 patches. Here, linear modeling treating year as random allows us to make assumptions leading to estimated values for even those first transitions.
Because of the size of the matrices and the proliferation of structural zeroes, we may wish to analyze these matrices after removing some unneeded rows and columns. Let’s re-do the above, but overwrite the models with smaller matrices using the reduce = TRUE
option, which eliminates stages or stage-pairs with corresponding row and column vectors both equal to zero vectors.
lathmat3ln <- flefko3(stageframe = lathframeln, modelsuite = lathmodelsln3,
data = lathvertln, repmatrix = lathrepmln, overwrite = lathover3,
year.as.random = FALSE, patch.as.random = FALSE, reduce = TRUE)
summary(lathmat3ln)
#>
#> This lefkoMat object contains 18 matrices.
#>
#> Each matrix is a square matrix with 410 rows and columns, and a total of 168100 elements.
#> A total of 130500 survival transitions were estimated, with 7250 per matrix.
#> A total of 6804 fecundity transitions were estimated, with 378 per matrix.
#>
#> Vital rate modeling quality control:
#>
#> Survival estimated with 257 individuals and 2246 individual transitions.
#> Observation estimated with 254 individuals and 2121 individual transitions.
#> Size estimated with 254 individuals and 1916 individual transitions.
#> Reproductive status estimated with 254 individuals and 1916 individual transitions.
#> Fecundity estimated with 101 individuals and 265 individual transitions.
#> Juvenile survival estimated with 187 individuals and 281 individual transitions.
#> Juvenile observation estimated with 154 individuals and 210 individual transitions.
#> Juvenile size estimated with 144 individuals and 193 individual transitions.
#> Juvenile reproductive status estimated with 0 individuals and 0 individual transitions.
#> NULL
This exercise eliminated 31 rows and columns, so the matrices definitely got smaller.
Now the mean matrices. Note that these include 6 mean matrices for the patches, followed by a grand mean matrix, yielding a total of 7 matrices per lefkoMat object.
lathmat2lnmean <- lmean(lathmat2ln)
lathmat3lnmean <- lmean(lathmat3ln)
summary(lathmat2lnmean)
#>
#> This lefkoMat object contains 7 matrices.
#>
#> Each matrix is a square matrix with 21 rows and columns, and a total of 441 elements.
#> A total of 2618 survival transitions were estimated, with 374 per matrix.
#> A total of 126 fecundity transitions were estimated, with 18 per matrix.
#>
#> Vital rate modeling quality control:
#>
#> Survival estimated with 257 individuals and 2246 individual transitions.
#> Observation estimated with 254 individuals and 2121 individual transitions.
#> Size estimated with 254 individuals and 1916 individual transitions.
#> Reproductive status estimated with 254 individuals and 1916 individual transitions.
#> Fecundity estimated with 101 individuals and 265 individual transitions.
#> Juvenile survival estimated with 187 individuals and 281 individual transitions.
#> Juvenile observation estimated with 154 individuals and 210 individual transitions.
#> Juvenile size estimated with 144 individuals and 193 individual transitions.
#> Juvenile reproductive status estimated with 0 individuals and 0 individual transitions.
#> NULL
summary(lathmat3lnmean)
#>
#> This lefkoMat object contains 7 matrices.
#>
#> Each matrix is a square matrix with 410 rows and columns, and a total of 168100 elements.
#> A total of 50750 survival transitions were estimated, with 7250 per matrix.
#> A total of 2646 fecundity transitions were estimated, with 378 per matrix.
#>
#> Vital rate modeling quality control:
#>
#> Survival estimated with 257 individuals and 2246 individual transitions.
#> Observation estimated with 254 individuals and 2121 individual transitions.
#> Size estimated with 254 individuals and 1916 individual transitions.
#> Reproductive status estimated with 254 individuals and 1916 individual transitions.
#> Fecundity estimated with 101 individuals and 265 individual transitions.
#> Juvenile survival estimated with 187 individuals and 281 individual transitions.
#> Juvenile observation estimated with 154 individuals and 210 individual transitions.
#> Juvenile size estimated with 144 individuals and 193 individual transitions.
#> Juvenile reproductive status estimated with 0 individuals and 0 individual transitions.
#> NULL
Here we will do some quality control, checking that survival terms are probabilities. We will focus on the grand mean U matrix in each case.
writeLines("Stage survival in ahistorical grand mean matrix")
#> Stage survival in ahistorical grand mean matrix
summary(colSums(lathmat2lnmean$U[[7]]))
#> Min. 1st Qu. Median Mean 3rd Qu. Max.
#> 0.3990 0.9047 0.9529 0.9106 0.9798 0.9908
writeLines("\nStage survival in historical grand mean matrix")
#>
#> Stage survival in historical grand mean matrix
summary(colSums(lathmat3lnmean$U[[7]]))
#> Min. 1st Qu. Median Mean 3rd Qu. Max.
#> 0.0000 0.9335 0.9752 0.8845 0.9960 1.0000
Quick scans of these numbers show no real problems. Note that the spread of values is higher in the historical case - this is expected, since theoretically, the ahistorical transition values are partially determined by the historical transition values.
Now let’s estimate the deterministic population growth rate in each case. First, the ahistorical case.
lambda3(lathmat2lnmean)
#> pop patch lambda
#> 1 1 1 0.9781053
#> 2 1 2 0.9393794
#> 3 1 3 0.9672494
#> 4 1 4 0.9254900
#> 5 1 5 0.9163495
#> 6 1 6 0.9715421
#> 7 1 All 0.9499706
These lambda estimates are all less than 1.0, suggesting a declining population. They generally agree with the ahistorical lambda values from raw matrix analysis.
Now the historical case.
lambda3(lathmat3lnmean)
#> pop patch lambda
#> 1 1 1 0.9538327
#> 2 1 2 0.9355245
#> 3 1 3 0.9441902
#> 4 1 4 0.9247563
#> 5 1 5 0.9114800
#> 6 1 6 0.9613652
#> 7 1 All 0.9395367
Note that the population growth rate values are very similar, but still differ by being typically lower than in the ahistorical case. These estimates are nonetheless in line with the raw matrix estimates, giving extra support for our inferences.
Now let’s look at the stable stage distributions, as follows for the ahistorical case. Our numbers here match those produced by package popbio
’s stable.stage()
function.
stablestage3(lathmat2lnmean)
#> matrix new_stage_id orig_stage_id original_size ss_prop
#> 1 1 1 Sd 0.0 1.881459e-01
#> 2 1 2 Sdl 4.6 2.944916e-02
#> 3 1 3 Dorm 0.0 5.584916e-02
#> 4 1 4 Sz1nr 1.0 9.371157e-03
#> 5 1 5 Sz2nr 2.0 5.903780e-02
#> 6 1 6 Sz3nr 3.0 1.176055e-01
#> 7 1 7 Sz4nr 4.0 1.783122e-01
#> 8 1 8 Sz5nr 5.0 1.577991e-01
#> 9 1 9 Sz6nr 6.0 7.348274e-02
#> 10 1 10 Sz7nr 7.0 1.769478e-02
#> 11 1 11 Sz8nr 8.0 2.240615e-03
#> 12 1 12 Sz9nr 9.0 1.584348e-04
#> 13 1 13 Sz1r 1.0 1.631850e-04
#> 14 1 14 Sz2r 2.0 1.583404e-03
#> 15 1 15 Sz3r 3.0 8.531691e-03
#> 16 1 16 Sz4r 4.0 2.431401e-02
#> 17 1 17 Sz5r 5.0 3.573112e-02
#> 18 1 18 Sz6r 6.0 2.701896e-02
#> 19 1 19 Sz7r 7.0 1.077943e-02
#> 20 1 20 Sz8r 8.0 2.406804e-03
#> 21 1 21 Sz9r 9.0 3.248681e-04
#> 22 2 1 Sd 0.0 1.587367e-01
#> 23 2 2 Sdl 4.6 2.484591e-02
#> 24 2 3 Dorm 0.0 9.185077e-02
#> 25 2 4 Sz1nr 1.0 1.429599e-02
#> 26 2 5 Sz2nr 2.0 6.879313e-02
#> 27 2 6 Sz3nr 3.0 1.363503e-01
#> 28 2 7 Sz4nr 4.0 1.871750e-01
#> 29 2 8 Sz5nr 5.0 1.495998e-01
#> 30 2 9 Sz6nr 6.0 6.337542e-02
#> 31 2 10 Sz7nr 7.0 1.387553e-02
#> 32 2 11 Sz8nr 8.0 1.588103e-03
#> 33 2 12 Sz9nr 9.0 1.004512e-04
#> 34 2 13 Sz1r 1.0 1.896212e-04
#> 35 2 14 Sz2r 2.0 1.668673e-03
#> 36 2 15 Sz3r 3.0 8.230101e-03
#> 37 2 16 Sz4r 4.0 2.152120e-02
#> 38 2 17 Sz5r 5.0 2.897043e-02
#> 39 2 18 Sz6r 6.0 1.998386e-02
#> 40 2 19 Sz7r 7.0 7.224684e-03
#> 41 2 20 Sz8r 8.0 1.449352e-03
#> 42 2 21 Sz9r 9.0 1.748930e-04
#> 43 3 1 Sd 0.0 1.837008e-01
#> 44 3 2 Sdl 4.6 2.875337e-02
#> 45 3 3 Dorm 0.0 9.048364e-02
#> 46 3 4 Sz1nr 1.0 8.952089e-03
#> 47 3 5 Sz2nr 2.0 5.365401e-02
#> 48 3 6 Sz3nr 3.0 1.038459e-01
#> 49 3 7 Sz4nr 4.0 1.614449e-01
#> 50 3 8 Sz5nr 5.0 1.571293e-01
#> 51 3 9 Sz6nr 6.0 8.359084e-02
#> 52 3 10 Sz7nr 7.0 2.339529e-02
#> 53 3 11 Sz8nr 8.0 3.475970e-03
#> 54 3 12 Sz9nr 9.0 2.904142e-04
#> 55 3 13 Sz1r 1.0 8.757601e-05
#> 56 3 14 Sz2r 2.0 9.172380e-04
#> 57 3 15 Sz3r 3.0 5.573996e-03
#> 58 3 16 Sz4r 4.0 1.833316e-02
#> 59 3 17 Sz5r 5.0 3.142528e-02
#> 60 3 18 Sz6r 6.0 2.787135e-02
#> 61 3 19 Sz7r 7.0 1.308387e-02
#> 62 3 20 Sz8r 8.0 3.443219e-03
#> 63 3 21 Sz9r 9.0 5.477693e-04
#> 64 4 1 Sd 0.0 1.314603e-01
#> 65 4 2 Sdl 4.6 2.057658e-02
#> 66 4 3 Dorm 0.0 6.929174e-02
#> 67 4 4 Sz1nr 1.0 1.673655e-02
#> 68 4 5 Sz2nr 2.0 7.885646e-02
#> 69 4 6 Sz3nr 3.0 1.629647e-01
#> 70 4 7 Sz4nr 4.0 2.162106e-01
#> 71 4 8 Sz5nr 5.0 1.587475e-01
#> 72 4 9 Sz6nr 6.0 6.027742e-02
#> 73 4 10 Sz7nr 7.0 1.165071e-02
#> 74 4 11 Sz8nr 8.0 1.159083e-03
#> 75 4 12 Sz9nr 9.0 6.238557e-05
#> 76 4 13 Sz1r 1.0 2.179491e-04
#> 77 4 14 Sz2r 2.0 1.815114e-03
#> 78 4 15 Sz3r 3.0 8.217025e-03
#> 79 4 16 Sz4r 4.0 1.934699e-02
#> 80 4 17 Sz5r 5.0 2.315451e-02
#> 81 4 18 Sz6r 6.0 1.403461e-02
#> 82 4 19 Sz7r 7.0 4.394143e-03
#> 83 4 20 Sz8r 8.0 7.497552e-04
#> 84 4 21 Sz9r 9.0 7.585271e-05
#> 85 5 1 Sd 0.0 6.814044e-02
#> 86 5 2 Sdl 4.6 1.066555e-02
#> 87 5 3 Dorm 0.0 1.355584e-01
#> 88 5 4 Sz1nr 1.0 2.760034e-02
#> 89 5 5 Sz2nr 2.0 9.985475e-02
#> 90 5 6 Sz3nr 3.0 1.875725e-01
#> 91 5 7 Sz4nr 4.0 2.170160e-01
#> 92 5 8 Sz5nr 5.0 1.411566e-01
#> 93 5 9 Sz6nr 6.0 4.817148e-02
#> 94 5 10 Sz7nr 7.0 8.395602e-03
#> 95 5 11 Sz8nr 8.0 7.498238e-04
#> 96 5 12 Sz9nr 9.0 3.577518e-05
#> 97 5 13 Sz1r 1.0 2.460243e-04
#> 98 5 14 Sz2r 2.0 1.815357e-03
#> 99 5 15 Sz3r 3.0 7.405461e-03
#> 100 5 16 Sz4r 4.0 1.582923e-02
#> 101 5 17 Sz5r 5.0 1.721812e-02
#> 102 5 18 Sz6r 6.0 9.460128e-03
#> 103 5 19 Sz7r 7.0 2.666985e-03
#> 104 5 20 Sz8r 8.0 4.052406e-04
#> 105 5 21 Sz9r 9.0 3.614822e-05
#> 106 6 1 Sd 0.0 2.087820e-01
#> 107 6 2 Sdl 4.6 3.267914e-02
#> 108 6 3 Dorm 0.0 4.883234e-02
#> 109 6 4 Sz1nr 1.0 9.156222e-03
#> 110 6 5 Sz2nr 2.0 5.731673e-02
#> 111 6 6 Sz3nr 3.0 1.134842e-01
#> 112 6 7 Sz4nr 4.0 1.672876e-01
#> 113 6 8 Sz5nr 5.0 1.424037e-01
#> 114 6 9 Sz6nr 6.0 6.359486e-02
#> 115 6 10 Sz7nr 7.0 1.472073e-02
#> 116 6 11 Sz8nr 8.0 1.806382e-03
#> 117 6 12 Sz9nr 9.0 1.254904e-04
#> 118 6 13 Sz1r 1.0 2.559741e-04
#> 119 6 14 Sz2r 2.0 2.344337e-03
#> 120 6 15 Sz3r 3.0 1.191365e-02
#> 121 6 16 Sz4r 4.0 3.211996e-02
#> 122 6 17 Sz5r 5.0 4.489186e-02
#> 123 6 18 Sz6r 6.0 3.254515e-02
#> 124 6 19 Sz7r 7.0 1.259863e-02
#> 125 6 20 Sz8r 8.0 2.769492e-03
#> 126 6 21 Sz9r 9.0 3.715820e-04
#> 127 7 1 Sd 0.0 1.569461e-01
#> 128 7 2 Sdl 4.6 2.456568e-02
#> 129 7 3 Dorm 0.0 8.050336e-02
#> 130 7 4 Sz1nr 1.0 1.356824e-02
#> 131 7 5 Sz2nr 2.0 6.785779e-02
#> 132 7 6 Sz3nr 3.0 1.353549e-01
#> 133 7 7 Sz4nr 4.0 1.891132e-01
#> 134 7 8 Sz5nr 5.0 1.539022e-01
#> 135 7 9 Sz6nr 6.0 6.666413e-02
#> 136 7 10 Sz7nr 7.0 1.504208e-02
#> 137 7 11 Sz8nr 8.0 1.790251e-03
#> 138 7 12 Sz9nr 9.0 1.186776e-04
#> 139 7 13 Sz1r 1.0 1.913729e-04
#> 140 7 14 Sz2r 2.0 1.697278e-03
#> 141 7 15 Sz3r 3.0 8.429555e-03
#> 142 7 16 Sz4r 4.0 2.227727e-02
#> 143 7 17 Sz5r 5.0 3.049765e-02
#> 144 7 18 Sz6r 6.0 2.155213e-02
#> 145 7 19 Sz7r 7.0 8.041766e-03
#> 146 7 20 Sz8r 8.0 1.675608e-03
#> 147 7 21 Sz9r 9.0 2.108510e-04
The output is a dataframe with stage information and stable stage distributions for each matrix, with matrix info appended. Here, we have 7 sets of stable stage distributions because there are 7 matrices. Note that the last matrix, the 7th, is the grand mean matrix. Also note that the ss_prop
column, which gives us the stable stage proportion of each stage, sums to 1.0 within each matrix.
Now the historical case. In this case, the historical output includes 2 data frames, so we will first create an object to hold the output and then look at the first data frame. Because of the size of the output, we will first only inspect the summary.
ehrlen3ss <- stablestage3(lathmat3lnmean)
summary(ehrlen3ss$hist)
#> matrix orig_stage_id_2 orig_stage_id_1 new_stage_id_2 new_stage_id_1 ss_prop
#> Min. :1 Sz1r : 147 Sz1r : 147 Min. : 1.00 Min. : 1.00 Min. :0.000e+00
#> 1st Qu.:2 Sz2r : 147 Sz2r : 147 1st Qu.: 7.00 1st Qu.: 6.00 1st Qu.:1.320e-06
#> Median :4 Sz3r : 147 Sz3r : 147 Median :12.00 Median :12.00 Median :5.191e-05
#> Mean :4 Sz4r : 147 Sz4r : 147 Mean :11.57 Mean :11.44 Mean :2.439e-03
#> 3rd Qu.:6 Sz5r : 147 Sz5r : 147 3rd Qu.:17.00 3rd Qu.:17.00 3rd Qu.:1.049e-03
#> Max. :7 Sz6r : 147 Sz6r : 147 Max. :21.00 Max. :21.00 Max. :1.688e-01
#> (Other):1988 (Other):1988
Once again, the ss_prop
column gives the stable stage proportions, with all proportions summing to 1.0 within each matrix. There are 7 matrices, as before. Now let’s look at the first 6 entries.
head(ehrlen3ss$hist)
#> matrix orig_stage_id_2 orig_stage_id_1 new_stage_id_2 new_stage_id_1 ss_prop
#> 1 1 Sd Sd 1 1 0.12412466
#> 2 1 Sdl Sd 2 1 0.01240104
#> 3 1 Sz1r Sd 13 1 0.00000000
#> 4 1 Sz2r Sd 14 1 0.00000000
#> 5 1 Sz3r Sd 15 1 0.00000000
#> 6 1 Sz4r Sd 16 1 0.00000000
Here we see the historical portion of the stable stage distribution, where the distribution of stage pairs is given. If we focus on the $ahist
elements, we can inspect the distribution in terms of the original ahistorical stages shown in our stageframe.
ehrlen3ss$ahist
#> matrix new_stage_id ss_prop
#> 1 1 1 3.431715e-01
#> 2 1 2 4.668665e-02
#> 3 1 3 4.513709e-02
#> 4 1 4 9.651740e-03
#> 5 1 5 2.669348e-02
#> 6 1 6 6.130545e-02
#> 7 1 7 1.121241e-01
#> 8 1 8 1.342637e-01
#> 9 1 9 8.643159e-02
#> 10 1 10 2.691773e-02
#> 11 1 11 3.935510e-03
#> 12 1 12 2.789421e-04
#> 13 1 13 4.995727e-05
#> 14 1 14 4.127435e-04
#> 15 1 15 2.914118e-03
#> 16 1 16 1.335918e-02
#> 17 1 17 3.148562e-02
#> 18 1 18 3.428497e-02
#> 19 1 19 1.674244e-02
#> 20 1 20 3.747452e-03
#> 21 1 21 4.060412e-04
#> 22 2 1 4.031255e-01
#> 23 2 2 5.451682e-02
#> 24 2 3 6.260283e-02
#> 25 2 4 7.917895e-03
#> 26 2 5 1.976387e-02
#> 27 2 6 4.366234e-02
#> 28 2 7 8.044311e-02
#> 29 2 8 1.079627e-01
#> 30 2 9 8.486697e-02
#> 31 2 10 3.377438e-02
#> 32 2 11 6.494813e-03
#> 33 2 12 6.210946e-04
#> 34 2 13 2.499287e-05
#> 35 2 14 1.994046e-04
#> 36 2 15 1.460872e-03
#> 37 2 16 7.889568e-03
#> 38 2 17 2.345849e-02
#> 39 2 18 3.300310e-02
#> 40 2 19 2.106493e-02
#> 41 2 20 6.240701e-03
#> 42 2 21 9.055826e-04
#> 43 3 1 3.458617e-01
#> 44 3 2 4.690723e-02
#> 45 3 3 7.214503e-02
#> 46 3 4 1.007171e-02
#> 47 3 5 2.443709e-02
#> 48 3 6 5.210453e-02
#> 49 3 7 9.280721e-02
#> 50 3 8 1.207746e-01
#> 51 3 9 9.223091e-02
#> 52 3 10 3.565047e-02
#> 53 3 11 6.645988e-03
#> 54 3 12 6.153049e-04
#> 55 3 13 3.041982e-05
#> 56 3 14 2.356143e-04
#> 57 3 15 1.675319e-03
#> 58 3 16 8.793594e-03
#> 59 3 17 2.545132e-02
#> 60 3 18 3.485105e-02
#> 61 3 19 2.161936e-02
#> 62 3 20 6.215356e-03
#> 63 3 21 8.761948e-04
#> 64 4 1 3.169047e-01
#> 65 4 2 4.269872e-02
#> 66 4 3 5.355441e-02
#> 67 4 4 1.155071e-02
#> 68 4 5 3.154841e-02
#> 69 4 6 7.121145e-02
#> 70 4 7 1.276553e-01
#> 71 4 8 1.486132e-01
#> 72 4 9 9.153368e-02
#> 73 4 10 2.665923e-02
#> 74 4 11 3.548787e-03
#> 75 4 12 2.238348e-04
#> 76 4 13 3.875210e-05
#> 77 4 14 3.218975e-04
#> 78 4 15 2.291606e-03
#> 79 4 16 1.040757e-02
#> 80 4 17 2.370438e-02
#> 81 4 18 2.429339e-02
#> 82 4 19 1.086180e-02
#> 83 4 20 2.170732e-03
#> 84 4 21 2.074103e-04
#> 85 5 1 2.202920e-01
#> 86 5 2 2.954061e-02
#> 87 5 3 1.123768e-01
#> 88 5 4 2.147564e-02
#> 89 5 5 4.793117e-02
#> 90 5 6 8.955142e-02
#> 91 5 7 1.369203e-01
#> 92 5 8 1.499277e-01
#> 93 5 9 9.408835e-02
#> 94 5 10 2.897848e-02
#> 95 5 11 4.135503e-03
#> 96 5 12 2.820268e-04
#> 97 5 13 4.215455e-05
#> 98 5 14 2.918221e-04
#> 99 5 15 1.827672e-03
#> 100 5 16 8.188096e-03
#> 101 5 17 1.962704e-02
#> 102 5 18 2.161985e-02
#> 103 5 19 1.042486e-02
#> 104 5 20 2.245736e-03
#> 105 5 21 2.327326e-04
#> 106 6 1 4.703944e-01
#> 107 6 2 6.414496e-02
#> 108 6 3 3.096174e-02
#> 109 6 4 3.627636e-03
#> 110 6 5 1.074307e-02
#> 111 6 6 2.770400e-02
#> 112 6 7 5.856033e-02
#> 113 6 8 8.540681e-02
#> 114 6 9 7.047556e-02
#> 115 6 10 2.953059e-02
#> 116 6 11 6.102855e-03
#> 117 6 12 6.342390e-04
#> 118 6 13 2.917018e-05
#> 119 6 14 2.595710e-04
#> 120 6 15 2.045080e-03
#> 121 6 16 1.124117e-02
#> 122 6 17 3.369135e-02
#> 123 6 18 4.885998e-02
#> 124 6 19 3.318696e-02
#> 125 6 20 1.071301e-02
#> 126 6 21 1.687533e-03
#> 127 7 1 3.554215e-01
#> 128 7 2 4.813001e-02
#> 129 7 3 6.033414e-02
#> 130 7 4 9.788222e-03
#> 131 7 5 2.525450e-02
#> 132 7 6 5.534302e-02
#> 133 7 7 9.933891e-02
#> 134 7 8 1.244904e-01
#> 135 7 9 8.813344e-02
#> 136 7 10 3.102957e-02
#> 137 7 11 5.226109e-03
#> 138 7 12 4.340768e-04
#> 139 7 13 3.736719e-05
#> 140 7 14 2.950122e-04
#> 141 7 15 2.081682e-03
#> 142 7 16 1.024475e-02
#> 143 7 17 2.696373e-02
#> 144 7 18 3.333651e-02
#> 145 7 19 1.866704e-02
#> 146 7 20 4.837384e-03
#> 147 7 21 6.125666e-04
These are quite different values, showing the impact of history once again.
Now let’s take a peek at the reproductive values. Let’s start with the ahistorical case.
repvalue3(lathmat2lnmean)
#> matrix new_stage_id orig_stage_id original_size left_vector rep_value
#> 1 1 1 Sd 0.0 -0.0093086 1.00000
#> 2 1 2 Sdl 4.6 -0.1091361 11.72422
#> 3 1 3 Dorm 0.0 -0.1218352 13.08846
#> 4 1 4 Sz1nr 1.0 -0.1265912 13.59938
#> 5 1 5 Sz2nr 2.0 -0.1308276 14.05449
#> 6 1 6 Sz3nr 3.0 -0.1352596 14.53061
#> 7 1 7 Sz4nr 4.0 -0.1407320 15.11849
#> 8 1 8 Sz5nr 5.0 -0.1485907 15.96273
#> 9 1 9 Sz6nr 6.0 -0.1607791 17.27210
#> 10 1 10 Sz7nr 7.0 -0.1791343 19.24396
#> 11 1 11 Sz8nr 8.0 -0.2042151 21.93833
#> 12 1 12 Sz9nr 9.0 -0.2348132 25.22540
#> 13 1 13 Sz1r 1.0 -0.1216515 13.06872
#> 14 1 14 Sz2r 2.0 -0.1346205 14.46195
#> 15 1 15 Sz3r 3.0 -0.1440202 15.47174
#> 16 1 16 Sz4r 4.0 -0.1561432 16.77408
#> 17 1 17 Sz5r 5.0 -0.1771789 19.03389
#> 18 1 18 Sz6r 6.0 -0.2156662 23.16849
#> 19 1 19 Sz7r 7.0 -0.2839853 30.50784
#> 20 1 20 Sz8r 8.0 -0.3979948 42.75560
#> 21 1 21 Sz9r 9.0 -0.5745100 61.71820
#> 22 2 1 Sd 0.0 -0.0085603 1.00000
#> 23 2 2 Sdl 4.6 -0.0942233 11.00701
#> 24 2 3 Dorm 0.0 -0.1217071 14.21762
#> 25 2 4 Sz1nr 1.0 -0.1273014 14.87114
#> 26 2 5 Sz2nr 2.0 -0.1322164 15.44530
#> 27 2 6 Sz3nr 3.0 -0.1371606 16.02287
#> 28 2 7 Sz4nr 4.0 -0.1429382 16.69780
#> 29 2 8 Sz5nr 5.0 -0.1507929 17.61538
#> 30 2 9 Sz6nr 6.0 -0.1625369 18.98729
#> 31 2 10 Sz7nr 7.0 -0.1799528 21.02179
#> 32 2 11 Sz8nr 8.0 -0.2036953 23.79535
#> 33 2 12 Sz9nr 9.0 -0.2327676 27.19152
#> 34 2 13 Sz1r 1.0 -0.1251640 14.62145
#> 35 2 14 Sz2r 2.0 -0.1393958 16.28399
#> 36 2 15 Sz3r 3.0 -0.1494393 17.45725
#> 37 2 16 Sz4r 4.0 -0.1616564 18.88443
#> 38 2 17 Sz5r 5.0 -0.1821531 21.27882
#> 39 2 18 Sz6r 6.0 -0.2191366 25.59917
#> 40 2 19 Sz7r 7.0 -0.2847257 33.26118
#> 41 2 20 Sz8r 8.0 -0.3952030 46.16696
#> 42 2 21 Sz9r 9.0 -0.5692765 66.50193
#> 43 3 1 Sd 0.0 0.0092287 1.00000
#> 44 3 2 Sdl 4.6 0.1063434 11.52312
#> 45 3 3 Dorm 0.0 0.1323453 14.34062
#> 46 3 4 Sz1nr 1.0 0.1370689 14.85246
#> 47 3 5 Sz2nr 2.0 0.1413810 15.31971
#> 48 3 6 Sz3nr 3.0 0.1458880 15.80808
#> 49 3 7 Sz4nr 4.0 0.1513173 16.39638
#> 50 3 8 Sz5nr 5.0 0.1588757 17.21539
#> 51 3 9 Sz6nr 6.0 0.1703946 18.46355
#> 52 3 10 Sz7nr 7.0 0.1877147 20.34032
#> 53 3 11 Sz8nr 8.0 0.2114580 22.91309
#> 54 3 12 Sz9nr 9.0 0.2402843 26.03664
#> 55 3 13 Sz1r 1.0 0.1356333 14.69690
#> 56 3 14 Sz2r 2.0 0.1471408 15.94383
#> 57 3 15 Sz3r 3.0 0.1556638 16.86736
#> 58 3 16 Sz4r 4.0 0.1668619 18.08076
#> 59 3 17 Sz5r 5.0 0.1861797 20.17399
#> 60 3 18 Sz6r 6.0 0.2213535 23.98534
#> 61 3 19 Sz7r 7.0 0.2835108 30.72056
#> 62 3 20 Sz8r 8.0 0.3858049 41.80490
#> 63 3 21 Sz9r 9.0 0.5395974 58.46949
#> 64 4 1 Sd 0.0 0.0088585 1.00000
#> 65 4 2 Sdl 4.6 0.0952277 10.74987
#> 66 4 3 Dorm 0.0 0.1075667 12.14277
#> 67 4 4 Sz1nr 1.0 0.1133735 12.79827
#> 68 4 5 Sz2nr 2.0 0.1183414 13.35908
#> 69 4 6 Sz3nr 3.0 0.1231801 13.90530
#> 70 4 7 Sz4nr 4.0 0.1286661 14.52459
#> 71 4 8 Sz5nr 5.0 0.1360015 15.35266
#> 72 4 9 Sz6nr 6.0 0.1471179 16.60754
#> 73 4 10 Sz7nr 7.0 0.1643112 18.54842
#> 74 4 11 Sz8nr 8.0 0.1890406 21.34002
#> 75 4 12 Sz9nr 9.0 0.2209105 24.93769
#> 76 4 13 Sz1r 1.0 0.1102274 12.44312
#> 77 4 14 Sz2r 2.0 0.1257529 14.19573
#> 78 4 15 Sz3r 3.0 0.1366838 15.42968
#> 79 4 16 Sz4r 4.0 0.1495444 16.88146
#> 80 4 17 Sz5r 5.0 0.1710362 19.30758
#> 81 4 18 Sz6r 6.0 0.2105517 23.76832
#> 82 4 19 Sz7r 7.0 0.2828190 31.92629
#> 83 4 20 Sz8r 8.0 0.4090416 46.17504
#> 84 4 21 Sz9r 9.0 0.6157298 69.50723
#> 85 5 1 Sd 0.0 0.0109971 1.00000
#> 86 5 2 Sdl 4.6 0.1163553 10.58054
#> 87 5 3 Dorm 0.0 0.1265000 11.50303
#> 88 5 4 Sz1nr 1.0 0.1326447 12.06179
#> 89 5 5 Sz2nr 2.0 0.1375909 12.51156
#> 90 5 6 Sz3nr 3.0 0.1421082 12.92233
#> 91 5 7 Sz4nr 4.0 0.1469290 13.36070
#> 92 5 8 Sz5nr 5.0 0.1530484 13.91716
#> 93 5 9 Sz6nr 6.0 0.1620056 14.73167
#> 94 5 10 Sz7nr 7.0 0.1756537 15.97273
#> 95 5 11 Sz8nr 8.0 0.1952294 17.75281
#> 96 5 12 Sz9nr 9.0 0.2205083 20.05150
#> 97 5 13 Sz1r 1.0 0.1278988 11.63023
#> 98 5 14 Sz2r 2.0 0.1449889 13.18428
#> 99 5 15 Sz3r 3.0 0.1558450 14.17146
#> 100 5 16 Sz4r 4.0 0.1672559 15.20909
#> 101 5 17 Sz5r 5.0 0.1855927 16.87651
#> 102 5 18 Sz6r 6.0 0.2189894 19.91338
#> 103 5 19 Sz7r 7.0 0.2801751 25.47718
#> 104 5 20 Sz8r 8.0 0.3882316 35.30309
#> 105 5 21 Sz9r 9.0 0.5687726 51.72024
#> 106 6 1 Sd 0.0 -0.0086775 1.00000
#> 107 6 2 Sdl 4.6 -0.1006818 11.60263
#> 108 6 3 Dorm 0.0 -0.1293138 14.90220
#> 109 6 4 Sz1nr 1.0 -0.1349100 15.54710
#> 110 6 5 Sz2nr 2.0 -0.1399493 16.12784
#> 111 6 6 Sz3nr 3.0 -0.1452360 16.73708
#> 112 6 7 Sz4nr 4.0 -0.1517167 17.48392
#> 113 6 8 Sz5nr 5.0 -0.1607548 18.52547
#> 114 6 9 Sz6nr 6.0 -0.1739683 20.04821
#> 115 6 10 Sz7nr 7.0 -0.1924375 22.17661
#> 116 6 11 Sz8nr 8.0 -0.2159657 24.88801
#> 117 6 12 Sz9nr 9.0 -0.2432699 28.03456
#> 118 6 13 Sz1r 1.0 -0.1298007 14.95831
#> 119 6 14 Sz2r 2.0 -0.1441724 16.61451
#> 120 6 15 Sz3r 3.0 -0.1543911 17.79212
#> 121 6 16 Sz4r 4.0 -0.1670347 19.24917
#> 122 6 17 Sz5r 5.0 -0.1880006 21.66530
#> 123 6 18 Sz6r 6.0 -0.2244766 25.86881
#> 124 6 19 Sz7r 7.0 -0.2861681 32.97817
#> 125 6 20 Sz8r 8.0 -0.3853862 44.41212
#> 126 6 21 Sz9r 9.0 -0.5354320 61.70349
#> 127 7 1 Sd 0.0 -0.0092331 1.00000
#> 128 7 2 Sdl 4.6 -0.1034404 11.20321
#> 129 7 3 Dorm 0.0 -0.1228552 13.30595
#> 130 7 4 Sz1nr 1.0 -0.1282940 13.89501
#> 131 7 5 Sz2nr 2.0 -0.1330385 14.40887
#> 132 7 6 Sz3nr 3.0 -0.1378140 14.92608
#> 133 7 7 Sz4nr 4.0 -0.1434375 15.53514
#> 134 7 8 Sz5nr 5.0 -0.1511517 16.37063
#> 135 7 9 Sz6nr 6.0 -0.1627470 17.62647
#> 136 7 10 Sz7nr 7.0 -0.1799970 19.49475
#> 137 7 11 Sz8nr 8.0 -0.2035998 22.05108
#> 138 7 12 Sz9nr 9.0 -0.2326269 25.19489
#> 139 7 13 Sz1r 1.0 -0.1246999 13.50575
#> 140 7 14 Sz2r 2.0 -0.1389920 15.05367
#> 141 7 15 Sz3r 3.0 -0.1490152 16.13924
#> 142 7 16 Sz4r 4.0 -0.1611548 17.45403
#> 143 7 17 Sz5r 5.0 -0.1815559 19.66359
#> 144 7 18 Sz6r 6.0 -0.2184495 23.65939
#> 145 7 19 Sz7r 7.0 -0.2839939 30.75824
#> 146 7 20 Sz8r 8.0 -0.3944768 42.72420
#> 147 7 21 Sz9r 9.0 -0.5684214 61.56344
The actual reproductive value estimates for each stage are given in the rep_value
column, while left_vector
gives the raw estimate of the left eigenvector. As before, our rep_value
estimates are similar to those estimated by popbio
’s reproductive.value()
function. Let’s now see the historical case.
repvalue3(lathmat3lnmean)$ahist
#> matrix new_stage_id rep_value
#> 1 1 1 0.0000000
#> 2 1 2 0.0000000
#> 3 1 3 1.0000000
#> 4 1 4 0.7910218
#> 5 1 5 1.0746154
#> 6 1 6 1.2528820
#> 7 1 7 1.3627822
#> 8 1 8 1.4331109
#> 9 1 9 1.4858740
#> 10 1 10 1.5286939
#> 11 1 11 1.5599571
#> 12 1 12 1.5764432
#> 13 1 13 0.5750740
#> 14 1 14 1.0878492
#> 15 1 15 1.3361227
#> 16 1 16 1.4562043
#> 17 1 17 1.5410861
#> 18 1 18 1.6125352
#> 19 1 19 1.6690674
#> 20 1 20 1.6845727
#> 21 1 21 1.5716529
#> 22 2 1 0.0000000
#> 23 2 2 0.0000000
#> 24 2 3 1.0000000
#> 25 2 4 0.7356918
#> 26 2 5 1.0281724
#> 27 2 6 1.2272192
#> 28 2 7 1.3707489
#> 29 2 8 1.4694925
#> 30 2 9 1.5412040
#> 31 2 10 1.5972138
#> 32 2 11 1.6359628
#> 33 2 12 1.6512848
#> 34 2 13 0.6398936
#> 35 2 14 1.1327220
#> 36 2 15 1.3869774
#> 37 2 16 1.5285658
#> 38 2 17 1.6338745
#> 39 2 18 1.7246220
#> 40 2 19 1.7934204
#> 41 2 20 1.7964149
#> 42 2 21 1.6078216
#> 43 3 1 0.0000000
#> 44 3 2 0.0000000
#> 45 3 3 1.0000000
#> 46 3 4 0.7809720
#> 47 3 5 1.0582846
#> 48 3 6 1.2344472
#> 49 3 7 1.3554119
#> 50 3 8 1.4363396
#> 51 3 9 1.4941010
#> 52 3 10 1.5388676
#> 53 3 11 1.5699129
#> 54 3 12 1.5822983
#> 55 3 13 0.6336615
#> 56 3 14 1.1120766
#> 57 3 15 1.3488961
#> 58 3 16 1.4745877
#> 59 3 17 1.5628010
#> 60 3 18 1.6358331
#> 61 3 19 1.6903963
#> 62 3 20 1.6929726
#> 63 3 21 1.5386759
#> 64 4 1 0.0000000
#> 65 4 2 0.0000000
#> 66 4 3 1.0000000
#> 67 4 4 0.7379277
#> 68 4 5 1.0837291
#> 69 4 6 1.3366772
#> 70 4 7 1.5046732
#> 71 4 8 1.6133600
#> 72 4 9 1.6955682
#> 73 4 10 1.7655073
#> 74 4 11 1.8204607
#> 75 4 12 1.8529690
#> 76 4 13 0.6029710
#> 77 4 14 1.1961092
#> 78 4 15 1.5171367
#> 79 4 16 1.6881609
#> 80 4 17 1.8174880
#> 81 4 18 1.9332236
#> 82 4 19 2.0301875
#> 83 4 20 2.0577493
#> 84 4 21 1.8679942
#> 85 5 1 0.0000000
#> 86 5 2 0.0000000
#> 87 5 3 1.0000000
#> 88 5 4 0.7839311
#> 89 5 5 1.1491141
#> 90 5 6 1.4122916
#> 91 5 7 1.5994936
#> 92 5 8 1.7241809
#> 93 5 9 1.8136755
#> 94 5 10 1.8871640
#> 95 5 11 1.9455280
#> 96 5 12 1.9811771
#> 97 5 13 0.6512977
#> 98 5 14 1.2452280
#> 99 5 15 1.5877127
#> 100 5 16 1.7840125
#> 101 5 17 1.9280533
#> 102 5 18 2.0517701
#> 103 5 19 2.1541426
#> 104 5 20 2.1847148
#> 105 5 21 1.9819227
#> 106 6 1 0.0000000
#> 107 6 2 0.0000000
#> 108 6 3 1.0000000
#> 109 6 4 0.7343774
#> 110 6 5 0.9790652
#> 111 6 6 1.1366463
#> 112 6 7 1.2440490
#> 113 6 8 1.3172870
#> 114 6 9 1.3710932
#> 115 6 10 1.4104508
#> 116 6 11 1.4339592
#> 117 6 12 1.4392481
#> 118 6 13 0.5932177
#> 119 6 14 1.0361464
#> 120 6 15 1.2423493
#> 121 6 16 1.3491708
#> 122 6 17 1.4283311
#> 123 6 18 1.4931146
#> 124 6 19 1.5364795
#> 125 6 20 1.5299903
#> 126 6 21 1.3906730
#> 127 7 1 0.0000000
#> 128 7 2 0.0000000
#> 129 7 3 1.0000000
#> 130 7 4 0.7576028
#> 131 7 5 1.0563296
#> 132 7 6 1.2585219
#> 133 7 7 1.3968972
#> 134 7 8 1.4890043
#> 135 7 9 1.5567689
#> 136 7 10 1.6108335
#> 137 7 11 1.6497190
#> 138 7 12 1.6684094
#> 139 7 13 0.6113696
#> 140 7 14 1.1271787
#> 141 7 15 1.3922411
#> 142 7 16 1.5338667
#> 143 7 17 1.6380644
#> 144 7 18 1.7273210
#> 145 7 19 1.7970124
#> 146 7 20 1.8091411
#> 147 7 21 1.6477342
Once again, we see strong differences here. We leave it to the reader to consider the importance of such differences.
In this analysis, we will build an integral projection model. This is essentially a form of function-based matrix, but one in which size must be modeled as Gaussian, and in which the size distribution is broken up into many fine-scale classes or size bins. Although the number of these bins varies from analysis to analysis, package lefko3
uses a default of 100 (this can be changed as an option). Note also that, because of the high dimensionality of IPMs, we will not create a historical version. The ahistorical version under the default setting will have at least 10,000 elements per matrix (dimensions of 100 by 100 at minimum), while a historical version would have at least 100,000,000 (dimensions of 10,000 by 10,000).
To begin, we need to create a stageframe for this dataset, in which we identify the key stages used in analysis. We will base all of this on Ehrlén (2000), but modify the size bits to allow IPM construction and make all mature stages other than vegetative dormancy reproductive.
In the stageframe code below, we show that we want an IPM by choosing two stages that serve as the size limits for IPM size classification. These two size classes should have exactly the same characteristics in the stageframe other than size. We mark these in the vector that we load into the stagenames
option using the string ipm
. Package lefko3
will then rename all IPM size classes according to its own conventions. Although we leave the number of size classes to the default setting here (100 bins), we may alter that using the ipmbins
option, for example by setting ipmbins = 25
, which would create 25 IPM size classes rather than 100.
sizevector <- c(0, 100, 0, 1, 7100)
stagevector <- c("Sd", "Sdl", "Dorm", "ipm", "ipm")
repvector <- c(0, 0, 0, 1, 1)
obsvector <- c(0, 1, 0, 1, 1)
matvector <- c(0, 0, 1, 1, 1)
immvector <- c(1, 1, 0, 0, 0)
propvector <- c(1, 0, 0, 0, 0)
indataset <- c(0, 1, 1, 1, 1)
binvec <- c(0, 100, 0.5, 1, 1)
lathframeipm <- sf_create(sizes = sizevector, stagenames = stagevector, repstatus = repvector,
obsstatus = obsvector, matstatus = matvector, immstatus = immvector,
indataset = indataset, binhalfwidth = binvec, propstatus = propvector)
We will also add some descriptive comments to this stageframe so that we know what each of these stages is.
A look at this stageframe shows that the IPM portion technically starts with the fourth stage and keeps going until the 103rd stage. Stage names within this range are concatenations of the central size (designated with “sz”), reproductive status (designated with “rp”), maturity status (designated with “mt”), and observation status (designated with “ob”). The first three stages, which fall outside of the IPM classification, are left unaltered.
To work with this dataset, we first need to format the data into ‘vertical’ format, in which each row corresponds to the state of a single individual in two (if ahistorical) or three (if historical) consecutive time intervals. Because this is an IPM, we will need to estimate linear models of vital rates, and that will require that NAs are avoided in key terms used in estimation. For this purpose, we will set NAas0 = TRUE
. We will also set NRasRep = TRUE
because there are mature individuals that do not reproduce that we wish to include in reproductive stages (setting this option to TRUE makes sure that the reproductive status of non-reproductive individuals is set to 1, although the actual fecundity is not altered).
lathvertipm <- verticalize3(lathyrus, noyears = 4, firstyear = 1988, patchidcol = "SUBPLOT",
individcol = "GENET", blocksize = 9, juvcol = "Seedling1988",
size1col = "Volume88", repstr1col = "FCODE88",
fec1col = "Intactseed88", dead1col = "Dead1988",
nonobs1col = "Dormant1988", stageassign = lathframeipm,
stagesize = "sizea", censorcol = "Missing1988",censorkeep = NA,
censor = TRUE, NAas0 = TRUE, NRasRep = TRUE)
Voila! Now we move on to create the extra bits of information needed for matrix estimation.
Now we will provide some given transitions. This is the same overwrite object as used before in ahistorical matrix estimation.
lathover2 <- overwrite(stage3 = c("Sd", "Sdl"), stage2 = c("Sd", "Sd"), givenrate = c(0.345, 0.054))
We will also create a reproductive matrix, which describes not only which stages are reproductive, but which stages they lead to the reproduction of, and at what level. This matrix is composed mostly of 0s, but fecundity is noted as non-zero entries equal to a scalar multiplier to the full fecundity estimated by R. This matrix has rows and columns equal to the number of stages described in the stageframe for this dataset, and the rows and columns refer to these stages in the same order as in the stageframe. In many ways, it looks like a nearly empty population matrix, but notes the per-individual mean modifiers on fecundity for each stage that actually reproduces. Here, we first create a 0 matrix with dimensions equal to the number of rows in lathframeipm
. Then we modify elements corresponding to fecundity by the expected mean seed dormancy probability (row 1), and by the germination rate (row 2).
Let’s now use the same rounding procedure as in Analysis 2 for fecundity in our vertical dataset, since we know that fecundity is all integers except for 6 data points that were estimated differently from the rest. Then we will take a peek at the degree to which 0s exist in fecundity.
lathvertipm$feca2 <- round(lathvertipm$feca2)
lathvertipm$feca1 <- round(lathvertipm$feca1)
lathvertipm$feca3 <- round(lathvertipm$feca3)
summary(subset(lathvertipm, repstatus2 == 1)$feca2)
#> Min. 1st Qu. Median Mean 3rd Qu. Max.
#> 0.000 0.000 0.000 4.791 6.000 66.000
length(subset(lathvertipm, repstatus2 == 1)$feca2)
#> [1] 599
length(which(subset(lathvertipm, repstatus2 == 1)$feca2 > 0))
#> [1] 265
Over half of reproductive individuals do not actually reproduce in this example. Under these circumstances, we will not be able to use the Poisson or negative binomial distribution to model fecundity, and so must rely on the Gaussian.
Integral projection models (IPMs) require functions of vital rates to populate them. Here, we will develop these functions as linear models using modelsearch
. This looks similar to the modelsearch
call in the last example, but differs in that we are not including models of reproductive status. Note that we will only create ahistorical models, since IPMs already have high dimensionality.
lathmodels2ipm <- modelsearch(lathvertipm, historical = FALSE, approach = "lme4", suite = "size",
vitalrates = c("surv", "obs", "size", "fec"), juvestimate = "Sdl",
bestfit = "AICc&k", sizedist = "gaussian", fecdist = "gaussian",
indiv = "individ", patch = "patchid", year = "year2",
year.as.random = TRUE, patch.as.random = TRUE,
show.model.tables = TRUE)
#>
#> Developing global model of survival probability...
#> boundary (singular) fit: see ?isSingular
#>
#> Developing global model of observation probability...
#> boundary (singular) fit: see ?isSingular
#>
#> Developing global model of size (Gaussian)...
#> boundary (singular) fit: see ?isSingular
#>
#> Developing global model of fecundity (Gaussian)...
#>
#>
#> Developing global model of juvenile survival probability...
#> boundary (singular) fit: see ?isSingular
#>
#> Developing global model of juvenile observation probability...
#> boundary (singular) fit: see ?isSingular
#>
#> Developing global model of juvenile size (Gaussian)...
#>
#>
#> All global models developed.
#>
#>
#> Commencing dredge of survival probability...
#> Fixed term is "(Intercept)"
#> boundary (singular) fit: see ?isSingular
#>
#> Commencing dredge of observation probability...
#> Fixed term is "(Intercept)"
#> boundary (singular) fit: see ?isSingular
#> boundary (singular) fit: see ?isSingular
#>
#> Commencing dredge of size...
#> Warning in dredge(size.global.model, rank = used.criterion): comparing models fitted by REML
#> Fixed term is "(Intercept)"
#> boundary (singular) fit: see ?isSingular
#>
#> Commencing dredge of fecundity...
#> Warning in dredge(fec.global.model, rank = used.criterion): comparing models fitted by REML
#> Fixed term is "(Intercept)"
#>
#> Commencing dredge of juvenile survival probability...
#> Fixed term is "(Intercept)"
#> boundary (singular) fit: see ?isSingular
#>
#> Commencing dredge of juvenile observation probability...
#> Fixed term is "(Intercept)"
#> boundary (singular) fit: see ?isSingular
#>
#> Commencing dredge of juvenile size...
#> Warning in dredge(juv.size.global.model, rank = used.criterion): comparing models fitted by REML
#> Fixed term is "(Intercept)"
#>
#> Finished dredging all vital rates.
#> boundary (singular) fit: see ?isSingular
#> boundary (singular) fit: see ?isSingular
#> boundary (singular) fit: see ?isSingular
#> boundary (singular) fit: see ?isSingular
#> boundary (singular) fit: see ?isSingular
Now we can take a look at the summary of these models.
summary(lathmodels2ipm)
#> This LefkoMod object includes 7 linear models.
#> Best-fit model criterion used: AICc&k
#>
#> ────────────────────────────────────────────────────────────────────────────────
#> Survival model:
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: binomial ( logit )
#> Formula: alive3 ~ sizea2 + (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: surv.data
#> AIC BIC logLik deviance df.resid
#> 932.6720 961.2565 -461.3360 922.6720 2241
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 5.335e-01
#> patchid (Intercept) 2.526e-01
#> year2 (Intercept) 4.008e-05
#> Number of obs: 2246, groups: individ, 257; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept) sizea2
#> 2.492457 0.001195
#> convergence code 0; 0 optimizer warnings; 1 lme4 warnings
#>
#> ────────────────────────────────────────
#>
#> Observation model:
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: binomial ( logit )
#> Formula: obsstatus3 ~ (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: obs.data
#> AIC BIC logLik deviance df.resid
#> 1342.9524 1365.5910 -667.4762 1334.9524 2117
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 6.46e-05
#> patchid (Intercept) 3.61e-01
#> year2 (Intercept) 0.00e+00
#> Number of obs: 2121, groups: individ, 254; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept)
#> 2.24
#> convergence code 0; 0 optimizer warnings; 1 lme4 warnings
#>
#> ────────────────────────────────────────
#>
#> Size model:
#> Linear mixed model fit by REML ['lmerMod']
#> Formula: sizea3 ~ sizea2 + (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: size.data
#> REML criterion at convergence: 29285.58
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 0.00
#> patchid (Intercept) 57.13
#> year2 (Intercept) 210.37
#> Residual 502.47
#> Number of obs: 1916, groups: individ, 254; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept) sizea2
#> 176.0197 0.6113
#> convergence code 0; 0 optimizer warnings; 1 lme4 warnings
#>
#> ────────────────────────────────────────
#>
#> Reproductive status model:
#> [1] 1
#>
#> ────────────────────────────────────────
#>
#> Fecundity model:
#> Linear mixed model fit by REML ['lmerMod']
#> Formula: feca2 ~ sizea2 + (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: fec.data
#> REML criterion at convergence: 12785.56
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 0.7014
#> patchid (Intercept) 0.1560
#> year2 (Intercept) 0.9831
#> Residual 4.0913
#> Number of obs: 2246, groups: individ, 257; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept) sizea2
#> -0.500957 0.003189
#>
#> ────────────────────────────────────────────────────────────────────────────────
#> Juvenile survival model:
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: binomial ( logit )
#> Formula: alive3 ~ (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: juvsurv.data
#> AIC BIC logLik deviance df.resid
#> 323.9167 338.4701 -157.9583 315.9167 277
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 0.0000
#> patchid (Intercept) 0.3623
#> year2 (Intercept) 0.0000
#> Number of obs: 281, groups: individ, 187; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept)
#> 1.07
#> convergence code 0; 0 optimizer warnings; 1 lme4 warnings
#>
#> ────────────────────────────────────────
#>
#> Juvenile observation model:
#> Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
#> Family: binomial ( logit )
#> Formula: obsstatus3 ~ (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: juvobs.data
#> AIC BIC logLik deviance df.resid
#> 93.4925 106.8809 -42.7462 85.4925 206
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 16.009
#> patchid (Intercept) 0.000
#> year2 (Intercept) 1.221
#> Number of obs: 210, groups: individ, 154; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept)
#> 10.39
#> convergence code 0; 0 optimizer warnings; 1 lme4 warnings
#>
#> ────────────────────────────────────────
#>
#> Juvenile size model:
#> Linear mixed model fit by REML ['lmerMod']
#> Formula: sizea3 ~ (1 | individ) + (1 | year2) + (1 | patchid)
#> Data: juvsize.data
#> REML criterion at convergence: 1303.003
#> Random effects:
#> Groups Name Std.Dev.
#> individ (Intercept) 0.988829
#> patchid (Intercept) 0.001148
#> year2 (Intercept) 1.182503
#> Residual 6.997522
#> Number of obs: 193, groups: individ, 144; patchid, 6; year2, 3
#> Fixed Effects:
#> (Intercept)
#> 11.02
#>
#> ────────────────────────────────────────
#>
#> Juvenile reproduction model:
#> [1] 1
#>
#>
#> ────────────────────────────────────────────────────────────────────────────────
#>
#> Number of models in survival table:2
#>
#> Number of models in observation table:2
#>
#> Number of models in size table:2
#>
#> Number of models in reproduction status table: 1
#>
#> Number of models in fecundity table:2
#>
#> Number of models in juvenile survival table:1
#>
#> Number of models in juvenile observation table:1
#>
#> Number of models in juvenile size table:1
#>
#> Number of models in juvenile reproduction table: 1
#>
#>
#> ────────────────────────────────────────────────────────────────────────────────
#>
#> General model parameter names (column 1), and specific names used in these models (column 2):
#> mainparams modelparams
#> 1 year2 year2
#> 2 individ individ
#> 3 patch patchid
#> 4 surv3 alive3
#> 5 obs3 obsstatus3
#> 6 size3 sizea3
#> 7 repst3 repstatus3
#> 8 fec3 feca3
#> 9 fec2 feca2
#> 10 size2 sizea2
#> 11 size1 <NA>
#> 12 repst2 repstatus2
#> 13 repst1 <NA>
#> 14 age <NA>
#>
#>
#> ────────────────────────────────────────────────────────────────────────────────
#>
#> Quality control:
#>
#> Survival estimated with 257 individuals and 2246 individual transitions.
#> Observation estimated with 254 individuals and 2121 individual transitions.
#> Size estimated with 254 individuals and 1916 individual transitions.
#> Reproduction probability not estimated.
#> Fecundity estimated with 257 individuals and 2246 individual transitions.
#> Juvenile survival estimated with 187 individuals and 281 individual transitions.
#> Juvenile observation estimated with 154 individuals and 210 individual transitions.
#> Juvenile size estimated with 144 individuals and 193 individual transitions.
#> Juvenile reproduction probability not estimated.
#> NULL
Let’s move on now to the matrices themselves.
We will now create the suite of matrices covering the patches and years of study. Note that we will use the negfec = TRUE
option. This option prevents fecundity estimates added to the matrix to be negative - a situation that can happen when fecundity is treated as Gaussian.
lathmat2ipm <- flefko2(stageframe = lathframeipm, repmatrix = lathrepmipm,
modelsuite = lathmodels2ipm, overwrite = lathover2,
data = lathvertipm, year.as.random = FALSE,
patch.as.random = FALSE, reduce = FALSE, negfec = TRUE)
summary(lathmat2ipm)
#>
#> This lefkoMat object contains 18 matrices.
#>
#> Each matrix is a square matrix with 103 rows and columns, and a total of 10609 elements.
#> A total of 183744 survival transitions were estimated, with 10208 per matrix.
#> A total of 3500 fecundity transitions were estimated, with 194.444444444444 per matrix.
#>
#> Vital rate modeling quality control:
#>
#> Survival estimated with 257 individuals and 2246 individual transitions.
#> Observation estimated with 254 individuals and 2121 individual transitions.
#> Size estimated with 254 individuals and 1916 individual transitions.
#> Reproductive status estimated with 0 individuals and 0 individual transitions.
#> Fecundity estimated with 257 individuals and 2246 individual transitions.
#> Juvenile survival estimated with 187 individuals and 281 individual transitions.
#> Juvenile observation estimated with 154 individuals and 210 individual transitions.
#> Juvenile size estimated with 144 individuals and 193 individual transitions.
#> Juvenile reproductive status estimated with 0 individuals and 0 individual transitions.
#> NULL
One thing to note is that the IPM is a large matrix with most elements estimated. This makes it likely to become overparameterized if the total sample size in the dataset and the number of stages needed are not properly considered. For example, here survival is estimated based on data for 257 individuals, yielding 2246 individual transitions actually used in modeling, while each matrix includes over 10,000 estimated elements, most of which are survival-transitions. Caution is advised.
Let’s take a look at the top-left corner of the first matrix (the matrix is too huge to inspect in full here).
lathmat2ipm$A[[1]][1:25,1:5]
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 0.345 0.000000e+00 0.000000000 0.000000000 0.000000000
#> [2,] 0.054 0.000000e+00 0.000000000 0.000000000 0.000000000
#> [3,] 0.000 5.275532e-05 0.068921955 0.069104601 0.069448221
#> [4,] 0.000 6.460949e-03 0.044432976 0.043642179 0.041859393
#> [5,] 0.000 3.809264e-41 0.046893560 0.046345169 0.045003371
#> [6,] 0.000 1.557213e-124 0.048502331 0.048232982 0.047417512
#> [7,] 0.000 4.413636e-253 0.049164752 0.049195526 0.048963711
#> [8,] 0.000 0.000000e+00 0.048841243 0.049175491 0.049550894
#> [9,] 0.000 0.000000e+00 0.047551192 0.048174104 0.049144001
#> [10,] 0.000 0.000000e+00 0.045370932 0.046250900 0.047767347
#> [11,] 0.000 0.000000e+00 0.042426367 0.043517965 0.045502324
#> [12,] 0.000 0.000000e+00 0.038880836 0.040129021 0.042479329
#> [13,] 0.000 0.000000e+00 0.034920237 0.036265227 0.038865436
#> [14,] 0.000 0.000000e+00 0.030736922 0.032119135 0.034849060
#> [15,] 0.000 0.000000e+00 0.026514621 0.027879124 0.030623894
#> [16,] 0.000 0.000000e+00 0.022415687 0.023715704 0.026373719
#> [17,] 0.000 0.000000e+00 0.018572080 0.019771278 0.022259949
#> [18,] 0.000 0.000000e+00 0.015080323 0.016153814 0.018412747
#> [19,] 0.000 0.000000e+00 0.012000587 0.012934725 0.014926389
#> [20,] 0.000 0.000000e+00 0.009359145 0.010150352 0.011858581
#> [21,] 0.000 0.000000e+00 0.007153382 0.007806324 0.009233201
#> [22,] 0.000 0.000000e+00 0.005358319 0.005883746 0.007045531
#> [23,] 0.000 0.000000e+00 0.003933573 0.004346132 0.005268861
#> [24,] 0.000 0.000000e+00 0.002830009 0.003146253 0.003861550
#> [25,] 0.000 0.000000e+00 0.001995400 0.002232164 0.002773627
This matrix is very large, of course, so is difficult to read properly. We can get another handle on quality control by checking the column sums of the first U matrix, to make sure that all column sums look like survival probabilities.
summary(colSums(lathmat2ipm$U[[1]]))
#> Min. 1st Qu. Median Mean 3rd Qu. Max.
#> 0.006514 0.985215 0.998926 0.955025 0.999878 0.999986
Everything looks OK, with stage survival probabilities within the realm of possibility.
Let’s estimate the mean IPM matrices. This code will estimate mean matrices for each of the 6 patches, followed by a grand mean, yielding 7 matrices in ther lefkoMat object.
lathipmmean <- lmean(lathmat2ipm)
summary(lathipmmean)
#>
#> This lefkoMat object contains 7 matrices.
#>
#> Each matrix is a square matrix with 103 rows and columns, and a total of 10609 elements.
#> A total of 71456 survival transitions were estimated, with 10208 per matrix.
#> A total of 1400 fecundity transitions were estimated, with 200 per matrix.
#>
#> Vital rate modeling quality control:
#>
#> Survival estimated with 257 individuals and 2246 individual transitions.
#> Observation estimated with 254 individuals and 2121 individual transitions.
#> Size estimated with 254 individuals and 1916 individual transitions.
#> Reproductive status estimated with 0 individuals and 0 individual transitions.
#> Fecundity estimated with 257 individuals and 2246 individual transitions.
#> Juvenile survival estimated with 187 individuals and 281 individual transitions.
#> Juvenile observation estimated with 154 individuals and 210 individual transitions.
#> Juvenile size estimated with 144 individuals and 193 individual transitions.
#> Juvenile reproductive status estimated with 0 individuals and 0 individual transitions.
#> NULL
As a final check, let’s take a look at the column sums of the grand mean survival-transition matrix.
colSums(lathipmmean$U[[7]])
#> [1] 0.399000000 0.005977678 0.613658417 0.628472850 0.657372823 0.685359009 0.712283439 0.738018790 0.762459857 0.785524309
#> [11] 0.807152859 0.827308770 0.845976883 0.863162122 0.878887668 0.893192808 0.906130623 0.917765549 0.928170944 0.937426695
#> [21] 0.945616968 0.952828119 0.959146838 0.964658526 0.969445937 0.973588076 0.977159361 0.980229019 0.982860707 0.985112323
#> [31] 0.987035995 0.988678200 0.990079995 0.991277339 0.992301459 0.993179270 0.993933794 0.994584594 0.995148187 0.995638442
#> [41] 0.996066943 0.996443329 0.996775592 0.997070344 0.997333046 0.997568210 0.997779568 0.997970214 0.998142723 0.998299249
#> [51] 0.998441606 0.998571331 0.998689737 0.998797956 0.998896971 0.998987642 0.999070729 0.999146906 0.999216778 0.999280885
#> [61] 0.999339717 0.999393718 0.999443291 0.999488803 0.999530591 0.999568960 0.999604191 0.999636542 0.999666249 0.999693528
#> [71] 0.999718578 0.999741580 0.999762703 0.999782099 0.999799910 0.999816266 0.999831285 0.999845077 0.999857741 0.999869370
#> [81] 0.999880049 0.999889854 0.999898859 0.999907127 0.999914719 0.999921691 0.999928092 0.999933971 0.999939368 0.999944325
#> [91] 0.999948876 0.999953055 0.999956891 0.999960414 0.999963648 0.999966616 0.999969339 0.999971835 0.999974122 0.999976213
#> [101] 0.999978119 0.999979848 0.999981402
summary(colSums(lathipmmean$U[[7]]))
#> Min. 1st Qu. Median Mean 3rd Qu. Max.
#> 0.005978 0.975374 0.998571 0.945247 0.999838 0.999981
All looks fine!
Now let’s estimate the deterministic population growth rate for the IPM analysis.
lambda3(lathipmmean)
#> pop patch lambda
#> 1 1 1 0.8220400
#> 2 1 2 0.8232120
#> 3 1 3 0.8145404
#> 4 1 4 0.7820070
#> 5 1 5 0.7796077
#> 6 1 6 0.8720003
#> 7 1 All 0.8165723
Now let’s look at the stable stage distribution. We will only look at the summary and first 6 entries, given the size of the output.
summary(stablestage3(lathipmmean))
#> matrix new_stage_id orig_stage_id original_size ss_prop
#> Min. :1 Min. : 1 Length:721 Min. : 0 Min. :0.0000000
#> 1st Qu.:2 1st Qu.: 26 Class :character 1st Qu.:1606 1st Qu.:0.0000000
#> Median :4 Median : 52 Mode :character Median :3461 Median :0.0000008
#> Mean :4 Mean : 52 Mean :3465 Mean :0.0097087
#> 3rd Qu.:6 3rd Qu.: 78 3rd Qu.:5316 3rd Qu.:0.0051016
#> Max. :7 Max. :103 Max. :7100 Max. :0.5546522
head(stablestage3(lathipmmean))
#> matrix new_stage_id orig_stage_id original_size ss_prop
#> 1 1 1 Sd 0.00000 0.53067472
#> 2 1 2 Sdl 100.00000 0.08306213
#> 3 1 3 Dorm 0.00000 0.03344793
#> 4 1 4 sz35.85354 rp1 mt1 ob1 35.85354 0.01362008
#> 5 1 5 sz107.20855 rp1 mt1 ob1 107.20855 0.01428832
#> 6 1 6 sz178.56356 rp1 mt1 ob1 178.56356 0.01553735
The stable stage distribution appears to be dominated by dormant seeds, followed by seedlings, and adults get progressively less common as they get larger. The importance of the seed bank to the population is quite clear!
Finally, the reproductive values.
summary(repvalue3(lathipmmean))
#> matrix new_stage_id orig_stage_id original_size left_vector rep_value
#> Min. :1 Min. : 1 Length:721 Min. : 0 Min. :-0.13439 Min. : 1
#> 1st Qu.:2 1st Qu.: 26 Class :character 1st Qu.:1606 1st Qu.:-0.11129 1st Qu.:2415
#> Median :4 Median : 52 Mode :character Median :3461 Median :-0.08421 Median :3121
#> Mean :4 Mean : 52 Mean :3465 Mean :-0.04033 Mean :2921
#> 3rd Qu.:6 3rd Qu.: 78 3rd Qu.:5316 3rd Qu.: 0.06039 3rd Qu.:3584
#> Max. :7 Max. :103 Max. :7100 Max. : 0.12604 Max. :4481
head(repvalue3(lathipmmean))
#> matrix new_stage_id orig_stage_id original_size left_vector rep_value
#> 1 1 1 Sd 0.00000 -0.00003397 1.000000
#> 2 1 2 Sdl 100.00000 -0.00030006 8.833088
#> 3 1 3 Dorm 0.00000 -0.03623054 1066.545187
#> 4 1 4 sz35.85354 rp1 mt1 ob1 35.85354 -0.03734351 1099.308508
#> 5 1 5 sz107.20855 rp1 mt1 ob1 107.20855 -0.03955389 1164.377097
#> 6 1 6 sz178.56356 rp1 mt1 ob1 178.56356 -0.04176376 1229.430674
A quick scan through these values shows that the highest reproductive values are for the largest adults, all the way at the bottom of the data frame output. Since these values have been scaled to the contribution of dormant seed, the reproductive values show the important contribution of large adults to the maintenance of the population. These results also showcase the importance of the underlying assumptions going into population analyses - our IPM made a number of assumptions that were different from the two other analyses conducted. Most important is likely to be the inclusion of fecundity as Gaussian, to deal with the presence of 0 values. We leave it to the reader to explore the possible reasons for the differences.
The project resulting in this package and this tutorial was funded by Grant-In-Aid 19H03298 from the Japan Society for the Promotion of Science.
Bartoń, Kamil A. 2014. “MuMIn: Multi-Model Inference.” https://CRAN.R-project.org/package=MuMIn.
Bates, Douglas, Martin Maechler, Ben Bolker, and Steve Walker. 2015. “Fitting Linear Mixed-Effects Models Using Lme4.” Journal of Statistical Software 67 (1): 1–48. https://doi.org/10.18637/jss.v067.i01.
Burnham, Kenneth P., and David R. Anderson. 2002. Model Selection and Multimodel Inference: A Practical Information-Theoretic Approach. New York, New York, USA: Springer-Verlag New York, Inc.
Ehrlén, Johan. 1995. “Demography of the Perennial Herb Lathyrus Vernus. I. Herbivory and Individual Performance.” Journal of Ecology 83 (2): 287–95. https://doi.org/10.2307/2261567.
———. 2000. “The Dynamics of Plant Populations: Does the History of Individuals Matter?” Ecology 81 (6): 1675–84. https://doi.org/10.1890/0012-9658(2000)081[1675:TDOPPD]2.0.CO;2.
———. 2002. “Assessing the Lifetime Consequences of Plant-Animal Interactions for the Perennial Herb Lathyrus Vernus (Fabaceae).” Perspectives in Plant Ecology, Evolution and Systematics 5 (3): 145–63. https://doi.org/10.1078/1433-8319-00031.
Ehrlén, Johan, and Ove Eriksson. 1996. “Seedling Recruitment in the Perennial Herb Lathyrus Vernus.” Flora 191 (4): 377–83. https://doi.org/10.1016/S0367-2530(17)30744-2.
Ehrlén, Johan, and Kari Lehtilä. 2002. “How Perennal Are Perennial Plants?” Oikos 98: 308–22. https://doi.org/10.1034/j.1600-0706.2002.980212.x.
Ehrlén, Johan, and Zuzana Münzbergová. 2009. “Timing of Flowering: Opposed Selection on Different Fitness Components and Trait Covariation.” The American Naturalist 173 (6): 819–30. https://doi.org/10.1086/598492.
Ehrlén, Johan, and Jan Van Groenendael. 2001. “Storage and the Delayed Costs of Reproduction in the Understorey Perennial Lathyrus Vernus.” Journal of Ecology 89 (2): 237–46. https://doi.org/10.1046/j.1365-2745.2001.00546.x.
Shefferson, Richard P., and Deborah A. Roach. 2010. “Longitudinal Analysis of Plantago: Adaptive Benefits of Iteroparity in a Short-Lived, Herbaceous Perennial.” Ecology 91 (2): 441–47. https://doi.org/10.1890/09-0423.1.
Shefferson, Richard P., Robert J. Warren II, and H. Ronald Pulliam. 2014. “Life History Costs Make Perfect Sprouting Maladaptive in Two Herbaceous Perennials.” Journal of Ecology 102 (5): 1318–28. https://doi.org/10.1111/1365-2745.12281.