library(dplyr)
library(ggplot2)
library(latex2exp)
library(knitr)
library(kableExtra)
El objetivo de esta práctica es generar desde cero los métodos no paramétricos para la función de Supervivencia, los métodos son:
Se divide el tiempo en intervalos y se calcula \(S(t)\) dentro de cada intervalo, el proceso es el siguiente:
Se divide el eje de tiempo en \(k+1\) intervalos, en este caso se toma como limite inferior el \(0\) y como límite superior \(\lceil \text{max}\{T_i\}\rceil\) donde \(T_i\) son los tiempos de fallo observados.
Cada intervalo es de la forma: \[l_j=(a_{j-1},a_j]\] Se calculan:
\[\hat q_j=1-\frac{d_j}{n_j-\frac{c_j}{2}}\]
* \(p_j=1-q_j\) es la probabilidad de sobrevivir hasta \(a_j\) despues de haver sobrevivido hasta \(a_{j-1}\).
Si no hay censuras en \(l_j\), entonces \(n_j^*=n_j\)
Finalmente se calcula \(\hat S(t)\) como:
\[\hat S_j=\prod_{i=1}^jp_j\] Se cargan los datos
myeloma<-read.csv("Myeloma_data.csv")
d<-data.frame(myeloma)
options(digits=4)
La siguiente función sigue el proceso descrito anteriormente y devuelve una tabla que contiene la informacion relevante sobre el método Actuarial.
#Funcion que calcula la supervivencia mediante el metodo actuarial
#d:conjunto de datos(dataframe)
#k:numero de intervalos
#La funcion devuelve una tabla($tabla) y un vector de tiempos($t)
metodo_actuarial<-function(d,k){
#longitud de cada intervalo
l=ceiling(max(d$Survival_time))/k
#generamos los vectores que contienen los intervalos aj-1 y aj,
#donde [-(k+1)] se usa para eliminar el ultimo elemento ya que no nos sirve
aj_1=seq(0,l*k,l)[-(k+1)]
aj=lead(seq(0,l*k,l))[-(k+1)]
#obtenemos lo siguiente:
#nj: cantidad de supervivientes a tiempo aj-1
#nj ajustado: ajuste sobre nj
#dj: numero de fallas en el intervalo (aj-1,aj]
#cj: numero de censuras en el intervalo (aj-1,aj]
#pj: probabilidad de sobrevivir hasta aj, despues de haber sobrevivido hasta aj-1
nj<-rep(0,k+1)
nj_ajustado<-rep(0,k+1)
dj<-rep(0,k+1)
cj<-rep(0,k+1)
pj<-rep(0,k+1)
Sj<-rep(1,k+1)
intervalo<-seq(1,k)
for(i in 1:k){
nj[i] = nrow(subset(d, Survival_time>aj_1[i]))
dj[i] = nrow(subset(d, Survival_time>aj_1[i] & Survival_time<=aj[i] & Status==1))
cj[i] = nrow(subset(d, Survival_time>aj_1[i] & Survival_time<=aj[i] & Status==0))
nj_ajustado[i]=nj[i]-cj[i]/2
pj[i] = 1-(dj[i]/nj_ajustado[i])
Sj[i+1] = prod(pj[1:i])
intervalo[i] = paste("(",round(aj_1[i],3),",",round(aj[i],3),"]",sep = "")
}
intervalo[k+1] = paste(">",aj[k],sep = "")
tabla<-data.frame(intervalo,dj,cj,nj,nj_ajustado,Sj)
#la funcion devuelve la tabla y un vector con los tiempos que sirve para graficar
return(list(tabla=tabla,t=seq(0,l*k,l)[-(k)]))
}
Generemos la tabla con \(15\) intervalos.
k=15
metodo_act<-metodo_actuarial(d,k)
#le damos formato a la tabla
kable(metodo_act$tabla, caption = "Método Actuarial"
, align = c('c', 'c', 'c', 'c', 'c', 'c'),
col.names=c("Intervalo","$d_j$", "$c_j$", "$n_j$", "$n^{*}_j$", "$S(t)$")) %>%
kable_styling(full_width = F, bootstrap_options = c("striped", "hover", "condensed"))
| Intervalo | \(d_j\) | \(c_j\) | \(n_j\) | \(n^{*}_j\) | \(S(t)\) |
|---|---|---|---|---|---|
| (0,6.067] | 11 | 1 | 48 | 47.5 | 1.0000 |
| (6.067,12.133] | 7 | 4 | 36 | 34.0 | 0.7684 |
| (12.133,18.2] | 7 | 3 | 25 | 23.5 | 0.6102 |
| (18.2,24.267] | 2 | 0 | 15 | 15.0 | 0.4285 |
| (24.267,30.333] | 0 | 0 | 13 | 13.0 | 0.3713 |
| (30.333,36.4] | 1 | 0 | 13 | 13.0 | 0.3713 |
| (36.4,42.467] | 2 | 1 | 12 | 11.5 | 0.3428 |
| (42.467,48.533] | 0 | 0 | 9 | 9.0 | 0.2831 |
| (48.533,54.6] | 2 | 1 | 9 | 8.5 | 0.2831 |
| (54.6,60.667] | 0 | 1 | 6 | 5.5 | 0.2165 |
| (60.667,66.733] | 2 | 0 | 5 | 5.0 | 0.2165 |
| (66.733,72.8] | 0 | 0 | 3 | 3.0 | 0.1299 |
| (72.8,78.867] | 0 | 1 | 3 | 2.5 | 0.1299 |
| (78.867,84.933] | 0 | 0 | 2 | 2.0 | 0.1299 |
| (84.933,91] | 2 | 0 | 2 | 2.0 | 0.1299 |
| >91 | 0 | 0 | 0 | 0.0 | 0.0000 |
La gráfica es la siguiente:
ggplot()+
geom_step(aes(x=metodo_act$t,y=metodo_act$tabla$Sj[1:k], color = "Método-Actuarial"),size=1)+
theme_bw()+
labs(title="Función de Supervivencia", x = "Tiempo", y = TeX("$\\hat{S}(t)$")) +
scale_color_manual(breaks=c("Método-Actuarial","K-M") ,values = c("Método-Actuarial"="steelblue","K-M"="#c45d16")) +
theme(legend.position = "top", legend.direction = "horizontal", plot.title = element_text(hjust = 0.5))+
labs(color = "Estimador")
Se define el soporte \(\{u_1,u_2,...\}\) de los tiempos de fallo \(T_1,T_2,...,T_n\), dado que es posible obtener observacions repetidas.
Se calculan:
Se calcula \(\hat S(t)\) como:
\[\hat S(t)=\prod_{k:u_k\leq t}\left(1-\frac{d_k}{n_k}\right)\]
La siguiente función sigue el proceso descrito anteriormente y devuelve una tabla que contiene la informacion relevante sobre el método K-M.
#Funcion que calcula la supervivencia mediante el metodo Kaplan-Meier
#d:conjunto de datos(dataframe)
K_M<-function(d){
#determinamos el soporte de los tiempos(uk)
t<-sort(unique(d$Survival_time))
l<-length(t)
#se calculan:
#dk:numero de tiempos de fallo iguales a uk
#nk:numero de individuos en riesgo a tiempo uk
#ck:numero de censuras a tiempo uk
#Sk:supervivencia
dk<-rep(0,l)
nk<-rep(0,l)
ck<-rep(0,l)
Sk<-rep(1,l)
pk<-rep(0,l)
for(i in 1:(l)){
dk[i] = nrow(subset(d, Survival_time==t[i] & Status==1))
ck[i] = nrow(subset(d, Survival_time==t[i] & Status==0))
nk[i] = nrow(subset(d, Survival_time>=t[i]))
pk[i] = 1-dk[i]/nk[i]
Sk[i] = prod(pk[1:i])
}
tabla<-data.frame(t,dk,nk,ck,Sk)
return(tabla)
}
metodo_KM<-K_M(d)
#le damos formato a la tabla resultante
kable(metodo_KM, caption = "Método K-M"
, align = c('c', 'c', 'c', 'c', 'c'),
col.names=c("Tiempo","$d_k$", "$n_k$", "$c_k$", "$S(t)$")) %>%
kable_styling(full_width = F, bootstrap_options = c("striped", "hover", "condensed"))
| Tiempo | \(d_k\) | \(n_k\) | \(c_k\) | \(S(t)\) |
|---|---|---|---|---|
| 1 | 3 | 48 | 0 | 0.9375 |
| 3 | 0 | 45 | 1 | 0.9375 |
| 4 | 2 | 44 | 0 | 0.8949 |
| 5 | 4 | 42 | 0 | 0.8097 |
| 6 | 2 | 38 | 0 | 0.7670 |
| 7 | 0 | 36 | 1 | 0.7670 |
| 8 | 1 | 35 | 0 | 0.7451 |
| 10 | 4 | 34 | 1 | 0.6575 |
| 11 | 0 | 29 | 1 | 0.6575 |
| 12 | 2 | 28 | 1 | 0.6105 |
| 14 | 1 | 25 | 0 | 0.5861 |
| 15 | 1 | 24 | 1 | 0.5617 |
| 16 | 2 | 22 | 0 | 0.5106 |
| 17 | 1 | 20 | 0 | 0.4851 |
| 18 | 2 | 19 | 2 | 0.4340 |
| 23 | 1 | 15 | 0 | 0.4051 |
| 24 | 1 | 14 | 0 | 0.3761 |
| 36 | 1 | 13 | 0 | 0.3472 |
| 40 | 2 | 12 | 1 | 0.2893 |
| 50 | 1 | 9 | 0 | 0.2572 |
| 51 | 1 | 8 | 0 | 0.2250 |
| 52 | 0 | 7 | 1 | 0.2250 |
| 56 | 0 | 6 | 1 | 0.2250 |
| 65 | 1 | 5 | 0 | 0.1800 |
| 66 | 1 | 4 | 0 | 0.1350 |
| 76 | 0 | 3 | 1 | 0.1350 |
| 88 | 1 | 2 | 0 | 0.0675 |
| 91 | 1 | 1 | 0 | 0.0000 |
La gráfica es la siguiente:
ggplot()+
geom_step(aes(x=metodo_KM$t,y=metodo_KM$Sk, color = "K-M"),size=1)+
theme_bw()+
labs(title="Función de Supervivencia", x = "Tiempo", y = TeX("$\\hat{S}(t)$")) +
scale_color_manual(breaks=c("Método-Actuarial","K-M") ,values = c("Método-Actuarial"="steelblue","K-M"="#c45d16")) +
theme(legend.position = "top", legend.direction = "horizontal", plot.title = element_text(hjust = 0.5))+
labs(color = "Estimador")
Realizamos una comparación gráfica de ambos modelos
ggplot()+
geom_step(aes(x=metodo_act$t,y=metodo_act$tabla$Sj[1:k], color = "Método-Actuarial"),size=1)+
geom_step(aes(x=metodo_KM$t,y=metodo_KM$Sk, color = "K-M"),size=1)+
theme_bw()+
labs(title="Función de Supervivencia", x = "Tiempo", y = TeX("$\\hat{S}(t)$")) +
scale_color_manual(breaks=c("Método-Actuarial","K-M") ,values = c("Método-Actuarial"="steelblue","K-M"="#c45d16")) +
theme(legend.position = "top", legend.direction = "horizontal", plot.title = element_text(hjust = 0.5))+
labs(color = "Estimador")
Si usamos una mayor cantidad de intervalos para el método actuarial, la grafica de \(S(t)\) se “suavizará” más. Para \(k=30\) se obtiene la siguiente gráfica.
k=30
metodo_act<-metodo_actuarial(d,k)
ggplot()+
geom_step(aes(x=metodo_act$t,y=metodo_act$tabla$Sj[1:k], color = "Método-Actuarial"),size=1)+
geom_step(aes(x=metodo_KM$t,y=metodo_KM$Sk, color = "K-M"),size=1)+
theme_bw()+
labs(title="Función de Supervivencia", x = "Tiempo", y = TeX("$\\hat{S}(t)$")) +
scale_color_manual(breaks=c("Método-Actuarial","K-M") ,values = c("Método-Actuarial"="steelblue","K-M"="#c45d16")) +
theme(legend.position = "top", legend.direction = "horizontal", plot.title = element_text(hjust = 0.5))+
labs(color = "Estimador")