El modelo SEIR es un modelo epidemiológico que divide a la población en cuatro compartimentos: Susceptibles (S), Expuestos (E), Infectados (I) y Recuperados (R). Este modelo es útil para enfermedades que tienen un período de latencia durante el cual los individuos están expuestos pero no son infecciosos.
Las ecuaciones diferenciales que describen el modelo SEIR son las siguientes: \[\begin{align*} \frac{dS}{dt} & = -\beta \frac{S I}{N} \\ \frac{dE}{dt} & = \beta \frac{S I}{N} - \sigma E \\ \frac{dI}{dt} & = \sigma E - \gamma I \\ \frac{dR}{dt} & = \gamma I \end{align*}\].
donde:
A continuación, implementaremos el modelo SEIR en R utilizando el
paquete deSolve para resolver las ecuaciones
diferenciales.
# Install if needed: install.packages("deSolve")
library(deSolve)
# para graficar
library(ggplot2)
library(tidyr)
# SEIR model function
seir_model <- function(time, state, parameters) {
with(as.list(c(state, parameters)), {
N <- S + E + I + R
dS <- -beta * S * I / N
dE <- beta * S * I / N - sigma * E
dI <- sigma * E - gamma * I
dR <- gamma * I
return(list(c(dS, dE, dI, dR)))
})
}
# Parameters
parameters <- c(
beta = 0.5, # transmission rate
sigma = 1/5.2, # 1/latent period (5.2 days for COVID-19)
gamma = 1/10 # 1/infectious period (10 days)
)
# Initial state
N <- 1
initial_state <- c(
S = N - 0.001,
E = 0.0005,
I = 0.0005,
R = 0
)
# Time vector (days)
times <- seq(0, 180, by = 1)
# Solve ODE
output <- ode(y = initial_state, times = times, func = seir_model, parms = parameters)
# Convert to data frame
output_df <- as.data.frame(output)
# Reshape data for ggplot
output_long <- output_df %>%
pivot_longer(cols = c(S, E, I, R), names_to = "Compartimento", values_to = "Count")
# Plot
ggplot(output_long, aes(x = time, y = Count, color = Compartimento)) +
geom_line(linewidth = 1.2) +
scale_color_manual(values = c("S" = "blue", "E" = "orange", "I" = "red", "R" = "green")) +
labs(x = "Tiempo (días)", y = "Fracción de Individuos") +
theme_minimal() +
theme(legend.position = "right")
Figura 1. Dinámica del modelo SEIR mostrando las fracciones de individuos en cada compartimento a lo largo del tiempo.
EJERCICIO 1: Modifique los parámetros del modelo (β, σ, γ) y observe cómo afectan la dinámica de la enfermedad. ¿Qué sucede si aumenta la tasa de transmisión β? ¿Y si disminuye la tasa de recuperación γ?
A continuación calcularemos algunas métricas claves de las epidemias:
Las cantidades de individuos están expresadas en fracciones de la población total N.
# 1. Maximum number of infectious individuals (I_max)
I_max <- max(output_df$I)
# 2. Time when peak occurs
time_peak <- output_df$time[which.max(output_df$I)]
# 3. Susceptible population at peak (S at peak)
S_at_peak <- output_df$S[which.max(output_df$I)]
# 4. Herd immunity threshold (theoretical)
R0 <- parameters["beta"] / parameters["gamma"]
HIT_theoretical <- 1 - (1 / R0) # Herd Immunity Threshold
S_threshold_theoretical <- N * (1 - HIT_theoretical) # Susceptibles at HIT
# 5. Final epidemic size (proportion infected)
final_R <- tail(output_df$R, 1)
attack_rate <- final_R / N
## ==================================================
## TABLA 1. Métricas Epidemiológicas del Modelo SEIR
## ==================================================
## Tamaño de la Población (N): 1
## Número básico de reproducción (R_0): 5
## --- Dinámica del Modelo---
## Pico de infecciones (I_max): 0.301 individuos
## Tiempo hasta el pico: 50 días
## Suceptibles en el pico (S_Imax): 0.123 individuos
## --- Umbral de Inmunidad de Rebaño ---
## Valor teórico de UIR: 80 %
## Fracción de S_UIR: 0.2 individuos
## --- Tamaño final de la Epidemia ---
## Infectados totales (attack rate): 99.302 %
## Recuperados finales: 0.993 individuos
## Suceptibles finales: 0.007 individuos
## ===============================================
gt# Instalar si es necesario: install.packages("gt")
library(gt)
library(dplyr)
# Crear data frame con las métricas
tabla_metricas <- data.frame(
Categoría = c(
"Parámetros Poblacionales",
"Parámetros Poblacionales",
"",
"Dinámica del Modelo",
"Dinámica del Modelo",
"Dinámica del Modelo",
"",
"Umbral de Inmunidad de Rebaño",
"Umbral de Inmunidad de Rebaño",
"",
"Tamaño Final de la Epidemia",
"Tamaño Final de la Epidemia",
"Tamaño Final de la Epidemia"
),
Métrica = c(
"Tamaño de la Población (N)",
"Número básico de reproducción (R₀)",
"",
"Pico de infecciones (I_max)",
"Tiempo hasta el pico",
"Susceptibles en el pico (S_Imax)",
"",
"Valor teórico de UIR",
"Fracción de S_UIR",
"",
"Infectados totales (attack rate)",
"Recuperados finales",
"Susceptibles finales"
),
Valor = c(
format(N, big.mark = ","),
round(R0, 2),
"",
format(round(I_max, 3), big.mark = ","),
time_peak,
format(round(S_at_peak, 3), big.mark = ","),
"",
paste0(round(HIT_theoretical * 100, 3), "%"),
format(round(S_threshold_theoretical, 3), big.mark = ","),
"",
paste0(round(attack_rate * 100, 3), "%"),
format(round(final_R, 3), big.mark = ","),
format(round(tail(output_df$S, 1), 3), big.mark = ",")
),
Unidad = c(
"individuos",
"adimensional",
"",
"individuos",
"días",
"individuos",
"",
"porcentaje",
"individuos",
"",
"porcentaje",
"individuos",
"individuos"
)
)
# Crear tabla con gt
tabla_gt <- tabla_metricas %>%
filter(Categoría != "") %>% # Eliminar filas vacías
gt() %>%
tab_header(
title = md("**TABLA 1. Métricas Epidemiológicas del Modelo SEIR**"),
subtitle = "Resultados de la simulación determinística"
) %>%
tab_row_group(
label = "Tamaño Final de la Epidemia",
rows = Categoría == "Tamaño Final de la Epidemia"
) %>%
tab_row_group(
label = "Umbral de Inmunidad de Rebaño",
rows = Categoría == "Umbral de Inmunidad de Rebaño"
) %>%
tab_row_group(
label = "Dinámica del Modelo",
rows = Categoría == "Dinámica del Modelo"
) %>%
tab_row_group(
label = "Parámetros Poblacionales",
rows = Categoría == "Parámetros Poblacionales"
) %>%
cols_hide(columns = Categoría) %>%
cols_label(
Métrica = "Métrica",
Valor = "Valor",
Unidad = "Unidad"
) %>%
cols_align(
align = "left",
columns = Métrica
) %>%
cols_align(
align = "right",
columns = c(Valor, Unidad)
) %>%
tab_style(
style = cell_text(weight = "bold"),
locations = cells_column_labels()
) %>%
tab_style(
style = cell_fill(color = "#E8F4F8"),
locations = cells_row_groups()
) %>%
tab_style(
style = cell_text(weight = "bold", size = px(13)),
locations = cells_row_groups()
) %>%
tab_options(
table.font.size = px(12),
heading.title.font.size = px(16),
heading.subtitle.font.size = px(13),
row_group.padding = px(8),
table.border.top.style = "solid",
table.border.bottom.style = "solid",
row_group.border.top.style = "solid",
row_group.border.bottom.style = "solid"
) %>%
tab_source_note(
source_note = md("*Nota: R₀ = β/γ; UIR = Umbral de Inmunidad de Rebaño*; individuos: fracción de N")
)
# Mostrar tabla
tabla_gt
| TABLA 1. Métricas Epidemiológicas del Modelo SEIR | ||
| Resultados de la simulación determinística | ||
| Métrica | Valor | Unidad |
|---|---|---|
| Parámetros Poblacionales | ||
| Tamaño de la Población (N) | 1 | individuos |
| Número básico de reproducción (R₀) | 5 | adimensional |
| Dinámica del Modelo | ||
| Pico de infecciones (I_max) | 0.301 | individuos |
| Tiempo hasta el pico | 50 | días |
| Susceptibles en el pico (S_Imax) | 0.123 | individuos |
| Umbral de Inmunidad de Rebaño | ||
| Valor teórico de UIR | 80% | porcentaje |
| Fracción de S_UIR | 0.2 | individuos |
| Tamaño Final de la Epidemia | ||
| Infectados totales (attack rate) | 99.302% | porcentaje |
| Recuperados finales | 0.993 | individuos |
| Susceptibles finales | 0.007 | individuos |
| Nota: R₀ = β/γ; UIR = Umbral de Inmunidad de Rebaño; individuos: fracción de N | ||