Building a Life Table
build_lifetable.Rmd
In this article we will walk through the steps of creating a life table from input deaths and population data, including how to extend a life table to a higher open age interval using an iterative method.
Loading data
We begin by loading data for a single location-year. As an example, we will use USA males in 2000 in 5-year age groups from HMD, initially collapsed to a lower open age interval to show the effects of extension later
lt_id_cols <- c("hmd_loc_id", "year", "source_type", "sex")
id_cols <- c(lt_id_cols, "age_start", "age_end")
open_age <- 110
lt <- collapse_open_age(
lifeTableProcessing::hmd_vr_pop_usa_males_2000,
open_age = 70
)
We will also load regression parameters created from HMD life tables so that we can create an initial set of life table parameters at higher ages to iterate
coef_qx_diff <- lifeTableProcessing::hmd_extension_qx_diff
coef_ax_mx <- lifeTableProcessing::hmd_extension_ax_mx
coef_ax_qx <- lifeTableProcessing::hmd_extension_ax_qx
Inital Life Table
From deaths and population, we can create an initial life table using naive assumptions about \(a_x\):
lt[, mx := deaths / population]
lt[, ax := (age_end - age_start) / 2]
demCore::gen_u5_ax_from_mx(lt, id_cols)
#> Rows with age not 0-1 or 1-4 will not be assigned ax values.
lt[is.infinite(age_end), ax := demCore::mx_to_ax(mx, age_end - age_start)]
lt[, qx := demCore::mx_ax_to_qx(mx, ax, age_end - age_start)]
demCore::gen_lx_from_qx(lt, id_cols)
demCore::gen_dx_from_lx(lt, id_cols)
source_type | hmd_loc_id | year | sex | age_start | age_end | deaths | population | mx | ax | qx | lx | dx |
---|---|---|---|---|---|---|---|---|---|---|---|---|
VR | USA | 2000 | male | 0 | 1 | 15729.83 | 1958928 | 0.0080298 | 0.066552 | 0.0079701 | 1.0000000 | 0.0079701 |
VR | USA | 2000 | male | 1 | 5 | 2823.68 | 7841313 | 0.0003601 | 1.628388 | 0.0014392 | 0.9920299 | 0.0014277 |
VR | USA | 2000 | male | 5 | 10 | 1847.44 | 10516497 | 0.0001757 | 2.500000 | 0.0008780 | 0.9906022 | 0.0008697 |
VR | USA | 2000 | male | 10 | 15 | 2553.61 | 10466468 | 0.0002440 | 2.500000 | 0.0012192 | 0.9897325 | 0.0012066 |
VR | USA | 2000 | male | 15 | 20 | 9699.37 | 10381688 | 0.0009343 | 2.500000 | 0.0046605 | 0.9885259 | 0.0046070 |
VR | USA | 2000 | male | 20 | 25 | 13378.28 | 9630209 | 0.0013892 | 2.500000 | 0.0069220 | 0.9839188 | 0.0068106 |
VR | USA | 2000 | male | 25 | 30 | 12621.08 | 9813310 | 0.0012861 | 2.500000 | 0.0064100 | 0.9771082 | 0.0062632 |
VR | USA | 2000 | male | 30 | 35 | 15276.72 | 10341599 | 0.0014772 | 2.500000 | 0.0073589 | 0.9708449 | 0.0071443 |
VR | USA | 2000 | male | 35 | 40 | 23255.66 | 11350590 | 0.0020489 | 2.500000 | 0.0101920 | 0.9637006 | 0.0098221 |
VR | USA | 2000 | male | 40 | 45 | 34060.31 | 11082786 | 0.0030733 | 2.500000 | 0.0152492 | 0.9538785 | 0.0145458 |
VR | USA | 2000 | male | 45 | 50 | 45127.00 | 9810326 | 0.0045999 | 2.500000 | 0.0227383 | 0.9393327 | 0.0213588 |
VR | USA | 2000 | male | 50 | 55 | 55291.46 | 8491794 | 0.0065112 | 2.500000 | 0.0320344 | 0.9179739 | 0.0294067 |
VR | USA | 2000 | male | 55 | 60 | 64450.41 | 6438883 | 0.0100096 | 2.500000 | 0.0488260 | 0.8885672 | 0.0433852 |
VR | USA | 2000 | male | 60 | 65 | 78920.52 | 5123319 | 0.0154042 | 2.500000 | 0.0741648 | 0.8451820 | 0.0626827 |
VR | USA | 2000 | male | 65 | 70 | 103967.33 | 4398992 | 0.0236344 | 2.500000 | 0.1115790 | 0.7824993 | 0.0873105 |
VR | USA | 2000 | male | 70 | Inf | 698575.26 | 9786764 | 0.0713796 | 14.009480 | 1.0000000 | 0.6951888 | 0.6951888 |
Then we can achieve better estimates of \(a_x\) by recalculating \(a_x\) from \(d_x\), recalculating \(d_x\), and iterating until agreement is reached:
lt_ax_prep <- demCore::iterate_ax(lt, id_cols)
#> Iteration 1
#> Number of remaining life tables: 1
#> Min. | 1st Qu. | Median | Mean | 3rd Qu. | Max.
#> 1.51 | 1.51 | 1.51 | 1.51 | 1.51 | 1.51
#> Iteration 2
#> Number of remaining life tables: 1
#> Min. | 1st Qu. | Median | Mean | 3rd Qu. | Max.
#> 0.06 | 0.06 | 0.06 | 0.06 | 0.06 | 0.06
#> Iteration 3
#> Number of remaining life tables: 0
#> Iterations done
source_type | hmd_loc_id | year | sex | age_start | age_end | age_length | deaths | population | mx | ax | qx | lx | dx |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
VR | USA | 2000 | male | 0 | 1 | 1 | 15729.83 | 1958928 | 0.0080298 | 0.066552 | 0.0079701 | 1.0000000 | 0.0079701 |
VR | USA | 2000 | male | 1 | 5 | 4 | 2823.68 | 7841313 | 0.0003601 | 1.463845 | 0.0014391 | 0.9920299 | 0.0014276 |
VR | USA | 2000 | male | 5 | 10 | 5 | 1847.44 | 10516497 | 0.0001757 | 2.447109 | 0.0008780 | 0.9906023 | 0.0008697 |
VR | USA | 2000 | male | 10 | 15 | 5 | 2553.61 | 10466468 | 0.0002440 | 3.145355 | 0.0012193 | 0.9897326 | 0.0012068 |
VR | USA | 2000 | male | 15 | 20 | 5 | 9699.37 | 10381688 | 0.0009343 | 2.753370 | 0.0046616 | 0.9885258 | 0.0046081 |
VR | USA | 2000 | male | 20 | 25 | 5 | 13378.28 | 9630209 | 0.0013892 | 2.550629 | 0.0069224 | 0.9839176 | 0.0068111 |
VR | USA | 2000 | male | 25 | 30 | 5 | 12621.08 | 9813310 | 0.0012861 | 2.511119 | 0.0064101 | 0.9771065 | 0.0062633 |
VR | USA | 2000 | male | 30 | 35 | 5 | 15276.72 | 10341599 | 0.0014772 | 2.603851 | 0.0073600 | 0.9708432 | 0.0071454 |
VR | USA | 2000 | male | 35 | 40 | 5 | 23255.66 | 11350590 | 0.0020489 | 2.657072 | 0.0101953 | 0.9636978 | 0.0098252 |
VR | USA | 2000 | male | 40 | 45 | 5 | 34060.31 | 11082786 | 0.0030733 | 2.665306 | 0.0152568 | 0.9538726 | 0.0145531 |
VR | USA | 2000 | male | 45 | 50 | 5 | 45127.00 | 9810326 | 0.0045999 | 2.645067 | 0.0227533 | 0.9393195 | 0.0213726 |
VR | USA | 2000 | male | 50 | 55 | 5 | 55291.46 | 8491794 | 0.0065112 | 2.656259 | 0.0320665 | 0.9179469 | 0.0294353 |
VR | USA | 2000 | male | 55 | 60 | 5 | 64450.41 | 6438883 | 0.0100096 | 2.660064 | 0.0489024 | 0.8885116 | 0.0434504 |
VR | USA | 2000 | male | 60 | 65 | 5 | 78920.52 | 5123319 | 0.0154042 | 2.655051 | 0.0743357 | 0.8450612 | 0.0628182 |
VR | USA | 2000 | male | 65 | 70 | 5 | 103967.33 | 4398992 | 0.0236344 | 3.953257 | 0.1153189 | 0.7822430 | 0.0902074 |
VR | USA | 2000 | male | 70 | Inf | Inf | 698575.26 | 9786764 | 0.0713796 | 14.009606 | 1.0000000 | 0.6920356 | 0.6920356 |
Extending the Life Table
Now we focus on extending the life table to the desired open age. We begin by creating an initial set of \(q_x\) values for ages between the input and desired open age using regression parameters based on the difference in logit-transformed \(q_x\) values
lt_extended <- extend_qx_diff(
lt_ax_prep[!is.infinite(age_end), c(..id_cols, "mx", "ax", "qx")],
coef_qx_diff,
lt_id_cols
)
#> Warning in min(age_start): no non-missing arguments to min; returning Inf
#> Warning in min(age_start): no non-missing arguments to min; returning Inf
lt_extended[
is.na(mx) & age_start >= 5,
mx := demCore::qx_ax_to_mx(qx, ax, age_end - age_start)
]
demCore::gen_lx_from_qx(lt_extended, id_cols)
demCore::gen_dx_from_lx(lt_extended, id_cols, assert_na = FALSE)
lt_extended[is.na(dx), dx := lx * qx]
sex | age_start | age_end | hmd_loc_id | year | source_type | mx | ax | qx | lx | dx |
---|---|---|---|---|---|---|---|---|---|---|
male | 0 | 1 | USA | 2000 | VR | 0.0080298 | 0.066552 | 0.0079701 | 1.0000000 | 0.0079701 |
male | 1 | 5 | USA | 2000 | VR | 0.0003601 | 1.463845 | 0.0014391 | 0.9920299 | 0.0014276 |
male | 5 | 10 | USA | 2000 | VR | 0.0001757 | 2.447109 | 0.0008780 | 0.9906023 | 0.0008697 |
male | 10 | 15 | USA | 2000 | VR | 0.0002440 | 3.145355 | 0.0012193 | 0.9897326 | 0.0012068 |
male | 15 | 20 | USA | 2000 | VR | 0.0009343 | 2.753370 | 0.0046616 | 0.9885258 | 0.0046081 |
male | 20 | 25 | USA | 2000 | VR | 0.0013892 | 2.550629 | 0.0069224 | 0.9839176 | 0.0068111 |
male | 25 | 30 | USA | 2000 | VR | 0.0012861 | 2.511119 | 0.0064101 | 0.9771065 | 0.0062633 |
male | 30 | 35 | USA | 2000 | VR | 0.0014772 | 2.603851 | 0.0073600 | 0.9708432 | 0.0071454 |
male | 35 | 40 | USA | 2000 | VR | 0.0020489 | 2.657072 | 0.0101953 | 0.9636978 | 0.0098252 |
male | 40 | 45 | USA | 2000 | VR | 0.0030733 | 2.665306 | 0.0152568 | 0.9538726 | 0.0145531 |
male | 45 | 50 | USA | 2000 | VR | 0.0045999 | 2.645067 | 0.0227533 | 0.9393195 | 0.0213726 |
male | 50 | 55 | USA | 2000 | VR | 0.0065112 | 2.656259 | 0.0320665 | 0.9179469 | 0.0294353 |
male | 55 | 60 | USA | 2000 | VR | 0.0100096 | 2.660064 | 0.0489024 | 0.8885116 | 0.0434504 |
male | 60 | 65 | USA | 2000 | VR | 0.0154042 | 2.655051 | 0.0743357 | 0.8450612 | 0.0628182 |
male | 65 | 70 | USA | 2000 | VR | 0.0236344 | 3.953257 | 0.1153189 | 0.7822430 | 0.0902074 |
male | 70 | 75 | USA | 2000 | VR | NA | NA | 0.1756747 | 0.6920356 | 0.1215731 |
male | 75 | 80 | USA | 2000 | VR | NA | NA | 0.2674195 | 0.5704625 | 0.1525528 |
male | 80 | 85 | USA | 2000 | VR | NA | NA | 0.3997912 | 0.4179097 | 0.1670766 |
male | 85 | 90 | USA | 2000 | VR | NA | NA | 0.5637259 | 0.2508331 | 0.1414011 |
male | 90 | 95 | USA | 2000 | VR | NA | NA | 0.7277048 | 0.1094320 | 0.0796342 |
male | 95 | 100 | USA | 2000 | VR | NA | NA | 0.8509103 | 0.0297978 | 0.0253553 |
male | 100 | 105 | USA | 2000 | VR | NA | NA | 0.9257056 | 0.0044425 | 0.0041125 |
male | 105 | 110 | USA | 2000 | VR | NA | NA | 0.9627513 | 0.0003301 | 0.0003178 |
Iterate to an optimal extension
With an initial projection of \(q_x\), we can now iteratively solve for the ideal extension by calculating life expectancy from the extended ages and comparing it to the life expectancy at the original open age interval
lt_extended[
lt_ax_prep[is.infinite(age_end)],
`:=`(
terminal_age_start = i.age_start,
mx_term = i.mx
),
on = lt_id_cols
]
lt_extended[, age_length := age_end - age_start]
lt_extended[, age_end := NULL]
setnames(lt_extended, "age_start", "age")
setnames(coef_ax_qx, "age_start", "age")
iteration_results <- iterate_qx(
dt = lt_extended,
ax_params = coef_ax_qx[, -"age_end"],
id_vars = c(lt_id_cols, "age"),
n_iterations = 50
)
#> [1] "All column names present"
#> [1] "All column names present"
#> [1] "Variable beta passed gte test"
lt_iterated <- copy(iteration_results[[1]])
iteration_info <- copy(iteration_results[[2]])
setnames(lt_iterated, "age", "age_start")
lt_iterated[, age_end := shift(age_start, n = 1, type = "lead")]
lt_iterated[age_start == max(age_start), age_end := open_age]
setcolorder(lt_iterated, id_cols)
hmd_loc_id | year | source_type | sex | age_start | age_end | mx | ax | qx | lx | dx |
---|---|---|---|---|---|---|---|---|---|---|
USA | 2000 | VR | male | 0 | 1 | 0.0080298 | 0.066552 | 0.0079701 | 1.0000000 | 0.0079701 |
USA | 2000 | VR | male | 1 | 5 | 0.0003601 | 1.463845 | 0.0014391 | 0.9920299 | 0.0014276 |
USA | 2000 | VR | male | 5 | 10 | 0.0001757 | 2.447109 | 0.0008780 | 0.9906023 | 0.0008697 |
USA | 2000 | VR | male | 10 | 15 | 0.0002440 | 3.145355 | 0.0012193 | 0.9897326 | 0.0012068 |
USA | 2000 | VR | male | 15 | 20 | 0.0009343 | 2.753370 | 0.0046616 | 0.9885258 | 0.0046081 |
USA | 2000 | VR | male | 20 | 25 | 0.0013892 | 2.550629 | 0.0069224 | 0.9839176 | 0.0068111 |
USA | 2000 | VR | male | 25 | 30 | 0.0012861 | 2.511119 | 0.0064101 | 0.9771065 | 0.0062633 |
USA | 2000 | VR | male | 30 | 35 | 0.0014772 | 2.603851 | 0.0073600 | 0.9708432 | 0.0071454 |
USA | 2000 | VR | male | 35 | 40 | 0.0020489 | 2.657072 | 0.0101953 | 0.9636978 | 0.0098252 |
USA | 2000 | VR | male | 40 | 45 | 0.0030733 | 2.665306 | 0.0152568 | 0.9538726 | 0.0145531 |
USA | 2000 | VR | male | 45 | 50 | 0.0045999 | 2.645067 | 0.0227533 | 0.9393195 | 0.0213726 |
USA | 2000 | VR | male | 50 | 55 | 0.0065112 | 2.656259 | 0.0320665 | 0.9179469 | 0.0294353 |
USA | 2000 | VR | male | 55 | 60 | 0.0100096 | 2.660064 | 0.0489024 | 0.8885116 | 0.0434504 |
USA | 2000 | VR | male | 60 | 65 | 0.0154042 | 2.655051 | 0.0743357 | 0.8450612 | 0.0628182 |
USA | 2000 | VR | male | 65 | 70 | 0.0236344 | 3.953257 | 0.1153189 | 0.7822430 | 0.0902074 |
USA | 2000 | VR | male | 70 | 75 | 0.0317424 | 2.631083 | 0.1476124 | 0.6920356 | 0.1021530 |
USA | 2000 | VR | male | 75 | 80 | 0.0503577 | 2.606215 | 0.2247019 | 0.5898826 | 0.1325477 |
USA | 2000 | VR | male | 80 | 85 | 0.0803626 | 2.559480 | 0.3359285 | 0.4573349 | 0.1536318 |
USA | 2000 | VR | male | 85 | 90 | 0.1246131 | 2.469101 | 0.4736762 | 0.3037031 | 0.1438569 |
USA | 2000 | VR | male | 90 | 95 | 0.1828248 | 2.292583 | 0.6114611 | 0.1598461 | 0.0977397 |
USA | 2000 | VR | male | 95 | 100 | 0.2402334 | 2.169472 | 0.7149857 | 0.0621065 | 0.0444052 |
USA | 2000 | VR | male | 100 | 105 | 0.2823395 | 2.113722 | 0.7778332 | 0.0177012 | 0.0137686 |
USA | 2000 | VR | male | 105 | 110 | 0.3045864 | 2.102374 | 0.8089612 | 0.0039326 | 0.0031813 |
Add New Open Age Interval
Finally, all that remains is to calculate the life table parameters for the new open age interval
lt_final <- rbind(
lt_iterated,
lt_iterated[1, ..lt_id_cols][, `:=`(age_start = open_age, age_end = Inf, qx = 1)],
fill = TRUE
)
demCore::gen_lx_from_qx(lt_final, id_cols)
demCore::gen_dx_from_lx(lt_final, id_cols)
hmd_loc_id | year | source_type | sex | age_start | age_end | mx | ax | qx | lx | dx |
---|---|---|---|---|---|---|---|---|---|---|
USA | 2000 | VR | male | 0 | 1 | 0.0080298 | 0.066552 | 0.0079701 | 1.0000000 | 0.0079701 |
USA | 2000 | VR | male | 1 | 5 | 0.0003601 | 1.463845 | 0.0014391 | 0.9920299 | 0.0014276 |
USA | 2000 | VR | male | 5 | 10 | 0.0001757 | 2.447109 | 0.0008780 | 0.9906023 | 0.0008697 |
USA | 2000 | VR | male | 10 | 15 | 0.0002440 | 3.145355 | 0.0012193 | 0.9897326 | 0.0012068 |
USA | 2000 | VR | male | 15 | 20 | 0.0009343 | 2.753370 | 0.0046616 | 0.9885258 | 0.0046081 |
USA | 2000 | VR | male | 20 | 25 | 0.0013892 | 2.550629 | 0.0069224 | 0.9839176 | 0.0068111 |
USA | 2000 | VR | male | 25 | 30 | 0.0012861 | 2.511119 | 0.0064101 | 0.9771065 | 0.0062633 |
USA | 2000 | VR | male | 30 | 35 | 0.0014772 | 2.603851 | 0.0073600 | 0.9708432 | 0.0071454 |
USA | 2000 | VR | male | 35 | 40 | 0.0020489 | 2.657072 | 0.0101953 | 0.9636978 | 0.0098252 |
USA | 2000 | VR | male | 40 | 45 | 0.0030733 | 2.665306 | 0.0152568 | 0.9538726 | 0.0145531 |
USA | 2000 | VR | male | 45 | 50 | 0.0045999 | 2.645067 | 0.0227533 | 0.9393195 | 0.0213726 |
USA | 2000 | VR | male | 50 | 55 | 0.0065112 | 2.656259 | 0.0320665 | 0.9179469 | 0.0294353 |
USA | 2000 | VR | male | 55 | 60 | 0.0100096 | 2.660064 | 0.0489024 | 0.8885116 | 0.0434504 |
USA | 2000 | VR | male | 60 | 65 | 0.0154042 | 2.655051 | 0.0743357 | 0.8450612 | 0.0628182 |
USA | 2000 | VR | male | 65 | 70 | 0.0236344 | 3.953257 | 0.1153189 | 0.7822430 | 0.0902074 |
USA | 2000 | VR | male | 70 | 75 | 0.0317424 | 2.631083 | 0.1476124 | 0.6920356 | 0.1021530 |
USA | 2000 | VR | male | 75 | 80 | 0.0503577 | 2.606215 | 0.2247019 | 0.5898826 | 0.1325477 |
USA | 2000 | VR | male | 80 | 85 | 0.0803626 | 2.559480 | 0.3359285 | 0.4573349 | 0.1536318 |
USA | 2000 | VR | male | 85 | 90 | 0.1246131 | 2.469101 | 0.4736762 | 0.3037031 | 0.1438569 |
USA | 2000 | VR | male | 90 | 95 | 0.1828248 | 2.292583 | 0.6114611 | 0.1598461 | 0.0977397 |
USA | 2000 | VR | male | 95 | 100 | 0.2402334 | 2.169472 | 0.7149857 | 0.0621065 | 0.0444052 |
USA | 2000 | VR | male | 100 | 105 | 0.2823395 | 2.113722 | 0.7778332 | 0.0177012 | 0.0137686 |
USA | 2000 | VR | male | 105 | 110 | 0.3045864 | 2.102374 | 0.8089612 | 0.0039326 | 0.0031813 |
USA | 2000 | VR | male | 110 | Inf | NA | NA | 1.0000000 | 0.0007513 | 0.0007513 |