Period Life Table Construction
Here's how to reproduce the calculations in Box 3.1 of
Preston et a. (p. 49) using Stata as a calculator.
(Stata has a ltable command for cohort
life tables.)
The input data are counts of the mid-year population and the number of deaths at ages 0,1-4,5-9,...,80-84,85+ for Austrian males in 1992, available in the course website.
. infile age N D using http://data.princeton.edu/eco572/datasets/prestonb31.dat (19 observations read)
We need the width of the age intervals.
. gen n = age[_n+1]-age // leaves width of last interval missing (1 missing value generated)
The calculations are pretty straitforward. The numbers below refer to the numbered steps in the textbook. To ensure full precision I use doubles; floats are good for only about 7 digits and this can be a problem with large numbers such as nLx.
1. We compute death rates dividing events by exposure.
. gen m = D/N
2. Next we need the time lived by deaths (nax). Preston et al. borrow these values for ages 5 to 75 from Keyfitz and Flieger (1971), p.21. I saved those values in a Stata file so I can easily merge them here (after sorting by age)
. sort age . merge age using http://data.princeton.edu/eco572/datasets/kfnax
(You should list the data to see what you got.)
The factors for ages 0-1 and 1-4, however, are based on the
Coale-Demeny equations under age 5, which depends on the mortality
rate at age 0, so we use cond:
. rename nax a // I am omitting the subscripts for simplicity . replace a = cond(m[1] >= 0.107, .330, .045 + 2.684 * m[1]) in 1 (1 real change made) . replace a = cond(m[1] >= 0.107, 1.352, 1.651 - 2.816 * m[1]) in 2 (1 real change made)
The value for the last age is not used, but we will replace it anyway to avoid confusion
. replace a = 1/m in -1 (1 real change made)
3. Convert the death rates to probabilities using the
nax factors, and
4. Compute survival probabilities as the complement
. gen double q = n * m/(1+(n-a)*m) (1 missing value generated) . replace q = 1 in -1 (1 real change made) . gen double p = 1 - q
5. Generate the survival function starting with a radix of 100,000.
Note that each value of lx depends on previous values
. gen double lx = 100000 in 1 (18 missing values generated) . quietly replace lx = lx[_n-1] * p[_n-1] in 2/-1
6. Generate deaths by differencing the number of survivors and noting that everyone dies in the end
. generate d = lx - lx[_n+1] (1 missing value generated) . replace d = lx in -1 (1 real change made)
7. Compute person-years lived in each age group, which is n for those who survive the age group and nax for those who die
. gen double L = n * lx[_n+1] + a * d // not to be confused with D (1 missing value generated) . replace L = lx/m in -1 (1 real change made)
8. Accumulating from the bottom up is a bit tricky because Stata likes to sum from the top down. You could sort the data from oldest to youngest, sum, and then sort again. I will subtract the cumulative sum from the total.
. quietly summarize L . gen double T = r(sum) - sum(L) + L
9. Finally we compute expectation of life dividing time lived after each age by survivors to that age
. gen e = T/lx
To print the table exactly as in the book we specify a few formats
. format %6.3f a e . format %8.6f m q p . format %9.0fc N D lx d L T . format %8.6f m q p
And we are ready to print our results (in two parts)
. list age N D m a q p
+----------------------------------------------------------------+
| age N D m a q p |
|----------------------------------------------------------------|
1. | 0 47,925 419 0.008743 0.068 0.008672 0.991328 |
2. | 1 189,127 70 0.000370 1.626 0.001479 0.998521 |
3. | 5 234,793 36 0.000153 2.500 0.000766 0.999234 |
4. | 10 238,790 46 0.000193 3.143 0.000963 0.999037 |
5. | 15 254,996 249 0.000976 2.724 0.004872 0.995128 |
|----------------------------------------------------------------|
6. | 20 326,831 420 0.001285 2.520 0.006405 0.993595 |
7. | 25 355,086 403 0.001135 2.481 0.005659 0.994341 |
8. | 30 324,222 441 0.001360 2.601 0.006779 0.993221 |
9. | 35 269,963 508 0.001882 2.701 0.009368 0.990632 |
10. | 40 261,971 769 0.002935 2.663 0.014577 0.985423 |
|----------------------------------------------------------------|
11. | 45 238,011 1,154 0.004849 2.698 0.023975 0.976025 |
12. | 50 261,612 1,866 0.007133 2.676 0.035082 0.964918 |
13. | 55 181,385 2,043 0.011263 2.645 0.054861 0.945139 |
14. | 60 187,962 3,496 0.018600 2.624 0.089062 0.910938 |
15. | 65 153,832 4,366 0.028382 2.619 0.132925 0.867075 |
|----------------------------------------------------------------|
16. | 70 105,169 4,337 0.041238 2.593 0.187573 0.812427 |
17. | 75 73,694 5,279 0.071634 2.518 0.304102 0.695898 |
18. | 80 57,512 6,460 0.112324 2.423 0.435548 0.564452 |
19. | 85 32,248 6,146 0.190585 5.247 1.000000 0.000000 |
+----------------------------------------------------------------+
. list age lx d L T e
+-------------------------------------------------------+
| age lx d L T e |
|-------------------------------------------------------|
1. | 0 100,000 867 99,192 7,288,901 72.889 |
2. | 1 99,133 147 396,183 7,189,709 72.526 |
3. | 5 98,986 76 494,741 6,793,526 68.631 |
4. | 10 98,910 95 494,375 6,298,785 63.682 |
5. | 15 98,815 481 492,980 5,804,410 58.740 |
|-------------------------------------------------------|
6. | 20 98,334 630 490,106 5,311,431 54.014 |
7. | 25 97,704 553 487,127 4,821,324 49.346 |
8. | 30 97,151 659 484,175 4,334,198 44.613 |
9. | 35 96,492 904 480,384 3,850,023 39.900 |
10. | 40 95,588 1,393 474,686 3,369,639 35.252 |
|-------------------------------------------------------|
11. | 45 94,195 2,258 465,777 2,894,953 30.734 |
12. | 50 91,937 3,225 452,188 2,429,176 26.422 |
13. | 55 88,711 4,867 432,096 1,976,988 22.286 |
14. | 60 83,845 7,467 401,480 1,544,893 18.426 |
15. | 65 76,377 10,152 357,713 1,143,412 14.971 |
|-------------------------------------------------------|
16. | 70 66,225 12,422 301,224 785,699 11.864 |
17. | 75 53,803 16,362 228,404 484,475 9.005 |
18. | 80 37,441 16,307 145,182 256,070 6.839 |
19. | 85 21,134 21,134 110,889 110,889 5.247 |
+-------------------------------------------------------+
Finally, we will plot a couple of life table functions using the mid-points of the age groups:
. gen am = ( age + age[_n+1] )/2
(1 missing value generated)
. replace am = 90 in -1
(1 real change made)
. line m am, xtitle(age) ytitle("log(m)") yscale(log) ///
> ylabel(.01 .05 .2) title("Austria, 1992") subtitle(males)
. graph export aultm92.png, replace
(file aultm92.png written in PNG format)

