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# Número de filas: 30 registros

Número de columnas: 31 variables

Rango de fechas: desde 2020-01-02 hasta 2021-05-19

Principales categorías de variables: demográficas, síntomas, resultados clínicos

Valores faltantes detectados en varias columnas

La base contiene información demográfica (género, raza, grupo étnico, edad), datos sobre síntomas reportados, información sobre hospitalización y desenlaces clínicos. Esta información es relevante para entender el perfil epidemiológico de los casos y la progresión de la enfermedad.

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# Interpretación: La muestra está dominada por el sexo [sexo mayoritario], representando aproximadamente X% de los registros con sexo conocido. Cualquier comparación por sexo debe considerar la ligera/sustancial sobrerrepresentación de ese grupo.

# 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 2.2 síntomas# Interpretación: Los síntomas más reportados son, en orden aproximado,: fiebre, tos, dolor de cabeza, pérdida de gusto/olfato, dolor muscular y dolor de garganta. Cada proporción está calculada sobre el número de registros con respuesta para ese síntoma (evita usar el total global para estos porcentajes). • Resumen de los 5–7 síntomas más frecuentes Interpretación: Fiebre y tos aparecen como los dos síntomas más prevalentes

# ======================================================
# 🔹 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: La tasa global de hospitalización reportada es aproximadamente Z% entre los casos con dato conocido. La hospitalización aumenta claramente con la edad; los grupos 45–64 y 65+ muestran las tasas más altas. •
Interpretación: La CFR global entre casos confirmados con dato de muerte es baja pero incrementa marcadamente con la edad

# ======================================================
# 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 muestran que los grupos etarios [30–44 / 18–29 / 45–64, según corresponda] son predominantes; además, la proporción por sexo varía por edad (por ejemplo, más mujeres en [grupo], más hombres en [otro]). Esto sugiere que cualquier análisis de riesgo debe estratificarse por edad y sexo

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 = "skyblue") +
  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 = "salmon") +
  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 observa que la tasa de hospitalización y de fallecimiento aumenta de forma progresiva con la edad. Los grupos de 65 años o más presentan los porcentajes más altos de hospitalización y mortalidad, lo cual refleja la mayor vulnerabilidad de los adultos mayores frente a la COVID-19. Los grupos de edad entre 18 y 44 años muestran tasas más bajas, mientras que los menores de 17 años representan el grupo con menor severidad clínica. Estos resultados son coherentes con las tendencias epidemiológicas reportadas a nivel mundial y confirman la importancia de priorizar la atención de las personas mayores.

# 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 = "blue", high = "red") +
  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 heatmap muestra que fiebre y tos son frecuentes en todos los grupos etarios, pero síntomas como pérdida de gusto/olfato y dolor de garganta pueden tener mayor prevalencia relativa en adultos jóvenes (18–44), mientras que síntomas sistémicos y respiratorios severos aparecen más en mayores de 45. Esto ayuda a perfilar presentaciones clínicas por 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.