Generate a complete life table directly from the fitted parameters of a
parametric mortality model. This function evaluates the mortality law at
the given ages and passes the resulting death rates (mx) or death
probabilities (qx) to LifeTable for further
computation of all standard life-table columns (lx, dx,
Lx, Tx, ex, etc.).
Arguments
- x
Numeric vector of ages at the beginning of each age interval. For a full life table, use single-year ages (e.g.,
0:110). For an abridged life table, use the lower bound of each interval (e.g.,c(0, 1, 5, 10, ..., 110)).- par
The parameters of the mortality model. Can be:
A numeric vector containing the coefficients (for a single life table).
A numeric matrix or data.frame where each row corresponds to a separate set of parameters (producing multiple life tables). Column names must match the parameter names of the chosen law, as described in the details below.
- law
The name of the mortality law to be used (e.g.,
"gompertz","makeham"). RunavailableLawsto see all options.- sex
Sex of the population. Options are
NULL(default),"male","female", or"total". When specified, the first two entries of theaxcolumn are adjusted using Coale-Demeny coefficients, producing more accurate life-table values at the youngest ages. The adjustment differs slightly between males and females.- lx0
Radix, the starting population (or probability scale) at age 0. Default is
100,000. All subsequent life-table columns (lx,dx,Lx,Tx) are scaled accordingly.- ax
The average number of person-years lived in each age interval by those who die in it, given either as values or as the method that produces them. Accepts two forms:
a numeric scalar or vector: a scalar is applied to all intervals, a vector must have the same length as
x. A common assumption isax = 0.5, which places deaths at the midpoint of each interval;a method name, one of
"andreev_kingkade"(the default),"cfm","preston"or"coale_demeny"(see below).
"andreev_kingkade"follows the rule the Human Mortality Database applies to its period life tables (Methods Protocol, version 6, section 7.1): the Andreev-Kingkade (2015) formula sets the value for the first year of life fromm0, every other closed interval uses half its length (n/2), and the open interval uses1/mx. It is the most accurate of the four methods and the one that reproduces the published HMD life tables most closely. Because it produces a numericaxbefore the rates are converted, themxtoqxstep uses the exact identityqx = n*mx/(1 + (n - ax)*mx), which is the identity the protocol uses (equation 74). The Andreev-Kingkade value is a property of a one-year first interval that starts at birth, so when the first interval is wider or the table starts above age 0 the interval keeps the ordinary midpoint value instead.The other three methods share the same basis, the standard lifetable identity
ax = n + 1/m - n/qunder a constant force of mortality (Preston, Heuveline and Guillot 2001, eq. 3.15), and differ in how they treat the first two intervals:"cfm": the identity alone, for every interval;"preston": the identity, with the first two intervals replaced by the Coale-Demeny West separation factors published by Preston et al. (2001), table 3.3, whensexis given;"coale_demeny": the identity, with the first two intervals replaced by the original 1983 Coale-Demeny rule expressed inqx, reproduced by the PAS software, whensexis given.
"preston"and"coale_demeny"agree exactly oncemx[1]reaches 0.107, and differ by at most a few thousandths of a year below it. Both coincide with"cfm"whensexisNULL."cfm"and the Coale-Demeny variants adjustaxafter the rates have been converted, so they leave the constant force of mortality conversion in place; only"andreev_kingkade"changes the conversion itself.A value supplied for the open age interval is kept as given. Everybody alive there dies in that interval, so its own rate implies what the average time lived in it should be (
1/mx); a value that differs is reported and left alone, which leaves theaxandmxcolumns of the table disagreeing at that age, or the model-implied value whencloseis set. The one exception is a table entered fromex, where the curve being inverted fixes that interval. SeeDetails.
Value
An object of class "LifeTable" containing the following
components:
- lt
A
data.framewith the complete life table, including columns for age interval (x.int), exact age (x), death rate (mx), death probability (qx), person-years lived by decedents (ax), survivorship (lx), death distribution (dx), person-years lived (Lx), total person-years remaining (Tx), and life expectancy (ex).- call
The matched function call.
- process_date
Timestamp of when the life table was computed.
Details
This function is designed to work with models that have been fitted
externally (e.g., via MortalityLaw or by hand). The
par argument must contain the estimated coefficients of the
mortality law, and law must be one of the valid codes listed by
availableLaws.
The ax argument is passed straight to LifeTable; its
default, "andreev_kingkade", is the rule the Human Mortality
Database applies to its period life tables (Methods Protocol, version 6;
see LifeTable for the alternatives). Because a law is
evaluated on a possibly scaled age vector, the first interval is only
treated as a one-year interval with the Andreev-Kingkade rule when the
ages passed in x really start one year apart.
Important caveat: age scaling during fitting
Several mortality laws (e.g., Gompertz, Makeham) internally scale
the age vector during optimisation to ensure numerical stability. If the
model was fitted using MortalityLaw over an age range [a, b],
the published coefficients correspond to the scaled ages, not the
original ages. Consequently, LawTable will only produce valid life
tables for ages \(\ge a\) (the lower bound of the fitting range).
Attempting to use the same coefficients at younger ages will yield
incorrect results (e.g., life expectancy at age 25 will equal that at
age 45).
To determine which models apply age scaling, run:
A <- availableLaws()$table
A[, c("CODE", "SCALE_X")]Models with SCALE_X = TRUE rescale the age vector internally. When
using LawTable with such a model, make sure the x argument
starts from the same lower age bound used during fitting.
For models that do not scale (e.g., Heligman-Pollard "HP"),
this limitation does not apply, and LawTable can be used for any
age range.
Matching the coefficients to the model parameters
The coefficients supplied in par are matched to the parameters of
the chosen law by name and in any order. For a matrix or a
data.frame the column names must therefore be the parameter names of that
law (e.g. c("A", "B", "C") for "makeham"); the row names are
used as the labels of the resulting life tables and must be supplied. An
unnamed vector keeps the positional convention, i.e. the coefficients are
read in the order in which the parameters are documented for the law.
See also
LifeTable for constructing life tables from raw mortality
data;
MortalityLaw for fitting parametric mortality models;
availableLaws for the list of implemented laws and their
scaling behaviour.
Examples
# Example 1 --- Makeham --- multiple life tables from a matrix of parameters
x1 <- 45:100
L1 <- "makeham"
C1 <- matrix(
c(0.00717, 0.07789, 0.00363,
0.01018, 0.07229, 0.00001,
0.00298, 0.09585, 0.00002,
0.00067, 0.11572, 0.00078),
nrow = 4,
dimnames = list(1:4, c("A", "B", "C"))
)
LawTable(x = x1, par = C1, law = L1)
#>
#> Full Life Tables
#>
#> Number of life tables: 4
#> Dimension: 224 x 11
#> Age intervals: [45,46) [46,47) [47,48) ... ... [98,99) [99,100) [100,+)
#>
#> LT x.int x mx qx ax lx dx Lx Tx ex
#> 1 [45,46) 45 0.0077 0.0077 0.5 1e+05 770 99615 2755138 27.55
#> 1 [46,47) 46 0.0083 0.0083 0.5 99230 821 98820 2655523 26.76
#> 1 [47,48) 47 0.0089 0.0089 0.5 98409 875 97972 2556703 25.98
#> 1 [48,49) 48 0.0096 0.0095 0.5 97535 931 97069 2458731 25.21
#> 1 [49,50) 49 0.0103 0.0103 0.5 96604 991 96108 2361662 24.45
#> 1 [50,51) 50 0.0111 0.011 0.5 95613 1054 95086 2265554 23.7
#> <NA> <NA> ... ... ... ... ... ... ... ... ...
#> 4 [98,99) 98 1.8022 0.948 0.5 0 0 0 0 0.55
#> 4 [99,100) 99 1.9834 0.9958 0.5 0 0 0 0 0.5
#> 4 [100,+) 100 2.1828 1 0.46 0 0 0 0 0.46
# ---- Important note on age scaling ----
# The Makeham model applies internal age scaling during fitting.
# If the coefficients above were estimated over ages 45-100, the life
# table produced by LawTable is valid only from age 45 onward.
# ---- Example 1B: correct usage ----
LawTable(x = x1, par = c(0.00717, 0.07789, 0.00363), law = L1)
#>
#> Full Life Table
#>
#> Number of life tables: 1
#> Dimension: 56 x 10
#> Age intervals: [45,46) [46,47) [47,48) ... ... [98,99) [99,100) [100,+)
#>
#> x.int x mx qx ax lx dx Lx Tx ex
#> [45,46) 45 0.0114 0.0113 0.5 1e+05 1132 99434 2486699 24.87
#> [46,47) 46 0.012 0.0119 0.5 98868 1180 98278 2387264 24.15
#> [47,48) 47 0.0127 0.0126 0.5 97688 1232 97072 2288986 23.43
#> [48,49) 48 0.0134 0.0133 0.5 96457 1286 95814 2191914 22.72
#> [49,50) 49 0.0142 0.0141 0.5 95171 1343 94499 2096100 22.02
#> [50,51) 50 0.0151 0.015 0.5 93827 1404 93126 2001601 21.33
#> <NA> ... ... ... ... ... ... ... ... ...
#> [98,99) 98 0.4847 0.3901 0.5 231 90 186 442 1.92
#> [99,100) 99 0.5236 0.415 0.5 141 58 111 257 1.83
#> [100,+) 100 0.5658 1 1.77 82 82 145 145 1.77
# ---- Example 1C: incorrect usage ----
# The code below uses the same coefficients but starts at age 25.
# Because the model was fitted on scaled ages (starting at 45),
# the life table at age 25 will be meaningless (e.g., e25 equals e45).
LawTable(x = 25:100, par = c(0.00717, 0.07789, 0.00363), law = L1)
#>
#> Full Life Table
#>
#> Number of life tables: 1
#> Dimension: 76 x 10
#> Age intervals: [25,26) [26,27) [27,28) ... ... [98,99) [99,100) [100,+)
#>
#> x.int x mx qx ax lx dx Lx Tx ex
#> [25,26) 25 0.0114 0.0113 0.5 1e+05 1132 99434 2486687 24.87
#> [26,27) 26 0.012 0.0119 0.5 98868 1180 98278 2387253 24.15
#> [27,28) 27 0.0127 0.0126 0.5 97688 1232 97072 2288975 23.43
#> [28,29) 28 0.0134 0.0133 0.5 96457 1286 95814 2191902 22.72
#> [29,30) 29 0.0142 0.0141 0.5 95171 1343 94499 2096089 22.02
#> [30,31) 30 0.0151 0.015 0.5 93827 1404 93126 2001590 21.33
#> <NA> ... ... ... ... ... ... ... ... ...
#> [98,99) 98 2.2878 1 0.44 0 0 0 0 0
#> [99,100) 99 2.4728 1 0.4 0 0 0 0 0
#> [100,+) 100 2.6729 1 0.37 0 0 0 0 0
# ---- How to check which laws apply scaling ----
A <- availableLaws()$table
A[, c("CODE", "SCALE_X")]
#> CODE SCALE_X
#> 1 demoivre FALSE
#> 2 gompertz TRUE
#> 3 gompertz0 TRUE
#> 4 invgompertz TRUE
#> 5 makeham TRUE
#> 6 makeham0 TRUE
#> 7 opperman FALSE
#> 8 thiele FALSE
#> 9 neggompertz FALSE
#> 10 wittstein FALSE
#> 11 steffensen TRUE
#> 12 perks TRUE
#> 13 weibull FALSE
#> 14 pareto_2 FALSE
#> 15 invweibull TRUE
#> 16 vandermaen TRUE
#> 17 vandermaen2 TRUE
#> 18 strehler_mildvan TRUE
#> 19 quadratic TRUE
#> 20 beard TRUE
#> 21 beard_makeham TRUE
#> 22 ggompertz TRUE
#> 23 siler FALSE
#> 24 HP FALSE
#> 25 HP2 FALSE
#> 26 HP3 FALSE
#> 27 HP4 FALSE
#> 28 rogersplanck FALSE
#> 29 martinelle FALSE
#> 30 makeham_logquad TRUE
#> 31 gompertz_logquad TRUE
#> 32 carriere1 TRUE
#> 33 carriere2 TRUE
#> 34 kostaki FALSE
#> 35 kannisto TRUE
#> 36 kannisto_makeham TRUE
#> 37 scholey_shifted_power FALSE
#> 38 scholey FALSE
# Example 2 --- Heligman-Pollard (no scaling) ---
x2 <- 0:110
L2 <- "HP"
C2 <- c(0.00223, 0.01461, 0.12292, 0.00091,
2.75201, 29.01877, 0.00002, 1.11411)
LawTable(x = x2, par = C2, law = L2)
#> 'qx' is not closed at the last age; it has been set to 1. That is the usual way to close a life table and is applied here, so closing the input yourself is optional.
#>
#> Full Life Table
#>
#> Number of life tables: 1
#> Dimension: 111 x 10
#> Age intervals: [0,1) [1,2) [2,3) ... ... [108,109) [109,110) [110,+)
#>
#> x.int x mx qx ax lx dx Lx Tx ex
#> [0,1) 0 0.0264 0.0258 0.13 1e+05 2580 97760 7118840 71.19
#> [1,2) 1 0.0022 0.0022 0.5 97420 217 97312 7021080 72.07
#> [2,3) 2 0.0013 0.0013 0.5 97203 127 97140 6923768 71.23
#> [3,4) 3 9e-04 9e-04 0.5 97076 92 97030 6826629 70.32
#> [4,5) 4 7e-04 7e-04 0.5 96984 72 96948 6729599 69.39
#> [5,6) 5 6e-04 6e-04 0.5 96912 60 96882 6632651 68.44
#> <NA> ... ... ... ... ... ... ... ... ...
#> [108,109) 108 1.0784 0.7006 0.5 0 0 0 0 0.91
#> [109,110) 109 1.1318 0.7228 0.5 0 0 0 0 0.87
#> [110,+) 110 1.1845 1 0.84 0 0 0 0 0.84
# Because "HP" does NOT scale the age vector, the output is valid for
# any starting age. Compare:
LawTable(x = 3:110, par = C2, law = L2)
#> 'qx' is not closed at the last age; it has been set to 1. That is the usual way to close a life table and is applied here, so closing the input yourself is optional.
#>
#> Full Life Table
#>
#> Number of life tables: 1
#> Dimension: 108 x 10
#> Age intervals: [3,4) [4,5) [5,6) ... ... [108,109) [109,110) [110,+)
#>
#> x.int x mx qx ax lx dx Lx Tx ex
#> [3,4) 3 9e-04 9e-04 0.5 1e+05 95 99953 7032264 70.32
#> [4,5) 4 7e-04 7e-04 0.5 99905 74 99868 6932312 69.39
#> [5,6) 5 6e-04 6e-04 0.5 99831 62 99800 6832443 68.44
#> [6,7) 6 5e-04 5e-04 0.5 99769 53 99743 6732643 67.48
#> [7,8) 7 5e-04 5e-04 0.5 99716 47 99692 6632901 66.52
#> [8,9) 8 4e-04 4e-04 0.5 99669 43 99647 6533208 65.55
#> <NA> ... ... ... ... ... ... ... ... ...
#> [108,109) 108 1.0784 0.7006 0.5 0 0 0 0 0.91
#> [109,110) 109 1.1318 0.7228 0.5 0 0 0 0 0.87
#> [110,+) 110 1.1845 1 0.84 0 0 0 0 0.84
# Note that e3 = 70.31 in both tables, confirming consistency.