2.5 Hazards in software
Software 2.5.1 (The Weibull functions). \(S\), \(h\) and \(\exp (-H)\) at \(t = 5\) for Weibull distributions with scale \(10\) and shapes \(0.5\), \(1\), \(2\); a check that \(f = hS\) integrates to \(1\); and the mean of the \(k = 2\) distribution as the area under \(S\) and from the formula \(\lambda \Gamma (1 + 1/k)\):
> S <- function(t, k, lam) exp(-(t / lam)^k) # Weibull survival
> h <- function(t, k, lam) (k / lam) * (t / lam)^(k - 1) # and its hazard
> H <- function(t, k, lam) (t / lam)^k # cumulative hazard
> for (k in c(0.5, 1, 2)) {
+ cat(sprintf("k = %3.1f S(5) = %.4f h(5) = %.4f exp(-H(5)) = %.4f\n",
+ k, S(5, k, 10), h(5, k, 10), exp(-H(5, k, 10))))
+ }
k = 0.5 S(5) = 0.4931 h(5) = 0.0707 exp(-H(5)) = 0.4931
k = 1.0 S(5) = 0.6065 h(5) = 0.1000 exp(-H(5)) = 0.6065
k = 2.0 S(5) = 0.7788 h(5) = 0.1000 exp(-H(5)) = 0.7788
> f <- function(t) h(t, 2, 10) * S(t, 2, 10) # density = h S
> integrate(f, 0, Inf)$value # integrates to 1
[1] 1
> c(mean_by_integral = integrate(function(t) S(t, 2, 10), 0, Inf)$value,
+ mean_by_formula = 10 * gamma(1 + 1/2))
mean_by_integral mean_by_formula
8.862269 8.862269
Reading the output. In every case \(S(5) = \exp (-H(5))\), as Theorem 2.3.2 requires. At \(t = 5\) the decreasing hazard (\(k = 0.5\)) has already removed half the population, while the increasing one (\(k = 2\)) has removed only \(22\%\). The area under \(S\) gives the mean \(8.862\), equal to \(10\,\Gamma (1.5)\).
Python: scipy.stats.weibull_min(c=k, scale=10) provides sf, pdf and mean.
Software 2.5.2 (Medians, memory and residual life). For the exponential with mean \(10\): the median, the conditional probability of surviving \(5\) more units having survived \(10\), and the unconditional probability of surviving \(5\). Then the same comparison, the median and the mean residual life at ages \(0, 5, 10, 20\) for the Weibull with \(k = 2\):
> lam <- 0.1 # exponential, mean 10 > c(median = log(2) / lam, mean = 1 / lam) median mean 6.931472 10.000000 > c(P_survive_5_more_given_10 = exp(-lam * 15) / exp(-lam * 10), + P_survive_5_from_start = exp(-lam * 5)) # memoryless P_survive_5_more_given_10 P_survive_5_from_start 0.6065307 0.6065307 > Sw <- function(t) S(t, 2, 10) # Weibull k = 2: ageing > c(Sw(15) / Sw(10), Sw(5)) # conditional is lower [1] 0.2865048 0.7788008 > med <- uniroot(function(t) Sw(t) - 0.5, c(0, 100), tol = 1e-10)$root > c(median = med, formula = 10 * log(2)^(1/2)) median formula 8.325546 8.325546 > mrl <- function(t) integrate(Sw, t, Inf)$value / Sw(t) # mean residual life > round(sapply(c(0, 5, 10, 20), mrl), 3) [1] 8.862 5.456 3.789 2.263
Reading the output. The exponential’s median, \(6.93\), is below its mean \(10\), and its conditional and unconditional probabilities are both \(0.607\): it is memoryless. For the Weibull with increasing hazard, surviving \(5\) more units after \(10\) has probability \(0.287\), much less than \(0.779\) from new: it ages. Its median is \(8.33 = 10\sqrt {\log 2}\), and its mean residual life falls from \(8.86\) when new to \(2.26\) at age \(20\).
Python: scipy.integrate.quad for the residual life integral.
Software 2.5.3 (A Gompertz life table). Example 2.4.2: the probabilities of surviving from \(30\) to \(60\), \(80\) and \(90\), the median age at death, the probability of reaching \(80\) from \(60\), and the doubling time of the hazard:
> a <- 5e-5; b <- 0.09 # Gompertz hazard a e^(b x) > Hg <- function(x, x0) (a / b) * (exp(b * x) - exp(b * x0)) > Sg <- function(x, x0 = 30) exp(-Hg(x, x0)) # from age 30 > round(c(to_60 = Sg(60), to_80 = Sg(80), to_90 = Sg(90)), 4) to_60 to_80 to_90 0.8916 0.4791 0.1617 > uniroot(function(x) Sg(x) - 0.5, c(30, 120), tol = 1e-8)$root # median [1] 79.34316 > round(Sg(80) / Sg(60), 4) # P(reach 80 | alive at 60) [1] 0.5373 > round(log(2) / b, 2) # hazard doubling time [1] 7.7
Reading the output. \(89\%\) of \(30\)-year-olds reach \(60\) and \(48\%\) reach \(80\); the median age at death is \(79.3\); of those alive at \(60\), \(54\%\) reach \(80\). The hazard doubles every \(7.7\) years, close to the eight years observed in many populations.
Python: the same functions with numpy.exp and scipy.optimize.brentq for the median.
Questions on this section
Stuck on something here? Ask below and it stays attached to this topic.