Propósito de la sesión. A partir del juego mostrado por el profesor, cada equipo construye su propia tabla de vida y la función de sobrevivencia \(S(x)\) en R .
Objetivos - Ejecutar en R una simulación discreta de mortalidad por edades. - Construir: \(l_x, d_x, q_x, p_x, S_x\) y estimar \( \hat{e}_0 \approx \sum_x S_x \). - Comunicar hallazgos con gráficos y una interpretación breve.
Dinámica (hoy) 1) Demo del profesor (juego). 2) Trabajo en equipos (este archivo). 3) Entrega al final.
Entregables (hoy) - Tabla con columnas:
Edad, lx, dx, qx, px, Sx
. - Dos gráficos: línea de \(S(x)\)
y barras de \(d_x\). - Estimación de \(\hat{e}_0\) y 1
párrafo de interpretación técnica.
Rúbrica breve (10 pts): Correctitud (4), claridad del código (2), visualización (2), interpretación (2).
library(...)
para cargar.set.seed()
= resultados
repetibles.write.csv()
o
readr::write_csv()
.# Instala SOLO si aún no los tienes (ejecútalo una vez y comenta):
# install.packages(c("tidyverse","ggplot2","dplyr","readr","purrr","ggplot2","knitr"))
library(tidyverse)
library(readr)
library(knitr)
set.seed(params$seed)
A continuación definimos tres reglas para \(q_x\).
Elige una en params$q_model
.
linear
: \(q_x = \min(x/m, 1)\) — crece linealmente con
la edad.gompertz
: \(q_x = \min(A\,e^{B x}, 1)\) — mortalidad
creciente exponencial (ancianidad).weibull
: \(q_x = \min(\alpha\,x^{\beta}, 1)\) —
flexible, potencia de la edad.qfun_linear <- function(x, m) pmin(x / m, 1)
qfun_gompertz <- function(x, m, A = 0.002, B = 0.35) {
pmin(A * exp(B * x), 1)
}
qfun_weibull <- function(x, m, alpha = 0.002, beta = 2) {
pmin(alpha * (x ^ beta), 1)
}
get_qfun <- function(model = c("linear","gompertz","weibull")) {
model <- match.arg(model)
switch(model,
linear = function(x, m) qfun_linear(x, m),
gompertz = function(x, m) qfun_gompertz(x, m),
weibull = function(x, m) qfun_weibull(x, m))
}
La simulación recorre edades \(x = 0, 1, \dots, m\). En cada edad usamos \(q_x\) para decidir cuántos mueren (ensayos Bernoulli independientes).
Parámetros activos
params
## $l0
## [1] 40
##
## $edad_max
## [1] 12
##
## $q_model
## [1] "linear"
##
## $seed
## [1] 123
##
## $censura
## [1] 0
simulate_cohort <- function(l0, edad_max, q_model = "linear", censura = 0) {
stopifnot(l0 > 0, edad_max >= 1, censura >= 0, censura <= 1)
qfun <- get_qfun(q_model)
lx <- integer(edad_max + 1)
dx <- integer(edad_max + 1)
cx <- integer(edad_max + 1) # censuras por edad (opcional)
qxv <- numeric(edad_max + 1)
pxv <- numeric(edad_max + 1)
Sv <- numeric(edad_max + 1)
lx[1] <- l0
qxv[1] <- 0
pxv[1] <- NA
Sv[1] <- 1
for (x in 1:edad_max) {
qx <- qfun(x, edad_max)
# Muertes por Bernoulli(lx[x], qx)
muertes <- sum(runif(lx[x]) < qx)
# Censura aleatoria independiente
cens <- if (censura > 0) sum(runif(lx[x] - muertes) < censura) else 0
dx[x+1] <- muertes
cx[x+1] <- cens
lx[x+1] <- lx[x] - muertes - cens
qxv[x+1] <- qx
pxv[x+1] <- 1 - qx
Sv[x+1] <- lx[x+1] / l0
if (lx[x+1] <= 0) {
# completar filas restantes con ceros si se extingue la cohorte
lx[(x+2):(edad_max+1)] <- 0
dx[(x+2):(edad_max+1)] <- 0
cx[(x+2):(edad_max+1)] <- 0
qxv[(x+2):(edad_max+1)] <- NA
pxv[(x+2):(edad_max+1)] <- NA
Sv[(x+2):(edad_max+1)] <- 0
break
}
}
tabla <- tibble(
Edad = 0:edad_max,
lx = lx,
dx = c(NA, dx[-1]),
cx = c(NA, cx[-1]),
qx = round(qxv, 4),
px = round(pxv, 4),
Sx = round(Sv, 4)
)
# Esperanza de vida discreta aproximada (área bajo S)
e0 <- sum(Sv, na.rm = TRUE)
list(tabla = tabla, e0 = e0)
}
res <- simulate_cohort(
l0 = params$l0,
edad_max = params$edad_max,
q_model = params$q_model,
censura = params$censura
)
tabla_vida <- res$tabla
e0_est <- res$e0
kable(head(tabla_vida, 10), caption = "Primeras 10 filas de la tabla de vida simulada")
Edad | lx | dx | cx | qx | px | Sx |
---|---|---|---|---|---|---|
0 | 40 | NA | NA | 0.0000 | NA | 1.000 |
1 | 37 | 3 | 0 | 0.0833 | 0.9167 | 0.925 |
2 | 29 | 8 | 0 | 0.1667 | 0.8333 | 0.725 |
3 | 22 | 7 | 0 | 0.2500 | 0.7500 | 0.550 |
4 | 13 | 9 | 0 | 0.3333 | 0.6667 | 0.325 |
5 | 11 | 2 | 0 | 0.4167 | 0.5833 | 0.275 |
6 | 3 | 8 | 0 | 0.5000 | 0.5000 | 0.075 |
7 | 0 | 3 | 0 | 0.5833 | 0.4167 | 0.000 |
8 | 0 | 0 | 0 | NA | NA | 0.000 |
9 | 0 | 0 | 0 | NA | NA | 0.000 |
Esperanza de vida aproximada
e0_est
## [1] 3.875
# S(x)
ggplot(tabla_vida, aes(Edad, Sx)) +
geom_line(linewidth = 1) +
geom_point() +
labs(title = "Función de sobrevivencia S(x)", y = "S(x)") +
theme_minimal()
# dx (muertes por edad)
ggplot(tabla_vida[-1,], aes(Edad, dx)) +
geom_col() +
labs(title = "Muertes por edad (dx)", y = "dx") +
theme_minimal()
Pregunta guía: ¿Cómo cambia la curvatura de \(S(x)\) cuando cambias el modelo
q_model
oedad_max
?
compare_cohorts <- function(l0, edad_max, model_a = "linear", model_b = "gompertz") {
A <- simulate_cohort(l0, edad_max, model_a)$tabla %>% mutate(Modelo = model_a)
B <- simulate_cohort(l0, edad_max, model_b)$tabla %>% mutate(Modelo = model_b)
bind_rows(A, B)
}
comp <- compare_cohorts(params$l0, params$edad_max, "linear", "gompertz")
ggplot(comp, aes(Edad, Sx, color = Modelo)) +
geom_line(linewidth = 1) + geom_point() +
labs(title = "Comparación de S(x) entre modelos", y = "S(x)") +
theme_minimal()
Genera archivos para tu entrega o para usarlos en otra sesión.
write_csv(tabla_vida, "tabla_vida_equipo.csv")
Archivos generados:
tabla_vida_equipo.csv
en la carpeta del proyecto.
Escribe aquí tu párrafo de interpretación (máx. 8–10 líneas).
params$censura
): si
> 0
, en cada edad se retira aleatoriamente un % de la
cohorte (abandono/traslado). Útil para discutir sesgo si no se modela
censura.A
,
B
, alpha
, beta
dentro de las
funciones si necesitas curvas más/menos agresivas.