I've spent last several weeks learning about survival analysis, see one of the last posts at How to simulate variability (errors) in fitting a gamma model to survival data by using a generalized minimum extreme value distribution in R?
Now I am primarily concerned with simulating death rates and secondarily deriving survival curves for the deceased. Ultimately, this is leading towards simulating deaths/survival using extreme value distributions with heavy right tails (even if not best-fitting) for simulating conservative, very-bad-case scenarios especially when dealing with a paucity of data. The code below is a first step in that direction.
Does the approach I describe and per the code below appear reasonable? If so, are there easier or better approaches?
- I use the
lung
dataset from thesurvival
package as my example. - I use bootstrap sampling (
bootSample()
in code below) to derive death rates (deathRate <- ...
) and to extract the lung data for only the deaths from the same bootstrapped samples where "status" == 2 (bootDeaths[[i]] <<- ...
). - Using AIC, lognormal provided the best fit for bootstrap sampled death rates. Code not shown for this goodness-of-fit testing.
- I draw lognormal random samples for each of the bootstrap samples and derive a histogram of death rates per the image below on the left.
- I then take the deaths from the same bootstrapped samples and fitting the deaths with the
survreg()
function and applying the lognormal distribution, plot their survival curves (plot_survival_curves(...)
) as shown in the image below on the right.
Code:
library(MASS)
library(survival)
nbr <- 100
timeLine <- seq(0, max(lung$time))
bootDeaths <- list()
# Use bootstrapping for both average death rates and for plotting survival curves for deaths
bootSample <- sapply(
1:100,
function(i) {
sampleData <- lung[sample(nrow(lung), replace = TRUE), ]
bootDeaths[[i]] <<- sampleData[sampleData$status == 2, ] # used in plotting death survival curves later
deathRate <- with(sampleData, mean(status == 2))
return(deathRate)
}
)
### Generate random samples for the lognormal distribution, calculate and plot death rates ###
fit <- MASS::fitdistr(bootSample,"lognormal")
params <- fit$estimate
sampLognorm <- rlnorm(1000, params[1], params[2])
hist(sampLognorm, breaks = "FD", col = "steelblue",
xlab = "Death rate", ylab = "Frequency", main = "Histogram of Lognormal Samples")
sampDeathRate <- mean(bootSample)
abline(v = sampDeathRate, col = "black", lty = 1, lwd = 3)
popDeathRate <- with(lung, mean(status == 2))
abline(v = popDeathRate, col = "red", lty = 1, lwd = 3)
legend("topright", legend = c(paste("Sample Average:", round(sampDeathRate, 4)),
paste("Population Average:", round(popDeathRate, 4))),
lty = c(1,1), lwd = c(3,3), col = c("black", "red"), bty = "n")
### Lognormal survival curves for patients who die ###
plot(timeLine, type = "n", xlab = "Time", ylab = "Survival Probability", main = "Lung Data Survival Plot", ylim = c(0, 1), xlim = c(0,max(lung$time)))
# Fit lognormal distribution and plot survival curves for each deceased sample
plot_survival_curves <- sapply(
1:nbr,
function(i){
sampleDat <- data.frame(bootDeaths[[i]])
fit <- survreg(Surv(time, status == 2) ~ 1, data = sampleDat, dist = "lognormal")
meanlog <- fit$coef
sdlog <- fit$scale
surv_prob <- 1 - plnorm(timeLine, meanlog = meanlog, sdlog = sdlog)
lines(seq(0,length(surv_prob)-1), surv_prob, col = "lightblue", lty = "solid", lwd = 0.25)
}
)