# Life tables and R programming: Period Life Table Construction

There are many ways to construct a life table and they vary with complexity. Various assumptions go into the conversion of TeX Embedding failed! into TeX Embedding failed!, especially at the youngest ages, and how to terminate the life table at the highest ages. Graduation or other techniques may be used to go from abridged life tables (e.g. 5 year age groups) to single years of age. See sections 3.1 and following in Preston et. al. for details.

The data is deaths from all causes over the period 1999-2002, obtained from the CDC:

```## fetch data; will read in and define AllCOD.19992002

## Lifetable creation

Create a simple life table for 1999-2002 females using the raw data given in the above data. See one solution below.

```  > AllCOD.19992002
\$Females
Gender	   Age.Description	 Death.Count	 Population	 Crude.Death.Rate
1 	      F	      Under 1 Year	       49016	    7846166	            624.7
2 	      F	        1- 4 years	        8689	   30110500	             28.9
3 	      F	        5- 9 years	        5595	   39639456	             14.1
4 	      F	       10-14 years	        6399	   40360290	             15.9
5 	      F	       15-19 years	       15621	   39339459	             39.7
6 	      F	       20-24 years	       17776	   37857523	             47.0
7 	      F	       25-34 years	       50896	   79035547	             64.4
8 	      F	       35-44 years	      131696	   90536189	            145.5
9 	      F	       45-54 years	      245138	   78172750	            313.6
10	      F	       55-64 years	      394940	   51980118	            759.8
11	      F	       65-74 years	      766829	   40202118	           1907.4
12	      F	       75-84 years	     1443183	   30133845	           4789.2
13	      F	 85 years and over	     1782749	   12281209	          14516.1```

Compute the observed death rates and write a function in R to compute and return a period lifetable with the same age group boundaries as the raw data (0,1,5,10,15,...80, 85+) Refer to Jamie’s notes and chapter 3 in Preston et al. Your function should take as arguments: `x,nDx, nKx` (age, deaths between (x,x+n), population aged (x,x+n) and return columns of the lifetable: `x,nMx,nax,nqx, lx, ndx, nLx, Tx, ex`

A template of the function will look like:

``` lifetable<- function(x, nDx, nKx) {

# compute death rates
# decide on 1a0, 4a1, ... values
# compute nqx with final qx=1
# compute lx,dx,nLx,Tx, ex

# return data frame of results with named columns

lt <- data.frame(x=x, nax =nax,
nMx = nMx,
nqx = nqx,
lx = lx,
ndx = ndx,
nLx = nLx,
Tx = Tx,
ex = ex )
return(lt)
}```

Compare your solution with the examples of Jamie's example life table function, the terse code from UC Berkeley and the much more elaborate `life.table()` found in John Wilmoth's archive of R functions.

## Solution

Here is one possible route to take in solving this exercise. Since most people used Jamie’s life table function as a starting point, I will present a modification of that as my solution. I use `data.frame()` to return the value of the calculation because then the individual components of the result may be selected by name, not just by column number.

```### --- Data --- ###
## load() is quite different from reading in data from an ASCII file.  It restores
## variables once saved with the save() command.  It is difficult to know in advance
## what will be restored by load-ing a stored dataset.  I try to minimize confusion by
## using the same name for the R object and for the name of the file.

# str(AllCOD.19992002)  ## the str() function will tell you how something is structured.
# here is  shows that AllCOD.19992002 consists of a list with two components,
# (Female, Male), and each of those components is in turn a data.frame.

females <- AllCOD.19992002\$Females ;

# variables I will pass the life table function
# age is iregularly spaced
x <- c(0,1,5,10,15,20,25,35,45,55,65,75,85) ;
# note that R collapses a single column to a vector when it pulls out the result out
# of a data.frame
nDx <- females\$Death.Count;   # other syntax which produces the same result: females[[3]], females[,3],
# females["Death.Count"], or AllCOD.19992002\$Females\$Death.Count
nKx <- females\$Population ;
nMx <- nDx / nKx ;```

And now the lifetable function. Note that I do not have separate arguments for TeX Embedding failed! and TeX Embedding failed!, but only a single TeX Embedding failed! argument.

```life.table <- function( x, nMx){
## simple lifetable using Keyfitz and Flieger separation factors and
## exponential tail of death distribution (to close out life table)

b0 <- 0.07;   b1<- 1.7;
nmax <- length(x)
# nMx = nDx/nKx
n <- c(diff(x),999)          #width of the intervals
nax <- n / 2;		            # default to .5 of interval
nax[1] <- b0 + b1 *nMx[1]    # from Keyfitz & Flieger(1968)
nax[2] <- 1.5  ;
nax[nmax] <- 1/nMx[nmax] 	  # e_x at open age interval
nqx <- (n*nMx) / (1 + (n-nax)*nMx)
nqx<-ifelse( nqx > 1, 1, nqx); # necessary for high nMx
nqx[nmax] <- 1.0
lx <- c(1,cumprod(1-nqx)) ;  # survivorship lx
lx <- lx[1:length(nMx)]
ndx <- lx * nqx ;
nLx <- n*lx - nax*ndx;       # equivalent to n*l(x+n) + (n-nax)*ndx
nLx[nmax] <- lx[nmax]*nax[nmax]
Tx <- rev(cumsum(rev(nLx)))
ex <- ifelse( lx[1:nmax] > 0, Tx/lx[1:nmax] , NA);
lt <- data.frame(x=x,nax=nax,nmx=nMx,nqx=nqx,lx=lx,ndx=ndx,nLx=nLx,Tx=Tx,ex=ex)
return(lt)
}```