This vignette explains how to interpret the demographic quantities
produced by StablePopulation. The package reconstructs
survivorship profiles at the species level and derives quantities that
can later be connected to ecological or paleobiological questions such
as age structure, mortality structure, and potential biomass flow.
The package does not itself calculate ecosystem biomass or predator resources. It provides the demographic layer needed before those later steps.
The constrained reconstruction starts from a fertility schedule
mx. For a given Weibull shape parameter beta,
the corresponding scale parameter alpha is solved so
that
\[ \sum_x l_x m_x = 1. \]
mx <- c(0, 0, 0.30, 0.75, 0.60, 0.20)
reconstruction <- reconstruct_population(
fertility_rates = mx,
beta = 1.20
)
knitr::kable(reconstruction$table, digits = 4)| age | fertility_rates | lx | lxmx |
|---|---|---|---|
| 0 | 0.00 | 1.0000 | 0.0000 |
| 1 | 0.00 | 0.8642 | 0.0000 |
| 2 | 0.30 | 0.7151 | 0.2145 |
| 3 | 0.75 | 0.5796 | 0.4347 |
| 4 | 0.60 | 0.4629 | 0.2777 |
| 5 | 0.20 | 0.3654 | 0.0731 |
The reconstructed lx is cumulative survivorship to each
class. It starts at one and declines with age.
RThe stable structure is the normalised age distribution implied by the survivorship profile:
\[ R_x = \frac{l_x}{\sum_x l_x}. \]
profile <- derive_demographic_profile(
lx = reconstruction$lx,
fertility_rates = mx
)
knitr::kable(
profile$table[, c("age", "lx", "stable_structure")],
digits = 4
)| age | lx | stable_structure |
|---|---|---|
| 0 | 1.0000 | 0.2508 |
| 1 | 0.8642 | 0.2167 |
| 2 | 0.7151 | 0.1794 |
| 3 | 0.5796 | 0.1454 |
| 4 | 0.4629 | 0.1161 |
| 5 | 0.3654 | 0.0916 |
R sums to one and can be read as the expected proportion
of individuals in each class under the reconstructed stationary
structure.
Biologically, classes with high R are classes expected
to be abundant in the standing population, not necessarily classes
producing the most deaths or the most births.
DThe raw mortality profile is derived from the stable structure:
\[ D_x = R_x - R_{x+1}, \]
with the final class closed by setting
D_last = R_last.
| age | stable_structure | mortality_profile |
|---|---|---|
| 0 | 0.2508 | 0.0341 |
| 1 | 0.2167 | 0.0374 |
| 2 | 0.1794 | 0.0340 |
| 3 | 0.1454 | 0.0293 |
| 4 | 0.1161 | 0.0245 |
| 5 | 0.0916 | 0.0916 |
D describes the exit-by-death profile from the stable
structure. It is not simply 1 - lx, and it is not the same
as the relative death distribution. Its sum equals the first value of
R.
This distinction matters when moving from demographic reconstruction
to resource-flow questions. The raw D keeps the scale
implied by the stable structure.
D_relativeThe relative mortality profile is a separately normalised version of
D:
\[ D^{rel}_x = \frac{D_x}{\sum_x D_x}. \]
knitr::kable(
profile$table[, c("age", "mortality_profile", "mortality_profile_relative")],
digits = 4
)| age | mortality_profile | mortality_profile_relative |
|---|---|---|
| 0 | 0.0341 | 0.1358 |
| 1 | 0.0374 | 0.1491 |
| 2 | 0.0340 | 0.1355 |
| 3 | 0.0293 | 0.1167 |
| 4 | 0.0245 | 0.0975 |
| 5 | 0.0916 | 0.3654 |
D_relative sums to one.
It is useful when the question concerns the relative age distribution of deaths, independently of the scale of the stable age structure.
BConditional survival between consecutive classes is
\[ B_x = \frac{l_{x+1}}{l_x}. \]
| age | lx | conditional_survival |
|---|---|---|
| 0 | 1.0000 | 0.8642 |
| 1 | 0.8642 | 0.8275 |
| 2 | 0.7151 | 0.8105 |
| 3 | 0.5796 | 0.7986 |
| 4 | 0.4629 | 0.7894 |
| 5 | 0.3654 | NA |
B is returned as NA where the ratio is
undefined. It should be interpreted as survival from one class to the
next, not as cumulative survival from birth. Cumulative survival is
lx.
lxmxWhen fertility is supplied, the table also contains
lxmx, the contribution of each class to net
replacement.
| age | fertility_rates | lx | lxmx |
|---|---|---|---|
| 0 | 0.00 | 1.0000 | 0.0000 |
| 1 | 0.00 | 0.8642 | 0.0000 |
| 2 | 0.30 | 0.7151 | 0.2145 |
| 3 | 0.75 | 0.5796 | 0.4347 |
| 4 | 0.60 | 0.4629 | 0.2777 |
| 5 | 0.20 | 0.3654 | 0.0731 |
In the constrained reconstruction, the total of lxmx is
numerically one. This is the stationary-population condition imposed by
the reconstruction.
When observed survivorship is available, select_beta()
chooses the constrained candidate closest to it.
lx_observed <- c(1.0000000, 0.8480619, 0.7023945, 0.5759026, 0.4689639, 0.3798816)
selection <- select_beta(
fertility_rates = mx,
lx_observed = lx_observed,
beta_values = seq(0.50, 1.80, by = 0.05)
)
selection$best_beta
#> [1] 1.1
selection$best_RMSE
#> [1] 2.901736e-08
knitr::kable(selection$best_profile, digits = 4)| age | fertility_rates | lx_observed | lx_reconstructed | residual | squared_error | lxmx |
|---|---|---|---|---|---|---|
| 0 | 0.00 | 1.0000 | 1.0000 | 0 | 0 | 0.0000 |
| 1 | 0.00 | 0.8481 | 0.8481 | 0 | 0 | 0.0000 |
| 2 | 0.30 | 0.7024 | 0.7024 | 0 | 0 | 0.2107 |
| 3 | 0.75 | 0.5759 | 0.5759 | 0 | 0 | 0.4319 |
| 4 | 0.60 | 0.4690 | 0.4690 | 0 | 0 | 0.2814 |
| 5 | 0.20 | 0.3799 | 0.3799 | 0 | 0 | 0.0760 |
The selected profile is constrained by R0 = 1. It is the
best grid candidate among the supplied beta values, not a free
two-parameter optimum.
When observed lx is unavailable,
scan_beta() should be interpreted as a scenario
generator.
scan <- scan_beta(
fertility_rates = mx,
beta_values = seq(0.50, 1.80, by = 0.10),
terminal_window = c(0.10, 0.40)
)
knitr::kable(scan$admissible_summary, digits = 4)| beta | alpha | R0 | residual | lx_terminal | stable | terminal_admissible | admissible | status | |
|---|---|---|---|---|---|---|---|---|---|
| 6 | 1.0 | 5.3754 | 1 | 0 | 0.3945 | TRUE | TRUE | TRUE | converged |
| 7 | 1.1 | 5.1505 | 1 | 0 | 0.3799 | TRUE | TRUE | TRUE | converged |
| 8 | 1.2 | 4.9715 | 1 | 0 | 0.3654 | TRUE | TRUE | TRUE | converged |
| 9 | 1.3 | 4.8259 | 1 | 0 | 0.3509 | TRUE | TRUE | TRUE | converged |
| 10 | 1.4 | 4.7053 | 1 | 0 | 0.3366 | TRUE | TRUE | TRUE | converged |
| 11 | 1.5 | 4.6040 | 1 | 0 | 0.3225 | TRUE | TRUE | TRUE | converged |
| 12 | 1.6 | 4.5179 | 1 | 0 | 0.3085 | TRUE | TRUE | TRUE | converged |
| 13 | 1.7 | 4.4439 | 1 | 0 | 0.2947 | TRUE | TRUE | TRUE | converged |
| 14 | 1.8 | 4.3796 | 1 | 0 | 0.2810 | TRUE | TRUE | TRUE | converged |
A terminal window defines an admissible set of scenarios. It does not provide a single fitted curve. Downstream ecological interpretations should therefore preserve the scenario logic rather than reporting one arbitrary beta as if it had been estimated from observed survival data.
The main columns answer different biological questions.
| Quantity | Biological reading |
|---|---|
lx |
Cumulative survivorship to each class. |
R / stable_structure |
Expected standing age structure under the reconstructed stationary profile. |
D / mortality_profile |
Raw age-specific exits by death from that structure. |
D_relative |
Relative distribution of deaths across age classes. |
B / conditional_survival |
Survival from one class to the next. |
lxmx |
Class contribution to net replacement. |
For paleobiological applications, the most important point is that the package separates the reconstruction of a survivorship profile from its demographic interpretation. The Weibull model supplies a smooth survivorship structure; the derived quantities translate that structure into age distribution, death profile, and fertility contribution.
RDD_relativeBlxmx