Friday, 6 April 2018

Gompertz overhauled: Adaptation of a 200 years old distribution to the modern style of dying

If he could have looked 200 years into the future, Benjamin Gompertz (1779-1865) would surely have been pleased to see how well his "law of mortality" holds up under conditions vastly different from those where they were formulated. In particular, how it nowadays outperforms the more modern and versatile Weibull distribution, Gompertz is FG(x) = 1 - exp(-b/a (eax-1)) vs Weibull FW(x) = 1 - exp(-(x/a)k). I imagine Gompertz, having applied his standard set of tools, could have been spot on in his criticism of the Weibull as a mortality law:
"Look here. All the mortality data I have looked into approximately follow a geometric progression of hazard rates,   hn = h0αn     [1] But the Weibull has something in between an arithmetic and a geometric progression. Counting from age x0 we get:   hn = h0(1+n/x0)k-1.     In general, that is a worse fit to the data, and the lower h0 and the higher n are, the less adept it gets when it comes to capturing the more challenging features of human mortality."

But low h0 and high n are the most important characteristics of contemporary mortality in developed countries. We can illustrate this by applying maximum likelihood estimation (MLE) of Weibull, Gompertz, Gompertz-Makeham and "slightly generalized Gompertz" to what model-wise may be one of the most challenging mortality datasets: The 2017 table for Norwegian women. There are quite a few "generalized Gompertz" distributions available, but I haven't seen one labeled "slightly generalized Gompertz", so I use that for the distribution FG3(x) = 1 - exp(-b/a (eaxk-1)).
Some purists may frown upon this use of "synthetic" data, but I think that criticism overshoots a bit here: The main bulk of deaths occur between ages 75 and 95, and the mortality changes over short time spans are not big enough to make the table approach invalid for model evaluation and estimation.

MLE fitting using optimx and nlminb

The good'ol nlm function of base R doesn't quite cut it here, and I employed the optimx package [2], where the nlminb function proved to be the best choice for this task. I tried to help it by following the book and furnishing gradient and hessian functions, but it didn't quite work out, and I deemed the basic results obtained good enough for the present purpose. Beware that with several parameters, quite different combinations may give quite similar end results. If that is considered a bug, it is a bug of the model.

I think fig 1 quite clearly brings out the strengths and weaknesses of the distributions employed. First, we may say that "re-enacted" Gompertz' principally based criticism of the Weibull distribution is completely vindicated: Weibull isn't able to adapt to the sharply focused contemporary mortality, and strongly overestimates deaths from 60 to 80, in addition to furnishing us with a small, non-existent army of centenarians. Standard Gompertz is far better, but fails to capture the 70-90's deviations from linear log-hazard rate mentioned in [1].

Fig 1. Norwegian female mortality 2017 and four approximations: Gompertz, Gompertz-Makeham, Gompertz with exponent parameter exp(axk) and Weibull. Maximum likelihood approximation using R function nlminb on the log-likelihoods of the respective distribution families.

Gompertz-Makeham (GM) and "slightly generalized Gompertz" (FG3) both add a parameter: GM for including a constant component in the hazard rate, log(h(x)) = log(b eax + λ). FG3 models an often occurring kind of non-linearity in the log-hazard rate: log(h(x)) = log(b) + log(k) + axk + (k-1)log(x). While they approximate marginally better than plain Gompertz, they both fail to capture the deviations from linearity adequately. They overestimate mortality ages 70-80, underestimate it around 90, and don't fully get the sharp peak around 90.

As a mathematician, Gompertz probably appreciated the intricacies involved in focused mortality patterns, and I'm not sure he would rate the 2018 performance of his method so badly. But we can be quite sure that as an expert actuarian, he wouldn't feel content with 15-20% error in predicting deaths in an important age group. So he would surely agree that his method needed an overhaul, while probably insisting the the overhaul be local. For the overall performance of his method is still quite good.

There is clearly not just one way to do this overhaul. But FG3 has told us that the "generalization" approach may not be worthwhile. Maybe we need something "special" rather than "general"? The good performance of standard Gompertz at ages 95-100 may give us some hints: Don't introduce something that deviates a lot from the log-hazard line there.

Overhaul requirements

The overhauled method must be adaptive, so we need parameters. They should come in addition to (a,b)

  • As few additional parameters as possible, we accept some hard-coding in the result
  • Localized: Effect of modification minimal outside of age span ca 70-95
  • Perturbation with strong damping, exponential may be used for that
  • The deviations to model suggest an anti-symmetric perturbation, like x3+x
  • Localization may be done by translation x->x-h
  • We would like perturbation function l(x) to have a continous derivative
  • We would like to have log(h(x)) ≈ log(b) + a(x+l(x)) + δ(x) with δ(x) "small"
Are those requirements hard to meet, while still providing something that works well enough?

The requirements indicate that we could probably make good use of at least 3 parameters (c,d,h): Perturbation could be dimensioned by c, its exponential dampening regulated by d and the localization (around 85-90 years of age) byh. Giving us something like:
l(x) = c((x-h)3 + A(x-h))/(1+exp(d |x-h|))
The parameter A will be tuned "manually", and then hard-coded into the model.

Maxima: Visiting a friend of R

With the requirements, and a basic idea for solution, it may be time to turn to one of R's good, but maybe underrated and underexploited friends, the computer algebra system (CAS) of ancient Lisp lineage, Maxima[3]. I use it with the wxmaxima user interface. It's not that Maxima is so indispensable as a tool, but it is very good for structured approaches and quality control.

Defining l(x) in Maxima, we can try it out with different values of the parameters, we can differentiate (albeit it may be best to carry out that manually, because of the potential discontinuity of l'(x) at x=h. And more importantly, we can get assistance with the pdf and the log-likelihood. We can see that it does in fact have a continous derivative at x=h, but with a small cusp. The higher order discontinuities have no impact on our mortality modeling.

As an example, here is the "raw" MathML [4] output from wxmaxima, giving the log-likelihood for
FGO(x) = 1 - exp(-a/b (ea(x+l(x))-1)).
Saved as a function, it can be edited and used in the R code. Note that Maxima's straight use of d/dx |x| = x/|x| is not a good way to implement that functionality in R. log c d x h x h 3 + 6 x h %e d x h %e d x h + 1 2 x h + c 3 x h 2 + 6 %e d x h + 1 + 1 + a c x h 3 + 6 x h %e d x h + 1 + x b %e a c x h 3 + 6 x h %e d x h + 1 + x a + log b + b a

Fig 2. Norwegian female mortality 2017 approximated by overhauled Gompertz. Basic Gompertz shown for reference. Maximum likelihood approximation using R function nlminb on the log-likelihoods of the respective distribution families.
Estimated parameters: (a,b,c,d,h)=(0.115,3.913839e-06,0.03849455,0.3461503,92.5)

Running optimx with different initial conditions will invariably lead to different parameter estimates, many of which may meet the convergence criteria, and this may feel a bit frustrating. Furthermore, maximizing the log-likelihood carefully may not return the best parameter set for your purposes, some limited deviation from maximality may be warranted. But these issues must be considered necessary consequences of the parametrization.

One reason the more plain Newton-based routine nlm is less useful in such situations, is that the parameters may get very close to 0. But several functions may break on negative input, so we may need to limit the search - something nlminb and a few other easily available routines allow for.

Fig 2 shows that overhauling Gompertz by adding 3 parameters for modeling local non-linearity in the log-hazard function may indeed be enough to obtain good fits. Most of the overestimation at 60-80 is gone, and the mortality peak at 90 is well captured. The "costs" in this concrete case are somewhat larger deviations at the oldest ages, and in addition, small irregularities are "neglected". Different sets of parameters yield slightly different results in this respect.

Similar results are obtained by adding the l(x) modification to Gompertz-Makeham, but I don't show them here. With more parameters, we also potentially get more indetermination and more job choosing between essentially equivalent parameter sets. And as we can see from the plots, at the ages 25-50, where the fits are really improved by the Makeham parameter λ the absolute deviation between estimated and observed deaths is rather small.

The full specification of the overhauled Gompertz approximation for 2017 Norwegian female mortality thus becomes:
FGO(x) = 1 - exp(-0.115/3.9e-6 (e0.115(x+l(x))-1)).
l(x) = 0.04((x-92.5)3 + 6(x-92.5))/(1+exp(0.35 abs(x-92.5)))

Fig 3. Norwegian male (blue) and female (red) mortality 1967-2017 approximated by overhauled Gompertz. Basic Gompertz shown for reference.

A 50 years perspective

Fig 3 illustrates how the overhauled version also can be applied to older mortality data, but 50 years ago, the fit of the basic Gompertz distribution might be deemed adequate both for women and men. The estimated value of the c parameter was much smaller 50 years ago, but the 3 extra parameters might contribute to better fit also then. Therefore, it is not necessarily very efficient simply to set c=0 for older data. For older data, there may also be more to be gained by including the Makeham λ parameter. It should be noted, though, that Gompertz-Makeham in no way can account for the largest difference between today and 50 years ago: Infant mortality, which has decreased 6-8-fold. In 1967, about 2% of newborns died before 11, today, 2% of newborns are not expected to have died at 45, and about 97.5% are expected to reach 50.

The peak in deaths has become higher and more narrow over time, and in particular for women, less regular. About 36% of all female deaths now occur between 85 and 92, and fig 3 indicates a tendency for the men's mortality curves to resemble that of women 10-20 years earlier, just a little bit lower and translated a few years to the left. The coefficient plots shown in [1] may be interpreted as indication of a degree of convergence of male and female mortality, but what kind of evidence is extrapolating based on? In Norway, cardiovascular disease has over the years become a less prominent cause of death, while cancer mortality has increased. But what might the impact of that be when about 50% of male deaths and 62% of female deaths occur at age 85 or older?

One might try to assess the development in mortality by looking at plots of the coefficients of overhauled Gompertz, but the optimization procedure used here is not stable enough to produce estimates where the parameters, without further processing or quality control, can be organized in time series in any meaningful way. That is also a result of the higher degree of randomness introduced when irregularities are modeled more precisely. This also applies to derived indicators like the mode, which with overhauled Gompertz does not have the same predictable relation to the whole distribution as it has with basic Gompertz. The parameters (a,b) of the basic linear log-hazard should in principle be displayed in the fitted model, but the 5 parameters (a,b,c,d,h) are dependent, and different combinations may produce quite similar model fits.

The basic R machinery in use

When defining new distributions, functions for the pdf f(x,para) and the negative of the log-likelihood minusLogLikf(para) is in many cases enough. For simplicity, I don't try to supply data to the likelihood function as parameter(s), when it is to be used on several data sets I rather embed it in a wrapper function that takes the data as parameter(s) and prepares it for the optimization procedures. In this case, data is provided as a frequency table, with x holding the case values and dx the number of cases (sum(dx)=100000).

When parameter constraints are provided for optimx (here lower=c(0,0,0,0,0)), several entries in the method list may be excluded. I tend to keep a long list intact, as it may happen that the constraints can be dropped when we have zoomed in on the correct parameter neighborhoods.



fGompAugm5p  <- function(x,para) {
    a <- para[1] ; b <- para[2] ;   c <- para[3] ; d <- para[4] ; h <- para[5] ; 
    xepsi <- 2 ; l <- 1 ;
    diffact <- ifelse(x < h,-1,1) ;
    hxfunc <-c*((x-h)^3 + 3*xepsi*(x-h))/(l + exp(d*abs(x-h))) ; 
    ldxfunc <- 1 + 3*c*((x-h)^2 + 1*xepsi)/(l + exp(d*abs(x-h))) + -d*c*diffact*((x-h)^3 
              + 3*xepsi*(x-h))*exp(d*abs(x-h))/(l + exp(d*abs(x-h)))^2 ;
    b*ldxfunc*exp(a*(x + hxfunc))*exp(-b/a*exp(a*(x+hxfunc)) + b/a)
 }

minusLogLikGompAugm5p  <- function(para) {
    a <- para[1] ; b <- para[2] ;   c <- para[3] ; d <- para[4] ; h <- para[5] ;
    n <- sum(dx) ; xepsi <- 2 ; l <- 1 ;

    hxfunc <-c*((x-h)^3 + 3*xepsi*(x-h)) /(l+ exp(d*abs(x-h)))
    diffact <- ifelse(x < h,-1,1)
    ldxfunc <- 1 +  3*l*c*((x-h)^2 + 1*xepsi)/ (l + exp(d*abs(x-h))) -d*c*diffact*((x-h)^3 
               + 3*xepsi*(x-h))*exp(d*abs(x-h))/(l + exp(d*abs(x-h)))^2 ;
    logdxsum <- sum(dx*log(ldxfunc)) ;      
    xsum <- sum(dx*(x + hxfunc)) ; expsum <- sum(dx*exp(a*(x + hxfunc))) ;

 - ( n*log(b) + n*b/a + logdxsum  + a*xsum  - b/a*expsum  )
 }

# M2017 - dx vector contains mortality data for males 2017
p5 <- c(0.115,3.9e-06,0.04,0.35,92.5);
g5x<-optimx(p5,fn=minusLogLikGompAugm5p,
            method=c("Nelder-Mead","BFGS","nlm","L-BFGS-B","nlminb"),lower=c(0,0,0,0,0)) ;


References
1. "Gompertz rules" posting on this blog 20180402
2. Interview with John Nash about optimx
3. Background on Maxima
4. MathML introduction

Monday, 2 April 2018

Gompertz rules: A 50-year perspective on "contemporary" mortality

There are many ways to describe human mortality, the "best" way will often depend on the purpose. It is influenced by (among others) genetical, environmental, social and behavioral factors. With so many different factors influencing it, one single functional form may hardly be expected optimal for all modeling of life times. But some persistent patterns may emerge, and this is neatly demonstrated by recent Norwegian mortality data confirming the 1810-1825 observations of Benjamin Gompertz (1779-1865). Drawing on several different data sources, Gompertz found that the logarithm of the hazard rate for the elderly seemed to always be approximately a linear function of age, and we see the same basic pattern today: In this respect, Gompertz rules.

The hazard rate of a distribution with cdf F and pdf f, is defined as h(x) = f(x)/(1-F(x)) = d/dx log(1-F(x)). It has an immediate interpretation and application: With N(x) individuals at age x, and hazard rate h(x), the probability of one dying within one year is h(x), and we can expect approximately N(x)h(x) to die in that period. Given an exact h(x), F(x) is determined modulo eventual constants, but in most cases, the information we obtain about the hazard rate may be consistent with different types of distributions. The exponential hazard rate seen in human mortality is kind of limit case in this respect.

Gompertz published a comprehensive report on this in 1825, but did not dwell much on systematic deviations from the linear relationship at younger ages. In 1860, William Makeham (1826-1891) improved on the fit for younger ages by extending the Gompertz model with a constant added to the hazard rate. The resulting distribution is still widely applied as the Gompertz-Makeham law of mortality. It tends to fit fairly well from 15-20 to about 100 years if age.

In 1860, the high overall mortality made the Makeham term highly significant, but most developed countries today have a very low mortality at younger ages, which makes it less practically important. For example, in Norway today only 0.5-1% of females die between ages 20 and 40, and about 98% of female newborns are expected to reach the age of 50.

Gompertz' observation: Mortality follows a geometric progression

Gompertz discovered that whatever adult age he started counting from, mortality n years after, as measured by hazard rate hn, could be approximately expressed as a geometrical progression of the initial value h0:
      hn = h0αn
Taking logarithms, we get
      log(hn) = log(h0) + n log(α)
I.e. a linear function of time (age) n, and whenever this is approximately correct, the Gompertz distribution will be a (more or less accurate) model for the life times. The Gompertz cumulative distribution function is fairly simple, here is the parametrization used in R's flexsurv package:
      F(x) = 1 - exp(-b/a (eax-1))
The hazard rate becomes h(x) = f(x)/(1-F(x)) = b eax. The corresponding Gompertz-Makeham rate is h(x) = b eax + λ

An interpretation of a, is that the mortality doubles in (log(2)≈0.69)/a years. E.g. with a=0.10, mortality doubles every 7 years. This period varies widely, but 5-10 years is a normal range. When overall mortality decreases, the doubling time often decreases, i.e. a increases.

The linear log-hazard function may seem unreasonable

The Gompertz rule has very strong assertions (linearity over an extremely wide range of mortality rates) and an obvious way it breaks down: At some age xmax, we will have a*xmax + log(b) > 0 . That means for P(death) in the next period δx =1 :   P(death) ≈ b exp(a*xmax)*δx > 1   So death in the next period is more than guaranteed :-) Therefore, we must expect that from some high age on, this rate will be constant or even fall a bit. But what is the practical relevance of that?

I was more concerned about the shortcomings before looking at the Norwegian data. It turns out that the deviations from linear log-mortality has not increased over time, in spite of a tremendous increase in people reaching very old age. Rather, the practically important deviations mostly occur between 70 and 95, at around 100, Norwegian mortality follows standard Gompertz quite closely. It also turns out the the regression line in question tends to "rotate": Basic mortality have been steadily decreasing, while the age-dependent part has tended to increase lately, both for men and women. The mortality at 95-100 is rather stable, in spite of the huge increase in the number of persons reaching that age. Also, the gender differences in those parameters were much larger 50 years ago.

Used on the Norwegian data, the linear log-hazard function is reasonable. It is not in urgent need for any of the generalizations that have been proposed, and even the Makeham correction term is of only marginal practical significance. But it does not predict the number of deaths 70-90 in recent years very precisely. For ages ca 70-80, it overestimates, and for ca 83-93, it underestimates mortality. A modification which operates "locally" and addresses this shortcoming might be of practical significance.

Plotting Gompertz mortality

Rather than estimating the Gompertz parameters (a,b) by maximum likelihood estimation (MLE), we have focused on the age range 50-90, approximating the log-mortality function by linear regression. In this, we follow (loosely) the method presented in demography course material by Germán Rodríguez of Princeton.

We construct the age vs deaths (x,dx) data from the lx column of the mortality table. Parameters are estimated, and plots of data and residues presented for selected years: 1967,1997,2007 and 2017.

The time development of the two parameters are also plotted, separately and vs each other. An "educated guess" of future values may be made from these plots: First, extrapolating the log(b)-value for the actual year, and then getting the a-value from the a vs log(b) linear regression from latter years. Drawing from the "guessed" Gompertz distribution may provide some basic information on future mortality, but the model fit for age distribution of deaths will probably not be very good for ca 70-90 years of age.

Because we focus on the age interval where >90% of deaths occur (ca 65-105), we don't consider the Makeham adaptation here - it is mostly influential below 50 years of age, and its inclusion does not help that much for the systematic deviations we observe. Nor do we explore the most immediate generalizations of the Gompertz distribution, e.g. x -> xk in the exponent: F(x) = 1 - exp(-b/a (eaxk-1)). Or Perks type distributions with hazard rate h(x) = (b exp(ax) + c)/(d exp(ax) + 1) .

Some R-code

We prepare a table with age and sex as background variables, and columns with lx for the years 1966-2017. All years are processed, and plots are produced for selected years and time evolution of the parameters.

paramEstimYear <- function(dF,mkPlot=0,yr=1967,regrStart=50) {
   prepareHazard <- function(hdF,plotcol=4,yr,regrStart=50,plotNum=1) {
        hdF$lx <- ifelse(hdF$lx>0,hdF$lx,2) 
        lxm <- mutate(hdF, lx = lx/100000, Hx = -log(lx)) ;
        lxhm <- data.frame(hx = diff(lxm$Hx), x = midpoints(lxm$age))
        lfm <- lm(log(hx) ~ I(x - regrStart), data = filter(lxhm, (x >=regrStart)&(x<=90)))
        lxhmf <- filter(lxhm, (x >= regrStart)&(x<=90)) %>%  mutate(hf = exp(fitted(lfm)))
      
        if (mkPlot==1) {
           if (plotNum==1) mainTitle <- paste("Year: ",yr) else mainTitle <- " " ;
           plot(lxhm$x,log(lxhm$hx),ylim=c(-11,0),col=plotcol,xlab="Age x",ylab="log(h(x)",main=mainTitle)
           abline(lfm$coef[1]-regrStart*lfm$coef[2],lfm$coef[2],col=plotcol,lty=4)
           plot((regrStart+1):90,lfm$resid,ylim=c(-0.7,0.7),col=plotcol,
           xlab="Age x",ylab="Residuals of log(h(x)")
        }
        list(lxhm=lxhm,lfcoef=lfm$coef,lfres=lfm$resid)  
    }
    
    yrM <- data.frame(dF$age,dF$maleYear) ;  yrF <- data.frame(dF$age,dF$femYear) ;
    names(yrM) <- c("age","lx") ;  names(yrF) <- c("age","lx") ;
    yrHM <- prepareHazard(yrM,plotcol=4,yr,regrStart,plotNum=1) ;
    yrHF <- prepareHazard(yrF,plotcol=2,yr,regrStart,plotNum=2) ;
    list(yrHM=yrHM,yrHF=yrHF)
}


paramEstimSeriesOfYears <- function(sT,years=1967:2017,mkPlot=0,regrStart=50) {
    resM <- matrix(0,nrow=length(years),ncol=5) ; resM[,1] <- years ;
    for (yr in 1:length(years)) {
        yearData <- prepareYear(sT,as.character(yr+years[1]-1)) ;
        pE <- paramEstimYear(yearData,regrStart=regrStart) ;
        resM[yr,2] <- pE$yrHM$lfcoef[1] ;  resM[yr,3] <- pE$yrHM$lfcoef[2] ;
        resM[yr,4] <- pE$yrHF$lfcoef[1] ;  resM[yr,5] <- pE$yrHF$lfcoef[2] ;
    }
    resM
}

plotMortalityParameters <- function(resM,regrStart=50,lastPerStart=2007,savePng=0) {

    yrs <- resM[,1] ; a0M <- resM[,2] - resM[,3]*regrStart ;  a0F <- resM[,4] - resM[,5]*regrStart ;
    aFitM <- lm(a0M~yrs) ;    bFitM <- lm(resM[,3]~yrs) ;
    aFitF <- lm(a0F~yrs) ;    bFitF <- lm(resM[,5]~yrs)
    aCoefM <- aFitM$coef ; bCoefM <- bFitM$coef ;
    aCoefF <- aFitF$coef ; bCoefF <- bFitF$coef ;

    aFitM25<- lm(a0M[yrs>lastPerStart]~resM[yrs>lastPerStart,1]) ;    
    bFitM25 <- lm(resM[yrs>lastPerStart,3]~resM[yrs>lastPerStart,1]) ;
    aFitF25 <- lm(a0F[yrs>lastPerStart]~resM[yrs>lastPerStart,1]) ;    
    bFitF25 <- lm(resM[yrs>lastPerStart,5]~resM[yrs>lastPerStart,1])
    aCoefM25 <- aFitM25$coef ; bCoefM25 <- bFitM25$coef ;
    aCoefF25 <- aFitF25$coef ; bCoefF25 <- bFitF25$coef ;    

    abM25<- lm(resM[yrs>lastPerStart,3]~a0M[yrs>lastPerStart]) ; 
    abF25<- lm(resM[yrs>lastPerStart,5]~a0F[yrs>lastPerStart]) ;  
    abCoefM25 <- abM25$coef ; abCoefF25 <- abF25$coef ;
    print(paste(abCoefM25, abCoefF25))
   
    if (savePng>0) png(filename='gomp_f1.png',width=1000,height=600)
    else  X11(width=12,height=6)
    par(mfrow=c(1,3))
    plot(yrs,a0M,col=4,ylim=c(-12.5,-9.5),xlab="Year",ylab="Basic mortality",main="Parameter a in y=a+bx")
    points(yrs,a0F,col=2)
    abline(aCoefM[1],aCoefM[2],col=4)
    abline(aCoefF[1],aCoefF[2],col=2)
    abline(aCoefM25[1],aCoefM25[2],col=4,lty=3)
    abline(aCoefF25[1],aCoefF25[2],col=2,lty=3)  
    legend(1990,-4.75,pch=c(1,1),col=c(4,2),legend=c("Males","Females"))
    
    plot(resM[,1],resM[,3],col=4,ylim=c(0.09,0.12),xlab="Year",ylab="Aging mortality component",
       main="Parameter b in y=a+bx")
    points(resM[,1],resM[,5],col=2)
    abline(bCoefM[1],bCoefM[2],col=4)
    abline(bCoefF[1],bCoefF[2],col=2)
    abline(bCoefM25[1],bCoefM25[2],col=4,lty=3)
    abline(bCoefF25[1],bCoefF25[2],col=2,lty=3)

    plot(a0M,resM[,3],col=4,xlim=c(-12.5,-9.5),ylim=c(0.09,0.12),xlab="a-parameter",
         ylab="b-parameter",main="b vs a parameters in y=a+bx")
    points(a0F,resM[,5],col=2)
    abline(abCoefM25[1],abCoefM25[2],lty=4,col=4)
    abline(abCoefF25[1],abCoefF25[2],lty=4,col=2)
   
    if (savePng>0) dev.off()
    else dev.copy2eps(device=x11,file='gomp_f1.eps') ;
 
    c(aCoefM25[1],aCoefM25[2],aCoefF25[1],aCoefF25[2],bCoefM25[1],bCoefM25[2],bCoefF25[1],bCoefF25[2])
}

processingGompertz <- function(mkPlotSlct=1,regrStart=50,savePng=0) {
    sT <- getSurvivalTable()
    resM <- paramEstimSeriesOfYears(sT,years=1967:2017,mkPlot=0,regrStart=regrStart) 
    regrC <- plotMortalityParameters(resM,savePng=savePng)

    if (mkPlotSlct==1) {
        if (savePng>0) png(filename='gomp_f2.png',width=1000,height=1200)
        else X11(height=12,width=12) ;
        par(mfrow=c(4,4)) ;
        y1967 <- prepareYear(sT,"1967");  pE <- paramEstimYear(y1967,mkPlot=1,yr=1967,regrStart=regrStart);
        y1997 <- prepareYear(sT,"1997");  pE <- paramEstimYear(y1997,mkPlot=1,yr=1997,regrStart=regrStart);
        y2007 <- prepareYear(sT,"2007");  pE <- paramEstimYear(y2007,mkPlot=1,yr=2007,regrStart=regrStart);
        y2017 <- prepareYear(sT,"2017");  pE <- paramEstimYear(y2017,mkPlot=1,yr=2017,regrStart=regrStart);
        
        if (savePng>0) dev.off()         
        else dev.copy2eps(device=x11,file='gomp_f2.eps') ;
    }
    list(regrC=regrC,resM=resM)
}

Git repository for this blog: https://github.com/tyder-no/r-and-friends

Mortality: Basic patterns and some systematic deviations

The basic qualitative pattern of the log-hazard rate plots has hardly changed over 50 years, but there are a number of features to note:

  • During the last 30 years, there has been a fairly stable deviation from linearity, as illustrated by the residuals for 70-90 years in most cases having an increasing linear tendency.
  • Mortality at 93-100 years is "back on track", in spite of these years not being included in the regression fit.
  • There is a roughly linear "Makeham-type" deviation ca 25-50, horizontal for men, but not for women.
  • The last 30 years, strong deviations from linear log-mortality at 50+ only occurs above 100 years of age.

Fig 1. Log mortality plots for 1967, 1997, 2007 and 2017. Males (blue) and females (red), residual plots for the regression fit, which is performed for the interval (50,90).

Time evolution of the hazard rate parameters

A common feature is that the "basic mortality", as described by the b-parameter in the linear fit to the log(hazard rate), has been declining for both men and women, with a much faster rate for men - but from a much higher level. After 2010, this rate has continued to fall, but now men's rates are similar to women's - whose reduction may in turn have accelerated the last 10 years. But the absolute levels are low.

50 years ago, women "aged" quite a bit faster than men, as indicated by the a-parameter in the linear fit to the log(hazard rate). While it decreased for some decades for women, it now seems to increase for both sexes, and coefficients are similar.

Fig 2. Panels 1 and 2: Gompertz mortality parameters a and b for males and females 1967-2017, with regression lines for the whole period and for 2007-2017. Note than while these regression fits for men are similar for the two periods, for women they deviate strongly. Panel 3 shows a vs b with regression lines 2007-2017. Changes in the parameters have been strongly correlated in the recent years. Note that the "b" parameter in the plot is actually log(b) from the distribution function, while the "a" parameter is the same.