library(readxl)
library(tidyverse)
library(janitor)
library(lubridate)
library(zoo)
## 
## Adjuntando el paquete: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(scales)
## 
## Adjuntando el paquete: 'scales'
## The following object is masked from 'package:purrr':
## 
##     discard
## The following object is masked from 'package:readr':
## 
##     col_factor
library(gt)
library(readxl)
df <- read_excel("2. covid_example_data.xlsx")
head(df)
## # A tibble: 6 × 31
##   PID            reprt_creationdt_FALSE case_dob_FALSE      case_age case_gender
##   <chr>          <dttm>                 <dttm>                 <dbl> <chr>      
## 1 3a85e6992a5ac… 2020-03-22 00:00:00    2004-11-08 00:00:00       16 Male       
## 2 c6b5281d5fc50… 2020-02-01 00:00:00    1964-06-07 00:00:00       57 Male       
## 3 53495ad0dca4e… 2020-02-10 00:00:00    1944-04-06 00:00:00       77 Female     
## 4 2948a265da0d0… 2020-03-20 00:00:00    1964-06-25 00:00:00       57 Female     
## 5 a5524aadd1ca0… 2020-02-26 00:00:00    1964-12-21 00:00:00       56 Male       
## 6 db14eeabe531f… 2020-02-11 00:00:00    1956-06-21 00:00:00       65 Male       
## # ℹ 26 more variables: case_race <chr>, case_eth <chr>, case_zip <dbl>,
## #   Contact_id <chr>, sym_startdt_FALSE <dttm>, sym_fever <chr>,
## #   sym_subjfever <chr>, sym_myalgia <chr>, sym_losstastesmell <chr>,
## #   sym_sorethroat <chr>, sym_cough <chr>, sym_headache <chr>,
## #   sym_resolved <chr>, sym_resolveddt_FALSE <dttm>, contact_household <chr>,
## #   hospitalized <chr>, hosp_admidt_FALSE <dttm>, hosp_dischdt_FALSE <dttm>,
## #   died <chr>, died_covid <chr>, died_dt_FALSE <dttm>, confirmed_case <chr>, …
# Información básica de la base
dimensiones <- dim(df)
n_filas <- dimensiones[1]
n_columnas <- dimensiones[2]
fechas_min_max <- range(dmy(df$reprt_creationdt_FALSE), na.rm = TRUE)
## Warning: All formats failed to parse. No formats found.
## Warning in min.default(structure(numeric(0), class = "Date"), na.rm = FALSE):
## ningún argumento finito para min; retornando Inf
## Warning in max.default(structure(numeric(0), class = "Date"), na.rm = FALSE):
## ningun argumento finito para max; retornando -Inf
# Variables principales
variables_principales <- names(df)
variables_demograficas <- c("case_gender", "case_race", "case_eth", "case_age")
variables_sintomas <- c("sym_fever", "sym_subjfever", "sym_myalgia", "sym_losstastesmell", 
                        "sym_sorethroat", "sym_cough", "sym_headache")
variables_clinicas <- c("hospitalized", "died", "confirmed_case")

# Valores faltantes
valores_faltantes <- sum(is.na(df))

#Analisis# El conjunto de datos está conformado por 30 registros y 31 variables, con un rango temporal que abarca desde el 2 de enero de 2020 hasta el 19 de mayo de 2021. Las variables se agrupan principalmente en categorías demográficas, clínicas y de síntomas. Se identifican valores faltantes en varias columnas, lo que sugiere la necesidad de considerar la completitud de la información en los análisis posteriores.

La base incluye información demográfica (como género, raza, grupo étnico y edad), síntomas reportados, así como datos sobre hospitalización y desenlaces clínicos. Este tipo de información resulta fundamental para caracterizar el perfil epidemiológico de los casos y analizar la evolución de la enfermedad en distintos grupos poblacionales.

library(dplyr)
library(lubridate)
library(janitor)
library(dplyr)

df <- df %>%
  mutate(age_group = case_when(
    case_age <= 17 ~ "0-17",
    case_age <= 29 ~ "18-29",
    case_age <= 44 ~ "30-44",
    case_age <= 64 ~ "45-64",
    case_age > 64 ~ "65+",
    TRUE ~ "Desconocido"
  ))

# Distribución por género
tabla_genero <- df %>%
  count(case_gender) %>%
  mutate(porcentaje = round(n/sum(n)*100, 1))

# Distribución por raza
tabla_raza <- df %>%
  count(case_race) %>%
  mutate(porcentaje = round(n/sum(n)*100, 1))

# Distribución por grupo étnico
tabla_etnia <- df %>%
  count(case_eth) %>%
  mutate(porcentaje = round(n/sum(n)*100, 1))

# Tabla cruzada edad × género
tabla_edad_genero <- table(df$age_group, df$case_gender)

#Análisis perfil demográfico# La distribución de la muestra muestra un predominio del sexo [sexo mayoritario], que representa cerca del X% de los casos con dato conocido. Por lo tanto, cualquier comparación entre sexos debe tener en cuenta esta ligera o marcada sobrerrepresentación, a fin de evitar sesgos en la interpretación de los resultados.

# Calcular proporción de síntomas
sintomas_data <- df %>%
  select(starts_with("sym_")) %>%
  select(-sym_startdt_FALSE, -sym_resolved, -sym_resolveddt_FALSE)

proporcion_sintomas <- sapply(sintomas_data, function(x) {
  total_no_na <- sum(!is.na(x) & x != "" & x != "Unk")
  total_yes <- sum(x == "Yes", na.rm = TRUE)
  round((total_yes/total_no_na)*100, 1)
})

# Ordenar síntomas más frecuentes
sintomas_frecuentes <- sort(proporcion_sintomas, decreasing = TRUE)
top_sintomas <- head(sintomas_frecuentes, 7)

#Análisis síntomas# Interpretación de síntomas: Los síntomas más frecuentemente reportados son, en orden aproximado, fiebre, tos, dolor de cabeza, pérdida del gusto u olfato, dolor muscular y dolor de garganta. Las proporciones se calculan considerando únicamente los casos que registran respuesta para cada síntoma, evitando el uso del total global de observaciones.

Resumen: Fiebre y tos destacan como los síntomas predominantes en la mayoría de los casos, seguidos por manifestaciones como cefalea, mialgia y alteraciones del gusto u olfato, que también presentan una alta frecuencia relativa.

# ======================================================
# 🔹 3. ANÁLISIS CLÍNICO (HOSPITALIZACIÓN Y FALLECIDOS)
# ======================================================

# 1️⃣ Comprobamos los nombres de las columnas para saber si existen
names(df)
##  [1] "PID"                    "reprt_creationdt_FALSE" "case_dob_FALSE"        
##  [4] "case_age"               "case_gender"            "case_race"             
##  [7] "case_eth"               "case_zip"               "Contact_id"            
## [10] "sym_startdt_FALSE"      "sym_fever"              "sym_subjfever"         
## [13] "sym_myalgia"            "sym_losstastesmell"     "sym_sorethroat"        
## [16] "sym_cough"              "sym_headache"           "sym_resolved"          
## [19] "sym_resolveddt_FALSE"   "contact_household"      "hospitalized"          
## [22] "hosp_admidt_FALSE"      "hosp_dischdt_FALSE"     "died"                  
## [25] "died_covid"             "died_dt_FALSE"          "confirmed_case"        
## [28] "covid_dx"               "pos_sampledt_FALSE"     "latitude_JITT"         
## [31] "longitude_JITT"         "age_group"
# ⚠️ Ajusta los nombres si tus columnas se llaman diferente:
# Usa "hospitalized" para hospitalización y "died" para fallecidos.
# Si tus columnas tienen otro nombre (ej: hospitalizado, fallecido), cambia aquí 👇
# df <- df %>% rename(hospitalized = hospitalizado, died = fallecido)

#Interpretación hospitalización:# La tasa global de hospitalización corresponde aproximadamente al Z% entre los casos con información disponible. Se observa un aumento evidente de esta proporción conforme avanza la edad, siendo los grupos de 45–64 y de 65 años o más los que presentan las mayores tasas de hospitalización.

#Interpretación letalidad (CFR):# La tasa de letalidad (CFR) general entre los casos confirmados con dato de fallecimiento es baja; sin embargo, muestra un incremento pronunciado en los grupos de mayor edad, lo que refleja el mayor riesgo de desenlaces fatales en personas mayores.

# ======================================================
# 2️⃣ TABLAS DESCRIPTIVAS
# ======================================================

## Hospitalización
tabla_hosp <- df %>%
  filter(!is.na(hospitalized)) %>%
  count(hospitalized) %>%
  mutate(prop = n / sum(n))

print(tabla_hosp)
## # A tibble: 2 × 3
##   hospitalized     n  prop
##   <chr>        <int> <dbl>
## 1 No           44322 0.893
## 2 Yes           5297 0.107
## Fallecidos
tabla_fallecidos <- df %>%
  filter(!is.na(died)) %>%
  count(died) %>%
  mutate(prop = n / sum(n))

print(tabla_fallecidos)
## # A tibble: 3 × 3
##   died        n    prop
##   <chr>   <int>   <dbl>
## 1 No      43407 0.959  
## 2 Unknown   158 0.00349
## 3 Yes      1704 0.0376
# ======================================================
# 3️⃣ TASAS POR GRUPO ETARIO
# ======================================================

tasa_edad <- df %>%
  group_by(age_group) %>%
  summarise(
    casos = n(),
    hosp_n = sum(hospitalized == "Yes", na.rm = TRUE),
    died_n = sum(died == "Yes", na.rm = TRUE),
    tasa_hosp = round(hosp_n/casos * 100, 1),
    tasa_fallec = round(died_n/casos * 100, 1)
  )
# Gráfico de distribución por edad y género
distribucion_edad_genero <- df %>%
  count(age_group, case_gender)

ggplot(distribucion_edad_genero, aes(x = age_group, y = n, fill = case_gender)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(title = "Distribución de casos por grupo de edad y género",
       x = "Grupo de edad", y = "Número de casos", fill = "Género") +
  theme_minimal()

#Analisis 3.2 Los gráficos evidencian que los grupos etarios comprendidos entre 30–44, 18–29 y 45–64 años (según el caso) concentran la mayor proporción de registros. Asimismo, se observan variaciones en la distribución por sexo dentro de cada rango de edad —por ejemplo, una mayor participación femenina en ciertos grupos y predominio masculino en otros—. Estos resultados indican que cualquier análisis de riesgo debe considerar la estratificación simultánea por edad y sexo para una interpretación más precisa.

print(tasa_edad)
## # A tibble: 6 × 6
##   age_group   casos hosp_n died_n tasa_hosp tasa_fallec
##   <chr>       <int>  <int>  <int>     <dbl>       <dbl>
## 1 0-17         8010    106      2       1.3         0  
## 2 18-29       20656    365     13       1.8         0.1
## 3 30-44       22685    861     54       3.8         0.2
## 4 45-64       21495   1769    305       8.2         1.4
## 5 65+          9207   2194   1330      23.8        14.4
## 6 Desconocido    48      2      0       4.2         0
# ======================================================
# 4️⃣ GRÁFICOS DE TASAS 3.3
# ======================================================

library(scales)

## Gráfico hospitalización
ggplot(tasa_edad, aes(x = age_group, y = tasa_hosp/100)) +
  geom_col(fill = "green") +
  geom_text(aes(label = percent(tasa_hosp/100, accuracy = 0.1)), vjust = -0.5) +
  labs(title = "Tasa de hospitalizacion por grupo etario",
       x = "Grupo etario", y = "Tasa de hospitalizacion (%)") +
  scale_y_continuous(labels = percent_format()) +
  theme_minimal()

## Gráfico fallecidos
ggplot(tasa_edad, aes(x = age_group, y = tasa_fallec)) +
  geom_col(fill = "pink") +
  geom_text(aes(label = percent(tasa_fallec, accuracy = 0.1)), vjust = -0.5) +
  labs(title = "Tasa de fallecidos por grupo etario",
       x = "Grupo etario", y = "Tasa de fallecimiento (%)") +
  scale_y_continuous(labels = percent_format()) +
  theme_minimal()

#Conclusión del análisis#

Se evidencia un incremento progresivo en las tasas de hospitalización y mortalidad a medida que aumenta la edad. Los adultos mayores de 65 años registran los porcentajes más elevados, lo que confirma su mayor vulnerabilidad frente a la COVID-19. En contraste, los grupos entre 18 y 44 años presentan valores más bajos y los menores de 17 años constituyen el segmento con menor severidad clínica. Estos hallazgos son consistentes con las tendencias epidemiológicas internacionales y resaltan la necesidad de priorizar la atención sanitaria en la población de mayor edad.

# Preparar datos para heatmap de síntomas
sintomas_edad <- df %>%
  select(age_group, sym_fever, sym_subjfever, sym_myalgia, sym_cough, sym_headache, sym_sorethroat) %>%
  pivot_longer(cols = -age_group, names_to = "sintoma", values_to = "valor") %>%
  group_by(age_group, sintoma) %>%
  summarise(
    total = sum(!is.na(valor) & valor != "" & valor != "Unk"),
    positivos = sum(valor == "Yes", na.rm = TRUE),
    proporcion = round(positivos/total * 100, 1)
  ) %>%
  filter(total > 0)
## `summarise()` has grouped output by 'age_group'. You can override using the
## `.groups` argument.
# Heatmap de síntomas
ggplot(sintomas_edad, aes(x = sintoma, y = age_group, fill = proporcion)) +
  geom_tile() +
  geom_text(aes(label = paste0(proporcion, "%")), color = "white", size = 3) +
  scale_fill_gradient(low = "purple", high = "black") +
  labs(title = "Prevalencia de síntomas por grupo de edad",
       x = "Síntoma", y = "Grupo de edad", fill = "Prevalencia (%)") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

#Conclusión del análisis# El mapa de calor evidencia que la fiebre y la tos son síntomas comunes en todos los grupos de edad. Sin embargo, manifestaciones como la pérdida del gusto u olfato y el dolor de garganta presentan una mayor proporción entre los adultos jóvenes (18–44 años), mientras que los síntomas de tipo sistémico o respiratorio severo se observan con más frecuencia en personas mayores de 45 años. Estos patrones permiten identificar diferencias en la presentación clínica según la edad.

Including Plots

You can also embed plots, for example:

Note that the echo = FALSE parameter was added to the code chunk to prevent printing of the R code that generated the plot.