Ejercicio: Estadísticas Vitales en Epidemiología

Author

Dr. Juan Fidel Osuna-Ramos

Published

November 29, 2024

Estadísticas Vitales en Epidemiología

¿Qué son las Estadísticas Vitales?

Las estadísticas vitales son métricas clave que permiten analizar el estado de salud de una población. Entre las más comunes se encuentran:

- Tasa de natalidad: Número de nacimientos por cada 1,000 habitantes.

  • Tasa de mortalidad: Número de muertes por cada 1,000 habitantes.

  • Tasa de letalidad: Porcentaje de personas fallecidas entre las que padecieron una enfermedad específica.


Conjunto de Datos

Crear un Dataset Ficticio

Usaremos un conjunto de datos ficticio para realizar los cálculos:

# Crear un conjunto de datos ficticio
datos <- data.frame(
  region = c("Norte", "Sur", "Este", "Oeste"),
  poblacion = c(100000, 75000, 50000, 60000),
  nacimientos = c(1200, 800, 600, 700),
  muertes = c(900, 500, 300, 400),
  casos_enfermedad = c(1500, 1000, 800, 900),
  fallecidos_enfermedad = c(200, 150, 100, 120)
)

# Mostrar los primeros datos
print(datos)
  region poblacion nacimientos muertes casos_enfermedad fallecidos_enfermedad
1  Norte    100000        1200     900             1500                   200
2    Sur     75000         800     500             1000                   150
3   Este     50000         600     300              800                   100
4  Oeste     60000         700     400              900                   120

Tasa de Mortalidad

¿Qué es la Tasa de Mortalidad?

La Tasa de Mortalidad mide el número de muertes en una población por cada 1,000 habitantes durante un período determinado.

Es una métrica crucial para evaluar el impacto de factores que afectan la salud pública.


Fórmula

La fórmula general para calcular la Tasa de Mortalidad es:

Donde:

- Número de Muertes: Total de personas fallecidas en un año.

  • Población Total: Número total de habitantes en la población.

Implementación en R

Calculemos la Tasa de Mortalidad usando un ejemplo práctico:

# Datos
muertes <- 900  # Número de muertes en un año
poblacion_total <- 100000  # Población total en ese año

# Cálculo de la tasa de mortalidad
tasa_mortalidad <- (muertes / poblacion_total) * 1000

# Resultado
cat("Tasa de mortalidad:", tasa_mortalidad, "muertes por cada 1,000 habitantes\n")
Tasa de mortalidad: 9 muertes por cada 1,000 habitantes

Ejemplo Interpretativo

Supongamos que:

  • En una población de 100,000 personas ocurren 900 muertes durante un año.

El cálculo sería:

población <-  100000

muertes <- 900

Tasa_mortalidad2<- (muertes/población) * 1000

cat("Tasa de mortalidad:", Tasa_mortalidad2, "muertes por cada 1,000 habitantes\n")
Tasa de mortalidad: 9 muertes por cada 1,000 habitantes

Visualización de Tasa de Mortalidad

Usamos un gráfico de barras para visualizar las tasas de mortalidad en diferentes regiones:

library(ggplot2)

str(datos)
'data.frame':   4 obs. of  6 variables:
 $ region               : chr  "Norte" "Sur" "Este" "Oeste"
 $ poblacion            : num  100000 75000 50000 60000
 $ nacimientos          : num  1200 800 600 700
 $ muertes              : num  900 500 300 400
 $ casos_enfermedad     : num  1500 1000 800 900
 $ fallecidos_enfermedad: num  200 150 100 120
print(datos)
  region poblacion nacimientos muertes casos_enfermedad fallecidos_enfermedad
1  Norte    100000        1200     900             1500                   200
2    Sur     75000         800     500             1000                   150
3   Este     50000         600     300              800                   100
4  Oeste     60000         700     400              900                   120
# Calcular tasas de mortalidad

datos$tasa_mortalidad <- (datos$muertes / datos$poblacion) * 1000

print(datos)
  region poblacion nacimientos muertes casos_enfermedad fallecidos_enfermedad
1  Norte    100000        1200     900             1500                   200
2    Sur     75000         800     500             1000                   150
3   Este     50000         600     300              800                   100
4  Oeste     60000         700     400              900                   120
  tasa_mortalidad
1        9.000000
2        6.666667
3        6.000000
4        6.666667
# Gráfico
ggplot(datos, aes(x = region, y = tasa_mortalidad, fill = region)) +
  geom_bar(stat = "identity") +
  labs(title = "Tasa de Mortalidad por Región", x = "Región", y = "Tasa de Mortalidad (por 1,000 habitantes)") +
  theme_classic()


Reflexión

  1. ¿Qué regiones tienen la tasa de mortalidad más alta?

  2. ¿Qué factores pueden influir en la mortalidad regional?

  3. ¿Cómo podríamos usar esta información para priorizar intervenciones de salud pública?

Conclusión

La Tasa de Mortalidad es un indicador fundamental para medir el impacto de condiciones de salud y factores socioeconómicos en una población.

Comparar tasas entre regiones puede ayudar a identificar áreas que necesitan mayor atención.


Tasa de Letalidad

¿Qué es la Tasa de Letalidad?

La Tasa de Letalidad mide el porcentaje de personas fallecidas entre las que han padecido una enfermedad específica.

Es una métrica crucial para evaluar la gravedad de una enfermedad y la efectividad de las intervenciones médicas.

Fórmula

La fórmula general para calcular la Tasa de Letalidad es:

Donde:

- Número de Fallecidos: Total de personas que han muerto debido a la enfermedad. -

-Número de Casos: Total de personas diagnosticadas con la enfermedad.


Implementación en R

Calculemos la Tasa de Letalidad usando un ejemplo práctico:

Datos_fallecidos <- 200 # Número de fallecidos por la enfermedad 
casos <- 1500 # Número total de casos registrados

# Cálculo de la tasa de letalidad

tasa_letalidad <- (Datos_fallecidos / casos) * 100

# Resultado

cat("Tasa de letalidad:", tasa_letalidad, "% de los casos fallecen\n")
Tasa de letalidad: 13.33333 % de los casos fallecen

Ejemplo Interpretativo

Supongamos que:

  • En una población con 1,500 casos de una enfermedad, se registran 200 fallecidos.

El cálculo sería:

Visualización de Tasa de Letalidad

library(ggplot2)

datos
  region poblacion nacimientos muertes casos_enfermedad fallecidos_enfermedad
1  Norte    100000        1200     900             1500                   200
2    Sur     75000         800     500             1000                   150
3   Este     50000         600     300              800                   100
4  Oeste     60000         700     400              900                   120
  tasa_mortalidad
1        9.000000
2        6.666667
3        6.000000
4        6.666667
# Calcular tasas de letalidad
datos$tasa_letalidad <- (datos$fallecidos / datos$casos) * 100


# Gráfico
ggplot(datos, aes(x = region, y = tasa_letalidad, fill = region)) +
  geom_bar(stat = "identity") +
  labs(title = "Tasa de Letalidad por Región",
       x = "Región", y = "Tasa de Letalidad (%)") +
  theme_minimal()


Reflexión

  1. ¿Qué regiones tienen la tasa de letalidad más alta?

  2. ¿Cómo afecta la gravedad de una enfermedad a la tasa de letalidad?

  3. ¿Qué estrategias podrían implementarse para reducir esta tasa?

Conclusión

La Tasa de Letalidad es un indicador clave para evaluar la severidad de una enfermedad y el impacto de las intervenciones médicas. Un análisis detallado puede ayudar a identificar áreas prioritarias para la asignación de recursos.


Tasa de Natalidad

¿Qué es la Tasa de Natalidad?

La Tasa de Natalidad mide el número de nacimientos en una población por cada 1,000 habitantes durante un período determinado.

Es una métrica clave para analizar la dinámica poblacional y evaluar tendencias demográficas.

Fórmula

La fórmula general para calcular la Tasa de Natalidad es:


Implementación en R

Calculemos la Tasa de Natalidad usando un ejemplo práctico:

# Datos

nacimientos <- 1500  # Número de nacimientos en un año
poblacion_total <- 100000  # Población total en ese año

# Cálculo de la tasa de natalidad
tasa_natalidad <- (nacimientos / poblacion_total) * 1000

# Resultado
cat("Tasa de natalidad:", tasa_natalidad, "nacimientos por cada 1,000 habitantes\n")
Tasa de natalidad: 15 nacimientos por cada 1,000 habitantes

Ejemplo Interpretativo

Supongamos que:

  • En una población de 100,000 personas ocurren 1,500 nacimientos durante un año.

El cálculo sería:


Visualización de Tasa de Natalidad

Usamos un gráfico de barras para visualizar las tasas de natalidad en diferentes regiones:

library(ggplot2)

datos
  region poblacion nacimientos muertes casos_enfermedad fallecidos_enfermedad
1  Norte    100000        1200     900             1500                   200
2    Sur     75000         800     500             1000                   150
3   Este     50000         600     300              800                   100
4  Oeste     60000         700     400              900                   120
  tasa_mortalidad tasa_letalidad
1        9.000000       13.33333
2        6.666667       15.00000
3        6.000000       12.50000
4        6.666667       13.33333
# Calcular tasas de natalidad
datos$tasa_natalidad <- (datos$nacimientos / datos$poblacion) * 1000

# Gráfico
ggplot(datos, aes(x = region, y = tasa_natalidad, fill = region)) +
  geom_bar(stat = "identity") +
  labs(title = "Tasa de Natalidad por Región",
       x = "Región", y = "Tasa de Natalidad (por 1,000 habitantes)") +
  theme_minimal()


Reflexión

  1. ¿Qué regiones tienen la tasa de natalidad más alta?

  2. ¿Cómo podría influir la tasa de natalidad en la planificación de servicios de salud?

  3. ¿Qué otros factores deberíamos analizar para interpretar tendencias de natalidad?

Conclusión

La Tasa de Natalidad es una herramienta esencial en epidemiología para entender la dinámica poblacional. Usarla en conjunto con otras métricas puede proporcionar una visión completa de las tendencias demográficas y necesidades de salud pública.



Creamos una tabla con los datos generados:

Tabla de Estadísticas Vitales

Instalar y cargar las librerías necesarias

Si no tienes el paquete flextable, instálalo primero:


Creamos tabla con paquete flextable

Ventajas de flextable:

  1. Interactividad: Permite crear tablas fácilmente exportables a Word o PowerPoint.

  2. Estilo Personalizable: Cambia colores, fuentes y bordes sin complicaciones.

  3. Soporte para Reportes: Ideal para informes en formatos reproducibles.

Ambas opciones (kableExtra y flextable) son más simples y versátiles que gtable para este caso de uso.

#install.packages("flextable")
#install.packages("tidyverse")

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ lubridate 1.9.3     ✔ tibble    3.2.1
✔ purrr     1.0.2     ✔ tidyr     1.3.1
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(flextable)

Adjuntando el paquete: 'flextable'

The following object is masked from 'package:purrr':

    compose
# Crear el conjunto de datos
datos <- data.frame(
  region = c("Norte", "Sur", "Este", "Oeste"),
  poblacion = c(100000, 75000, 50000, 60000),
  nacimientos = c(1200, 800, 600, 700),
  muertes = c(900, 500, 300, 400),
  casos_enfermedad = c(1500, 1000, 800, 900),
  fallecidos_enfermedad = c(200, 150, 100, 120)
)

# Calcular las tasas
datos$tasa_natalidad <- (datos$nacimientos / datos$poblacion) * 1000
datos$tasa_mortalidad <- (datos$muertes / datos$poblacion) * 1000
datos$tasa_incidencia <- (datos$casos_enfermedad / datos$poblacion) * 1000
datos$tasa_letalidad <- (datos$fallecidos_enfermedad / datos$casos_enfermedad) * 100

# Redondear solo columnas numéricas
datos_redondeados <- datos %>%
  mutate_if(is.numeric, round, 2)

# Crear la tabla con flextable
flextable(datos_redondeados) %>%
  autofit()

region

poblacion

nacimientos

muertes

casos_enfermedad

fallecidos_enfermedad

tasa_natalidad

tasa_mortalidad

tasa_incidencia

tasa_letalidad

Norte

100,000

1,200

900

1,500

200

12.00

9.00

15.00

13.33

Sur

75,000

800

500

1,000

150

10.67

6.67

13.33

15.00

Este

50,000

600

300

800

100

12.00

6.00

16.00

12.50

Oeste

60,000

700

400

900

120

11.67

6.67

15.00

13.33


Frecuencias en R


Cálculo de Frecuencias

El análisis de frecuencias es una técnica básica pero esencial en epidemiología. Permite describir cómo se distribuyen los datos en categorías específicas y es especialmente útil para analizar variables categóricas como sexo, grupo de edad, o estado de enfermedad.


Cálculo de Frecuencias

Cargar Librerías

Primero, cargamos las librerías necesarias para el análisis:

library(dplyr)     # Para manipulación de datos %>% %>% %>% %>% %>%  control + shift + m = 
# %>% %>% %>% %>% %>% %>% %>% 
library(ggplot2)   # Para visualización de datos
library(tidyverse)

# control + alt + *+ = ~ 

#install.packages("janitor")
library(janitor)   # Para generar tablas de frecuencias

Adjuntando el paquete: 'janitor'
The following objects are masked from 'package:stats':

    chisq.test, fisher.test

Crear un Conjunto de Datos de Ejemplo

Usaremos un dataset ficticio para calcular las frecuencias:

# Crear un conjunto de datos ficticio
datos <- data.frame(
  sexo = c("F", "M", "F", "F", "M", "F", "M", "M", "F", "M"),
  grupo_edad = c("0-19", "20-39", "20-39", "40-59", "40-59", "60+", "20-39", "60+", "40-59", "0-19")
)

# Mostrar los primeros datos
head(datos)
  sexo grupo_edad
1    F       0-19
2    M      20-39
3    F      20-39
4    F      40-59
5    M      40-59
6    F        60+
str(datos)
'data.frame':   10 obs. of  2 variables:
 $ sexo      : chr  "F" "M" "F" "F" ...
 $ grupo_edad: chr  "0-19" "20-39" "20-39" "40-59" ...

Tablas de Frecuencias

Tabla de Frecuencias con table

Podemos calcular frecuencias simples usando table:

# Calcular frecuencias para la variable "sexo"
tabla_sexo <- table(datos$sexo)
tabla_sexo

F M 
5 5 

Tabla de Frecuencias Cruzadas con table

Para analizar dos variables:

# Tabla cruzada entre "sexo" y "grupo_edad"
tabla_cruzada <- table(datos$sexo, datos$grupo_edad)
tabla_cruzada
   
    0-19 20-39 40-59 60+
  F    1     1     2   1
  M    1     2     1   1

Tablas Limpias con janitor

El paquete janitor genera tablas de frecuencias ordenadas:

#install.packages("janitor")
library(janitor)
# Tabla de frecuencias con proporciones

tabla_ordenada <- datos %>%
  tabyl(sexo) %>%
  adorn_totals("row") %>%
  adorn_pct_formatting()

tabla_ordenada
  sexo  n percent
     F  5   50.0%
     M  5   50.0%
 Total 10  100.0%
flextable(tabla_ordenada)

sexo

n

percent

F

5

50.0%

M

5

50.0%

Total

10

100.0%


Paquete janitor

¿Qué es janitor? janitor es un paquete diseñado para limpiar datos y realizar análisis exploratorios rápidos. Es particularmente útil para manejar tablas y datos categóricos, como calcular frecuencias y proporciones.

Características Principales de janitor:

  1. Limpieza de Nombres de Columnas:

    • Convierte nombres de columnas en formato limpio y consistente, eliminando espacios o caracteres especiales.
library(janitor)
datos2 <- data.frame("Nombre Columna 1" = c(1, 2), "Otra Columna" = c(3, 4))

datos_clean <- clean_names(datos2) #función clean_names

print(datos_clean)  # nombres: nombre_columna_1, otra_columna
  nombre_columna_1 otra_columna
1                1            3
2                2            4

Tablas de Frecuencias:

  • Genera tablas de frecuencias simples y cruzadas.

  • Incluye totales y porcentajes para facilitar la interpretación.

    library(janitor)
    
    tabla <- datos %>% tabyl(grupo_edad)
    
    print(tabla)
     grupo_edad n percent
           0-19 2     0.2
          20-39 3     0.3
          40-59 3     0.3
            60+ 2     0.2

Tablas Ordenadas y Proporciones:

  • Añade totales y porcentajes a tablas de manera automática.
grupoedad<-tabla %>% adorn_totals("row") %>% adorn_pct_formatting()

grupoedad
 grupo_edad  n percent
       0-19  2   20.0%
      20-39  3   30.0%
      40-59  3   30.0%
        60+  2   20.0%
      Total 10  100.0%
flextable(grupoedad)

grupo_edad

n

percent

0-19

2

20.0%

20-39

3

30.0%

40-59

3

30.0%

60+

2

20.0%

Total

10

100.0%


Detección de Duplicados:

  • Identifica valores duplicados en tus datos.

    datos3 <- data.frame(id = c(1, 1, 2, 3), valor = c(10, 10, 20, 30))
    
    datos3
      id valor
    1  1    10
    2  1    10
    3  2    20
    4  3    30
    get_dupes(datos3, id)
      id dupe_count valor
    1  1          2    10
    2  1          2    10

¿Cuándo usar janitor?

  • Cuando necesitas calcular frecuencias rápidamente.

  • Para limpiar nombres de columnas automáticamente.

  • Al trabajar con datos categóricos donde las proporciones y totales son importantes.


Visualización de Frecuencias

Gráfico de Barras con ggplot2

Un gráfico de barras es ideal para visualizar frecuencias categóricas:

# Crear un gráfico de barras para "grupo_edad"
ggplot(datos, aes(x = grupo_edad, fill = grupo_edad)) +
  geom_bar() +
  labs(title = "Frecuencia por Grupo de Edad",
       x = "Grupo de Edad",
       y = "Frecuencia") +
  theme_minimal()

datos %>% ggplot(aes(grupo_edad, fill= grupo_edad))+
  geom_bar()


Gráfico de Pastel con ggplot2

Un gráfico de pastel es útil para mostrar proporciones:

# Calcular proporciones
proporciones <- datos %>%
  group_by(sexo) %>%
  summarise(frecuencia = n()) %>%
  mutate(proporcion = frecuencia / sum(frecuencia))

# Crear un gráfico de pastel
ggplot(proporciones, aes(x = "", y = proporcion, fill = sexo)) +
  geom_col(width = 1) +
  coord_polar(theta = "y") +
   theme_void()+
  labs(title = "Distribución por Sexo") 

flextable(tabla_ordenada)

sexo

n

percent

F

5

50.0%

M

5

50.0%

Total

10

100.0%

Tablas y Gráficos en un Reporte


Combinar Resultados en una Tabla Resumen

Podemos combinar frecuencias y proporciones en una tabla clara:

# Tabla resumen de frecuencias y proporciones
tabla_resumen <- datos %>%
  group_by(sexo) %>%
  summarise(
    frecuencia = n(),
    proporcion = n() / nrow(datos)
  )

tabla_resumen
# A tibble: 2 × 3
  sexo  frecuencia proporcion
  <chr>      <int>      <dbl>
1 F              5        0.5
2 M              5        0.5

Exportar Gráficos y Tablas

Guardar gráficos y tablas para incluirlos en reportes:

# Guardar el gráfico de barras como imagen
ggsave("frecuencia_grupo_edad.png")
Saving 7 x 5 in image
# Exportar la tabla resumen como CSV
write.csv(tabla_resumen, "tabla_resumen.csv")

Medidas de frecuencia

Las medidas de frecuencia son herramientas clave en epidemiología para cuantificar el impacto de enfermedades en una población. Las principales métricas son:

  1. Prevalencia: Proporción de individuos enfermos en un momento concreto.
  2. Incidencia acumulada: Probabilidad de que un individuo enferme durante un período.
  3. Densidad de incidencia: Velocidad con la que aparecen nuevos casos en una población.

Dataset Simulado

Crear un Dataset Ficticio

Usamos un conjunto de datos simulado para calcular estas métricas.

# Crear un conjunto de datos ficticio
datos <- data.frame(
  id = 1:100,  # Identificación de individuos
  inicio_riesgo = c(rep(0, 80), rep(1, 20)),  # 0 = no enfermo al inicio 1= enfermo 
  casos_nuevos = c(rep(0, 90), rep(1, 10)),  # Casos nuevos al final del período
  tiempo_observacion = c(rep(1, 50), rep(2, 30), rep(3, 20))  # Tiempo observado en años
  )

# Mostrar los primeros datos
head(datos)
  id inicio_riesgo casos_nuevos tiempo_observacion
1  1             0            0                  1
2  2             0            0                  1
3  3             0            0                  1
4  4             0            0                  1
5  5             0            0                  1
6  6             0            0                  1
View(datos)

Cálculo de Prevalencia

¿Qué es la Prevalencia?

La prevalencia mide la proporción de personas afectadas por una enfermedad en un momento dado.

Fórmula:

# Calcular prevalencia al inicio del período
poblacion_total <- nrow(datos)
poblacion_total <- 100

casos_existentes <- 20

casos_existentes <- sum(datos$inicio_riesgo == 1)

casos_existentes <- sum(datos$inicio_riesgo != 0)

prevalencia <- casos_existentes / poblacion_total


cat("Prevalencia:", round(prevalencia * 100, 2), "%\n")
Prevalencia: 20 %
cat("Prevalencia:", prevalencia*100, "%\n")
Prevalencia: 20 %

Interpretación: Este valor indica el porcentaje de la población afectada al inicio del estudio.

Cálculo de Incidencia Acumulada

¿Qué es la Incidencia Acumulada?

La incidencia acumulada mide la proporción de nuevos casos en una población en riesgo durante un período.

Fórmula:

# Calcular incidencia acumulada
casos_nuevos <- sum(datos$casos_nuevos)

casos_nuevos <- 10

poblacion_riesgo <- sum(datos$inicio_riesgo == 0)

poblacion_riesgo <- sum(datos$inicio_riesgo != 1)

poblacion_riesgo <- 80

incidencia_acumulada <- casos_nuevos / poblacion_riesgo

cat("Incidencia Acumulada:", round(incidencia_acumulada * 100, 2), "%\n")
Incidencia Acumulada: 12.5 %

Interpretación: Este valor indica el riesgo de desarrollar la enfermedad durante el período de observación.

Cálculo de Densidad de Incidencia

¿Qué es la Densidad de Incidencia?

La densidad de incidencia mide la velocidad con la que aparecen nuevos casos en una población durante períodos de tiempo acumulados.

Fórmula:

# Calcular densidad de incidencia
tiempo_total <- sum(datos$tiempo_observacion)

densidad_incidencia <- casos_nuevos / tiempo_total

cat("Densidad de Incidencia:", round(densidad_incidencia, 2), "casos por persona-año\n")
Densidad de Incidencia: 0.06 casos por persona-año

Interpretación: Este valor representa cuántos casos nuevos se generan por persona-año.

Visualización de las Métricas

Gráfico Comparativo

library(ggplot2)

# Crear datos para el gráfico
resultados <- data.frame(
  medida = c("Prevalencia", "Incidencia Acumulada", "Densidad de Incidencia"),
  valor = c(prevalencia * 100, incidencia_acumulada * 100, densidad_incidencia)
)

# Gráfico de barras
ggplot(resultados, aes(x = medida, y = valor, fill = medida)) +
  geom_bar(stat = "identity") +
  labs(title = "Medidas de Frecuencia Epidemiológica",
       x = "Medida", y = "Valor (%)") +
  theme_minimal()

Reflexión

  1. ¿Cómo afecta el tamaño de la población en riesgo a estas métricas?

  2. ¿Por qué es importante considerar el tiempo en la densidad de incidencia?

  3. ¿Qué otras métricas podrían complementar este análisis?

Conclusión

  1. La prevalencia ayuda a comprender la carga actual de la enfermedad.

  2. La incidencia acumulada mide el riesgo de enfermar.

  3. La densidad de incidencia captura la velocidad de propagación en el tiempo.

Herramientas adicionales

Número básico de Reproducción R0

Aalgunas herramientas adicionales y modernas que se usan para analizar el impacto de enfermedades en una población incluyen:

El número básico de reproducción R₀ es una métrica clave en epidemiología para estimar cuántos casos secundarios genera un caso inicial en una población completamente susceptible. Es esencial para evaluar el potencial de propagación de enfermedades infecciosas como el COVID-19.

El número básico de reproducción R₀ indica el promedio de casos secundarios generados por un caso inicial en una población completamente susceptible.

Cómo calcular R₀

El cálculo de R₀ puede realizarse usando varias metodologías. Una de las más comunes se basa en la relación:

Donde:

  • β (tasa de transmisión): Probabilidad de que una persona infectada transmita la enfermedad por unidad de tiempo.

  • D (duración infecciosa): Tiempo promedio durante el cual una persona infectada puede transmitir la enfermedad.

Para calcularlo usando datos reales del COVID-19, podemos usar un data.frame simulado o datos reales si se dispone de ellos.

Usamos un conjunto de datos que simula la propagación del COVID-19 en una población.

## Dataset Simulado de COVID-19

set.seed(123)

datos <- data.frame(
  id = 1:30,
  fecha = seq(as.Date("2020-03-01"), as.Date("2020-03-30"), by = "days"),
  nuevos_casos = round(runif(30, 50, 150)),  # Nuevos casos diarios
  recuperados = round(runif(30, 30, 100)),  # Recuperaciones diarias
  fallecidos = round(runif(30, 1, 10)))      # Fallecimientos diarios


# Mostrar los primeros datos
head(datos)
  id      fecha nuevos_casos recuperados fallecidos
1  1 2020-03-01           79          97          7
2  2 2020-03-02          129          93          2
3  3 2020-03-03           91          78          4
4  4 2020-03-04          138          86          3
5  5 2020-03-05          144          32          8
6  6 2020-03-06           55          63          5
View(datos)

Calcular R₀: Método Simplificado

Definición

Para estimar R₀, necesitamos:

  1. Duración infecciosa promedio (D): Asumimos 10 días para COVID-19.

  2. Crecimiento exponencial (λ): Calculado a partir de la tasa de nuevos casos diarios.

Paso 1: Calcular Crecimiento Diario

# Crecimiento diario de casos
datos$crecimiento <- c(NA, diff(datos$nuevos_casos))

# Calcular el promedio del crecimiento diario
lambda <- mean(datos$crecimiento, na.rm = TRUE)

cat("Crecimiento diario promedio (λ):", round(lambda, 2), "casos por día\n")
Crecimiento diario promedio (λ): -0.48 casos por día

Paso 2: Calcular R₀

# Asumimos una duración infecciosa promedio D = 10 días
D <- 10

# Estimación de R₀
R0 <- lambda * D
cat("Número básico de reproducción (R₀):", round(R0, 2), "\n")
Número básico de reproducción (R₀): -4.83 

Visualización del Número R₀

Gráfico de Nuevos Casos

library(ggplot2)

ggplot(datos, aes(x = fecha, y = nuevos_casos)) +
  geom_line(color = "blue", size = 1) +
  geom_point(color = "red") +
  labs(title = "Nuevos Casos Diarios de COVID-19",
       x = "Fecha", y = "Nuevos Casos") +
  theme_minimal()
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
ℹ Please use `linewidth` instead.

Reflexión

  1. ¿Cómo influye la duración infecciosa promedio (D) en el cálculo de R₀?

  2. ¿Qué intervenciones (como cuarentenas o vacunación) pueden reducir β y, por ende, R₀?

  3. ¿Qué significa un R₀ > 1 para la propagación de la enfermedad?

Detalles del Ejemplo

  1. Duración Infecciosa Promedio (D):
    • Se puede ajustar con base en evidencia clínica, como estudios que estimen cuánto tiempo los pacientes con COVID-19 son infecciosos.
  2. Datos Simulados:
    • En este ejemplo, los datos son generados aleatoriamente. Puedes reemplazarlos con datos reales del COVID-19 de fuentes como Our World in Data o bases gubernamentales.
  3. Crecimiento Diario (λ):
    • El crecimiento promedio se calcula con la diferencia diaria de nuevos casos.

Uso de Paquetes Adicionales

Si deseas usar herramientas específicas para el cálculo de R₀, puedes explorar paquetes como EpiEstim:

#install.packages("EpiEstim")
library(EpiEstim)

# Calcular R₀ usando EpiEstim (reemplazar con datos reales)
res <- estimate_R(
  incid = datos$nuevos_casos,
  method = "parametric_si",
  config = make_config(list(mean_si = 4, std_si = 2))
)
Default config will estimate R on weekly sliding windows.
    To change this change the t_start and t_end arguments. 
print(res$R)
   t_start t_end   Mean(R)     Std(R) Quantile.0.025(R) Quantile.0.05(R)
1        2     8 1.8082252 0.06393042         1.6850783        1.7043697
2        3     9 1.4353848 0.05152731         1.3361563        1.3516944
3        4    10 1.2467022 0.04461051         1.1607888        1.1742431
4        5    11 1.1482292 0.04087804         1.0694969        1.0818283
5        6    12 1.0189277 0.03745653         0.9468270        0.9581099
6        7    13 1.0716845 0.03781893         0.9988328        1.0102459
7        8    14 1.0649133 0.03748672         0.9926984        1.0040124
8        9    15 0.9476635 0.03512275         0.8800653        0.8906412
9       10    16 0.9824765 0.03556804         0.9139920        0.9247135
10      11    17 0.9613033 0.03529055         0.8933702        0.9040013
11      12    18 0.8488428 0.03329435         0.7848326        0.7948308
12      13    19 0.8450341 0.03345522         0.7807265        0.7907684
13      14    20 0.9111145 0.03533150         0.8431727        0.8537886
14      15    21 0.9926585 0.03759962         0.9203226        0.9316328
15      16    22 1.1028381 0.04010983         1.0256149        1.0377030
16      17    23 1.0661098 0.03945849         0.9901650        1.0020472
17      18    24 1.1517991 0.04062082         1.0735492        1.0858081
18      19    25 1.2134514 0.04123476         1.1339680        1.1464322
19      20    26 1.2229790 0.04067568         1.1445451        1.1568513
20      21    27 1.1125698 0.03787232         1.0395699        1.0510169
21      22    28 1.0242927 0.03548964         0.9559061        0.9666248
22      23    29 0.9486615 0.03368796         0.8837746        0.8939381
23      24    30 0.8849380 0.03244340         0.8224841        0.8322581
   Quantile.0.25(R) Median(R) Quantile.0.75(R) Quantile.0.95(R)
1         1.7647040 1.8074719        1.8509252        1.9146506
2         1.4003022 1.4347682        1.4697952        1.5211781
3         1.2163299 1.2461702        1.2764946        1.3209762
4         1.1203994 1.1477442        1.1755303        1.2162848
5         0.9934197 1.0184687        1.0439354        1.0813110
6         1.0459394 1.0712397        1.0969448        1.1346406
7         1.0393949 1.0644735        1.0899523        1.1273145
8         0.9237430 0.9472296        0.9711110        1.0061658
9         0.9582581 0.9820474        1.0062272        1.0417036
10        0.9372706 0.9608714        0.9848652        1.0200782
11        0.8261551 0.8484075        0.8710559        0.9043394
12        0.8222347 0.8445926        0.8673523        0.9008057
13        0.8870413 0.9106578        0.9346898        0.9699980
14        0.9670458 0.9921838        1.0177537        1.0553034
15        1.0755259 1.1023519        1.1296202        1.1696318
16        1.0392368 1.0656230        1.0924522        1.1318328
17        1.1241467 1.1513216        1.1789310        1.2194189
18        1.1853903 1.2129844        1.2410034        1.2820638
19        1.1953034 1.2225280        1.2501630        1.2906447
20        1.0867965 1.1121401        1.1378747        1.1755885
21        1.0001371 1.0238828        1.0480014        1.0833586
22        0.9257272 0.9482628        0.9711611        1.0047450
23        0.8628445 0.8845416        0.9065993        0.9389703
   Quantile.0.975(R)
1          1.9356534
2          1.5381168
3          1.3356392
4          1.2297181
5          1.0936365
6          1.1470641
7          1.1396277
8          1.0177273
9          1.0534001
10         1.0316903
11         0.9153265
12         0.9118505
13         0.9816513
14         1.0676919
15         1.1828244
16         1.1448208
17         1.2327625
18         1.2955889
19         1.3039753
20         1.1880116
21         1.0950083
22         1.0158143
23         0.9496449

R₀ o Rₑ

El número básico de reproducción R₀ es un indicador esencial para evaluar el potencial epidémico de una enfermedad. Su cálculo permite diseñar estrategias de control efectivas, como reducir la transmisión o disminuir la duración infecciosa mediante tratamientos.

El número de reproducción efectivo (Rₑ) mide cuántas personas son infectadas por un caso en un momento dado, considerando medidas de control y cambios en la población susceptible.

El paquete EpiEstim facilita el cálculo de Rₑ y su evolución temporal.

Dataset Simulado

Crear un Dataset Simulado

Generamos datos ficticios de un brote epidémico:

#  install.packages("EpiEstim")

library(EpiEstim)

Simulamos el brote epidemico (ficticio):

set.seed(123)
dias <- 30

casos <- round(runif(dias, min = 10, max = 100))

datos <- data.frame(
  fecha = seq(as.Date("2020-01-01"), by = "days", length.out = dias),
  nuevos_casos = casos
)

# Mostrar los primeros datos
head(datos)
       fecha nuevos_casos
1 2020-01-01           36
2 2020-01-02           81
3 2020-01-03           47
4 2020-01-04           89
5 2020-01-05           95
6 2020-01-06           14

Configuración del Intervalo Serial

Definir el Intervalo Serial

El intervalo serial representa el tiempo promedio entre infecciones primarias y secundarias. En COVID-19, estudios sugieren una distribución gamma con:

  • Media: 4 días

  • Desviación estándar: 2 días

# Configurar el intervalo serial
config <- make_config(
  list(mean_si = 4, std_si = 2)) # Normalmente, make_config se utiliza para crear o gestionar configuraciones

Calcular el Número de Reproducción Efectivo (Rₑ)

Estimar Rₑ

Usamos los datos diarios de nuevos casos para calcular Rₑ.

# Estimar Rₑ usando EpiEstim
resultado <- estimate_R(
  incid = datos$nuevos_casos,
  method = "parametric_si",
  config = config
)
Default config will estimate R on weekly sliding windows.
    To change this change the t_start and t_end arguments. 
# Mostrar resultados
print(resultado$R)
   t_start t_end   Mean(R)     Std(R) Quantile.0.025(R) Quantile.0.05(R)
1        2     8 1.8593765 0.08531405         1.6959020        1.7213078
2        3     9 1.4572531 0.06839228         1.3262723        1.3466120
3        4    10 1.2616828 0.05895456         1.1487648        1.1663023
4        5    11 1.1625656 0.05391269         1.0592863        1.0753311
5        6    12 0.9929245 0.04839218         0.9003308        0.9146897
6        7    13 1.0913620 0.04991774         0.9957052        1.0105730
7        8    14 1.0910978 0.04969814         0.9958527        1.0106587
8        9    15 0.9153806 0.04515240         0.8290116        0.8423991
9       10    16 0.9703550 0.04615508         0.8819897        0.8957051
10      11    17 0.9384689 0.04562992         0.8511554        0.8646967
11      12    18 0.7664445 0.04150530         0.6872449        0.6994758
12      13    19 0.7585442 0.04175648         0.6789014        0.6911923
13      14    20 0.8607546 0.04568411         0.7735336        0.7870144
14      15    21 0.9882266 0.05049602         0.8917223        0.9066606
15      16    22 1.1697495 0.05602084         1.0625135        1.0791538
16      17    23 1.1100069 0.05461987         1.0055219        1.0217190
17      18    24 1.2499814 0.05705358         1.1406450        1.1576402
18      19    25 1.3438984 0.05810179         1.2324185        1.2497787
19      20    26 1.3511005 0.05664108         1.2423519        1.2593036
20      21    27 1.1719269 0.05080948         1.0744448        1.0896237
21      22    28 1.0356267 0.04608478         0.9472600        0.9610077
22      23    29 0.9234467 0.04264081         0.8417525        0.8544459
23      24    30 0.8279688 0.04020972         0.7510248        0.7629583
   Quantile.0.25(R) Median(R) Quantile.0.75(R) Quantile.0.95(R)
1         1.8011440 1.8580719        1.9161869        2.0018956
2         1.4105586 1.4561833        1.5027814        1.5715434
3         1.2214339 1.2607646        1.3009308        1.3601951
4         1.1257621 1.1617323        1.1984608        1.2526425
5         0.9598701 0.9921384        1.0251220        1.0738407
6         1.0572910 1.0906010        1.1246034        1.1747467
7         1.0571784 1.0903433        1.1241948        1.1741106
8         0.8845347 0.9146383        0.9454174        0.9908942
9         0.9388379 0.9696233        1.0010746        1.0475009
10        0.9073022 0.9377295        0.9688296        1.0147634
11        0.7380563 0.7656954        0.7940162        0.8359684
12        0.7299779 0.7577781        0.7862755        0.8285092
13        0.8295165 0.8599465        0.8911118        0.9372513
14        0.9537150 0.9873667        1.0218008        1.0727260
15        1.1314925 1.1688554        1.2070319        1.2633955
16        1.0726944 1.1091112        1.1463430        1.2013505
17        1.2110408 1.2491134        1.2879758        1.3452832
18        1.3042663 1.3430612        1.3826178        1.4408740
19        1.3124775 1.3503091        1.3888608        1.4455971
20        1.1372680 1.1711927        1.2057855        1.2567346
21        1.0041817 1.0349432        1.0663267        1.1125773
22        0.8943394 0.9227904        0.9518386        0.9946860
23        0.8005047 0.8273180        0.8547235        0.8951993
   Quantile.0.975(R)
1          2.0302652
2          1.5943133
3          1.3798182
4          1.2705803
5          1.0899851
6          1.1913432
7          1.1906304
8          1.0059679
9          1.0628784
10         1.0299843
11         0.8499009
12         0.8425403
13         0.9525677
14         1.0896177
15         1.2820670
16         1.2195824
17         1.3642500
18         1.4601360
19         1.4643466
20         1.2735814
21         1.1278776
22         1.0088701
23         0.9086114

Interpretación: El resultado muestra valores de Rₑ estimados para cada ventana de tiempo.

Visualización de Rₑ

Gráfico de la Evolución de Rₑ

Creamos un gráfico que muestra cómo Rₑ cambia con el tiempo, lo que puede indicar el impacto de intervenciones.

# Gráfico de Rₑ
plot(
  resultado,
  what = "R",
  legend = FALSE,
  main = "Evolución del Número de Reproducción Efectivo (Rₑ)"
)

Interpretación:

  • Rₑ > 1: La epidemia está en expansión.

  • Rₑ < 1: La epidemia está disminuyendo.

La función estimate_R del paquete {EpiEstim} en R se utiliza para estimar el número de reproducción efectivo (Rₑ), es una métrica clave en epidemiología para medir la capacidad de transmisión de una enfermedad infecciosa en una población a lo largo del tiempo.

Practica

Introducción

En esta práctica calcularemos , Rₑ y R para varias enfermedades infecciosas utilizando parámetros reales. Estos valores son cruciales para comprender la dinámica de transmisión y el impacto de medidas de control.


Valores para las enfermedades Infecciosas

  1. COVID-19 (SARS-CoV-2):

    • Tasa de transmisión: ~99.4% (alta transmisión en entornos cerrados) .

    • Tasa de mortalidad: 0.185% .

    • Duración infecciosa: ~10 días .

    • Distanciamiento social: ~30% puede reducir significativamente la transmisión.

      Referencia: Estimation of the reproduction number of SARS-CoV-2.

  2. MERS-CoV (Middle East Respiratory Syndrome):

  3. Influenza Estacional:

  4. Tuberculosis:

  5. Sarampión:

Simularemos la propagación de 5 enfermedades infecciosas con diferentes tasas de transmisión, mortalidad y duración infecciosa. Estas simulaciones se basarán en parámetros obtenidos de la literatura científica.

# Parámetros de las enfermedades
enfermedades <- data.frame(
  Enfermedad = c("COVID-19", "MERS-CoV", "Influenza Estacional", "Tuberculosis", "Sarampión"),
  Tasa_Transmision = c(99.4, 5, 60, 30, 95), # Porcentaje
  Tasa_Mortalidad = c(0.185, 35, 0.1, 15, 0.2), # Porcentaje
  Duracion_Infecciosa = c(10, 14, 7, 180, 8), # Días
  Distanciamiento_Social = c(30, 0, 15, 10, 0), # Porcentaje
  Poblacion = c(1000000, 1000000, 1000000, 1000000, 1000000) # Población para simulación
)

Cálculo de R₀

Fórmula de R₀

  1. R₀ (Número básico de reproducción):

    • Representa el número promedio de infecciones secundarias causadas por un individuo infectado en una población completamente susceptible.

    • Fórmula:

# Calcular R₀ para cada enfermedad
enfermedades$R0 <- (enfermedades$Tasa_Transmision / 100) * enfermedades$Duracion_Infecciosa

# Mostrar resultados
enfermedades[c("Enfermedad", "R0")]
            Enfermedad    R0
1             COVID-19  9.94
2             MERS-CoV  0.70
3 Influenza Estacional  4.20
4         Tuberculosis 54.00
5            Sarampión  7.60

Cálculo de Rₑ

Fórmula de Rₑ

Calcula Re onsiderando que no toda la población es susceptible (debido a inmunidad o intervenciones).

Fórmula:

# Considerar 70% de la población inicial como susceptibles
enfermedades$Susceptibles <- enfermedades$Poblacion * 0.7

# Calcular Rₑ
enfermedades$Re <- enfermedades$R0 * (enfermedades$Susceptibles / enfermedades$Poblacion)

# Mostrar resultados
enfermedades[c("Enfermedad", "R0", "Re")]
            Enfermedad    R0     Re
1             COVID-19  9.94  6.958
2             MERS-CoV  0.70  0.490
3 Influenza Estacional  4.20  2.940
4         Tuberculosis 54.00 37.800
5            Sarampión  7.60  5.320

Cálculo de Rₜ

Dinámica Temporal de Rₜ

Consideramos intervenciones como distanciamiento social y cambios en los susceptibles a lo largo del tiempo.

# Crear un data frame para simular la dinámica temporal
dias <- 30
resultado_rt <- data.frame()

for (i in 1:nrow(enfermedades)) {
  enfermedad <- enfermedades[i, ]
  susceptibles <- enfermedad$Susceptibles
  rt <- numeric(dias)
  
  for (t in 1:dias) {
    rt[t] <- enfermedad$R0 * (susceptibles / enfermedad$Poblacion) * (1 - enfermedad$Distanciamiento_Social / 100)
    susceptibles <- max(0, susceptibles - (susceptibles * enfermedad$Tasa_Transmision / 100)) # Reducir susceptibles
  }
  
  resultado_rt <- rbind(resultado_rt, data.frame(Dia = 1:dias, R_t = rt, Enfermedad = enfermedad$Enfermedad))
}

# Mostrar resultados para una enfermedad
head(resultado_rt[resultado_rt$Enfermedad == "COVID-19", ])
  Dia          R_t Enfermedad
1   1 4.870600e+00   COVID-19
2   2 2.922360e-02   COVID-19
3   3 1.753416e-04   COVID-19
4   4 1.052050e-06   COVID-19
5   5 6.312298e-09   COVID-19
6   6 3.787379e-11   COVID-19

Visualización de Rₜ

Gráfico para Cada Enfermedad

library(ggplot2)

# Gráfico de Rₜ
ggplot(resultado_rt, aes(x = Dia, y = R_t, color = Enfermedad)) +
  geom_line(size = 1) +
  geom_hline(yintercept = 1, linetype = "dashed", color = "red") +
  labs(title = "Evolución de Rt por Enfermedad", 
       x = "Días", y = "Rt") +
  theme_minimal() +
  scale_color_brewer(palette = "Set1")

Reflexión

  1. R₀: Proporciona el potencial de propagación inicial de cada enfermedad.

  2. Rₑ: Muestra cómo las dinámicas poblacionales reducen el potencial de transmisión.

  3. Rₜ: Evalúa el impacto de medidas de control (como distanciamiento social) en tiempo real.

Bonus track:

Podemos crear una función en R para simular la enfermedad

En el siguiente bloque de codigo se crea la función simular_enfermedad

# Crear una función de simulación
simular_enfermedad <- function(enfermedad, tasa_transmision, tasa_mortalidad, duracion, dist_social, poblacion = 1000) {
  dias <- 30
  infecciosos <- 1  # Casos iniciales
  recuperados <- 0
  fallecidos <- 0
  susceptibles <- poblacion - infecciosos
  
  resultado <- data.frame(Dia = 1:dias, Infectados = NA, Recuperados = NA, Fallecidos = NA, Susceptibles = NA)
  
  for (dia in 1:dias) {
    nuevas_infecciones <- round((infecciosos * tasa_transmision / 100) * (1 - dist_social / 100))
    nuevas_infecciones <- min(nuevas_infecciones, susceptibles)  # No exceder susceptibles
    
    nuevos_recuperados <- ifelse(dia > duracion, infecciosos / duracion, 0)
    nuevos_fallecidos <- round((tasa_mortalidad / 100) * infecciosos)
    
    infecciosos <- infecciosos + nuevas_infecciones - nuevos_recuperados - nuevos_fallecidos
    recuperados <- recuperados + nuevos_recuperados
    fallecidos <- fallecidos + nuevos_fallecidos
    susceptibles <- poblacion - infecciosos - recuperados - fallecidos
    
    resultado[dia, ] <- c(dia, infecciosos, recuperados, fallecidos, susceptibles)
  }
  return(resultado)
}

Una vez creada la función ahora podemos utilizarla:

Vamos a crear un objeto que garde los datos simulados de una enfermedad ( puede ser de los datos que ya revisamos en la literatura)

# Simulación de ejemplo para COVID-19
sim_covid <- simular_enfermedad(
  "COVID-19", tasa_transmision = 99.4, tasa_mortalidad = 20, 
  duracion = 10, dist_social = 30, poblacion = 1000
)
library(ggplot2)

# Gráfico para COVID-19
ggplot(sim_covid, aes(x = Dia)) +
  geom_line(aes(y = Infectados, color = "Infectados")) +
  geom_line(aes(y = Recuperados, color = "Recuperados")) +
  geom_line(aes(y = Fallecidos, color = "Fallecidos")) +
  geom_line(aes(y = Susceptibles, color = "Susceptibles")) +
  labs(title = "Simulación de Covid-19", 
       x = "Días", y = "Número de Personas") +
  scale_color_manual(name = "Estado", values = c("Infectados" = "red", 
                                                 "Recuperados" = "green", 
                                                 "Fallecidos" = "black", 
                                                 "Susceptibles" = "blue")) +
  theme_minimal()

Reflexión

  1. ¿Cómo afecta el distanciamiento social a las infecciones?

  2. ¿Qué enfermedad mostró mayor propagación y por qué?

  3. ¿Cómo pueden estas simulaciones informar estrategias de control?

Conclusión

La simulación permite visualizar la dinámica de transmisión y el impacto de intervenciones como el distanciamiento social. Los resultados pueden usarse para planificar respuestas ante brotes reales.

Además, permite analizar la dinámica de la propagación de enfermedades bajo diferentes escenarios de intervención y parámetros epidemiológicos.

Siguientes pasos:

  • Ajustar parámetros para escenarios específicos.

  • Comparar entre diferentes poblaciones y entornos.