UNIVERSIDAD CENTRAL DEL ECUADOR

PROYECTO: ANÁLISIS ESTADÍSTICO SOBRE LA CALIDAD DE AIRE EN LA INDIA

FECHA: 22/11/2025

# ==============================================================================
# 1. CARGA DE PAQUETES Y DATOS
# ==============================================================================

# Cargar librerías necesarias
library(gt)
library(dplyr)
# Carga de librería para Asimetría y Curtosis
# install.packages("e1071")
library(e1071) 

# Carga de datos
# El archivo ya está cargado en el entorno
datos <- read.csv("C:/Users/WILLIAM/Pictures/overleaf/Datos Cambiados.csv",
                  header = TRUE,
                  sep = ",",
                  dec = ".")

# ==============================================================================
# 2. PREPARACIÓN Y LIMPIEZA DE DATOS DE DIÓXIDO DE NITRÓGENO (NO2)
# ==============================================================================

# Extracción de los "-" (valores inexistentes) de la variable NO2
# NOTA: Asumimos que la columna se llama 'NO2'
no2 <- datos$NO2[datos$NO2 != "-"]

# Tamaño muestral después de la limpieza
cat("Tamaño muestral del Dióxido de Nitrógeno (sin '-'):", length(no2), "\n")
## Tamaño muestral del Dióxido de Nitrógeno (sin '-'): 25946
# Conversión a numérico
no2 <- as.numeric(no2)

# ==============================================================================
# 3. CÁLCULOS PARA LA DISTRIBUCIÓN DE FRECUENCIAS DETALLADA (34 CLASES) - NO2
# ==============================================================================

N_no2 <- length(no2)
min_no2 <- min(no2)
max_no2 <- max(no2)
R_no2 <- max_no2 - min_no2

# Número de clases (k): Se mantienen 34 clases
k_detallado_no2 <- 34

# Amplitud de clase (A)
A_no2 <- R_no2 / k_detallado_no2

# Generación de límites de intervalos
Li_no2 <- seq(from = min_no2, to = max_no2 - A_no2, by = A_no2)
Ls_no2 <- c(seq(from = min_no2 + A_no2, to = max_no2 - A_no2, by = A_no2), max_no2)

# Redondeo para cálculos de intervalos precisos
no2 <- round(no2, 3)
Li_no2 <- round(Li_no2, 3)
Ls_no2 <- round(Ls_no2, 3)

# Marcas de Clase (MC)
MC_no2 <- (Li_no2 + Ls_no2) / 2

# Creación de frecuencias absolutas (ni)
ni_no2 <- numeric(length(Li_no2))
for (i in 1:length(Li_no2)) {
  if (i < length(Li_no2)) {
    # Intervalo abierto por la derecha: [Li, Ls)
    ni_no2[i] <- sum(no2 >= Li_no2[i] & no2 < Ls_no2[i])
  } else {
    # Último intervalo cerrado: [Li, Ls]
    ni_no2[i] <- sum(no2 >= Li_no2[i] & no2 <= Ls_no2[i])
  }
}

# Frecuencias relativas y acumuladas
hi_no2 <- (ni_no2 / N_no2) * 100
Ni_asc_no2 <- cumsum(ni_no2)
Ni_desc_no2 <- rev(cumsum(rev(ni_no2)))
Hi_asc_no2 <- cumsum(hi_no2)
Hi_desc_no2 <- rev(cumsum(rev(hi_no2)))

# Formatear la columna Intervalo
Intervalo_no2 <- paste0("[", round(Li_no2, 2), " - ", round(Ls_no2, 2), ")")
# Corregir el último intervalo para que sea cerrado
Intervalo_no2[length(Intervalo_no2)] <- paste0("[", round(Li_no2[length(Li_no2)], 2), " - ",
                                               round(Ls_no2[length(Ls_no2)], 2), "]")

# Crear el Data Frame (TDF)
TDF_no2 <- data.frame(
  Intervalo = Intervalo_no2,
  MC = round(MC_no2, 2),
  ni = ni_no2,
  hi = round(hi_no2, 2),
  Ni_ascendente = Ni_asc_no2,
  Ni_descendente = Ni_desc_no2,
  Hi_ascendente = round(Hi_asc_no2, 2),
  Hi_descendente = round(Hi_desc_no2, 2)
)

# Agregar la fila de totales
totales_no2 <- data.frame(
  Intervalo = "Totales",
  MC = "-",
  ni = sum(ni_no2),
  hi = sum(hi_no2),
  Ni_ascendente = "-",
  Ni_descendente = "-",
  Hi_ascendente = "-",
  Hi_descendente = "-"
)
TDF_no2_completa <- rbind(TDF_no2, totales_no2)

# ==============================================================================
# 4. TABLA DE FRECUENCIAS DETALLADA (Tabla Nro. 1)
# ==============================================================================

TDF_no2_completa %>%
  gt() %>%
  tab_header(
    title = "Tabla Nro. 1",
    subtitle = "Distribución de frecuencia de concentración de Dióxido de Nitrógeno (NO₂), estudio calidad del aire en India entre 2015-2020"
  ) %>%
  tab_source_note(
    source_note = "Autor: Grupo 2\n Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india"
  ) %>%
  tab_options(
    table.border.top.color = "black",
    table.border.bottom.color = "black",
    table.border.top.style = "solid",
    table.border.bottom.style = "solid",
    column_labels.border.top.color = "black",
    column_labels.border.bottom.color = "black",
    column_labels.border.bottom.width = px(2),
    row.striping.include_table_body = TRUE,
    heading.border.bottom.color = "black",
    heading.border.bottom.width = px(2),
    table_body.hlines.color = "gray",
    table_body.border.bottom.color = "black"
  )
Tabla Nro. 1
Distribución de frecuencia de concentración de Dióxido de Nitrógeno (NO₂), estudio calidad del aire en India entre 2015-2020
Intervalo MC ni hi Ni_ascendente Ni_descendente Hi_ascendente Hi_descendente
[0.01 - 10.66) 5.34 5484 21.14 5484 25946 21.14 100
[10.66 - 21.32) 15.99 7277 28.05 12761 20462 49.18 78.86
[21.32 - 31.97) 26.64 4901 18.89 17662 13185 68.07 50.82
[31.97 - 42.62) 37.3 3096 11.93 20758 8284 80 31.93
[42.62 - 53.27) 47.95 1963 7.57 22721 5188 87.57 20
[53.27 - 63.93) 58.6 1227 4.73 23948 3225 92.3 12.43
[63.93 - 74.58) 69.25 721 2.78 24669 1998 95.08 7.7
[74.58 - 85.23) 79.91 469 1.81 25138 1277 96.89 4.92
[85.23 - 95.89) 90.56 253 0.98 25391 808 97.86 3.11
[95.89 - 106.54) 101.21 165 0.64 25556 555 98.5 2.14
[106.54 - 117.19) 111.87 132 0.51 25688 390 99.01 1.5
[117.19 - 127.84) 122.52 62 0.24 25750 258 99.24 0.99
[127.84 - 138.5) 133.17 52 0.20 25802 196 99.45 0.76
[138.5 - 149.15) 143.82 36 0.14 25838 144 99.58 0.55
[149.15 - 159.8) 154.48 26 0.10 25864 108 99.68 0.42
[159.8 - 170.46) 165.13 22 0.08 25886 82 99.77 0.32
[170.46 - 181.11) 175.78 20 0.08 25906 60 99.85 0.23
[181.11 - 191.76) 186.44 7 0.03 25913 40 99.87 0.15
[191.76 - 202.42) 197.09 6 0.02 25919 33 99.9 0.13
[202.42 - 213.07) 207.74 8 0.03 25927 27 99.93 0.1
[213.07 - 223.72) 218.4 5 0.02 25932 19 99.95 0.07
[223.72 - 234.38) 229.05 3 0.01 25935 14 99.96 0.05
[234.38 - 245.03) 239.7 5 0.02 25940 11 99.98 0.04
[245.03 - 255.68) 250.35 1 0.00 25941 6 99.98 0.02
[255.68 - 266.33) 261.01 0 0.00 25941 5 99.98 0.02
[266.33 - 276.99) 271.66 2 0.01 25943 5 99.99 0.02
[276.99 - 287.64) 282.31 1 0.00 25944 3 99.99 0.01
[287.64 - 298.29) 292.97 1 0.00 25945 2 100 0.01
[298.29 - 308.94) 303.62 0 0.00 25945 1 100 0
[308.94 - 319.6) 314.27 0 0.00 25945 1 100 0
[319.6 - 330.25) 324.92 0 0.00 25945 1 100 0
[330.25 - 340.9) 335.58 0 0.00 25945 1 100 0
[340.9 - 351.56) 346.23 0 0.00 25945 1 100 0
[351.56 - 362.21] 356.88 1 0.00 25946 1 100 0
Totales - 25946 100.00 - - - -
Autor: Grupo 2 Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india
# ==============================================================================
# 5. CÁLCULOS PARA LA DISTRIBUCIÓN SIMPLIFICADA (13 CLASES) - NO2
# ==============================================================================

# Se utiliza la función hist() para obtener los intervalos simplificados
Histograma_no2 <- hist(no2, breaks = 13, plot = FALSE) # No mostrar la gráfica aún

# Extraer elementos simplificados
Lis_no2 <- Histograma_no2$breaks[1:(length(Histograma_no2$breaks) - 1)]
Lss_no2 <- Histograma_no2$breaks[2:length(Histograma_no2$breaks)]
MCs_no2 <- (Lis_no2 + Lss_no2) / 2
nis_no2 <- Histograma_no2$counts

# Frecuencias relativas y acumuladas simplificadas
his_no2 <- (nis_no2 / N_no2) * 100
Nis_asc_no2 <- cumsum(nis_no2)
His_asc_no2 <- cumsum(his_no2)
Nis_desc_no2 <- rev(cumsum(rev(nis_no2)))
His_desc_no2 <- rev(cumsum(rev(his_no2)))

# Crear el Data Frame Simplificado
TDF_no2simplificado <- data.frame(
  Intervalo = paste0("[", round(Lis_no2, 2), " - ", round(Lss_no2, 2), ")"),
  MC = round(MCs_no2, 2),
  ni = nis_no2,
  hi = round(his_no2, 2),
  Ni_asc = Nis_asc_no2,
  Hi_asc = round(His_asc_no2, 2),
  Ni_desc = Nis_desc_no2,
  Hi_desc = round(His_desc_no2, 2)
)

# Renombrar columnas con los nombres finales (usando comillas invertidas para % en R)
colnames(TDF_no2simplificado) <- c("Intervalo", "MC", "ni", "hi(%)",
                                   "Ni_asc", "Hi_asc (%)", "Ni_desc", "Hi_desc (%)")

# Agregar la fila de totales (Código Corregido)
totaless_no2 <- data.frame(
  Intervalo = "Totales",
  MC = "-",
  ni = sum(nis_no2),
  `hi(%)` = sum(his_no2),
  Ni_asc = "-",
  `Hi_asc (%)` = "-",
  Ni_desc = "-",
  `Hi_desc (%)` = "-"
)
# Asegurar que las columnas de totaless coincidan con los nombres finales
colnames(totaless_no2) <- colnames(TDF_no2simplificado)

# Unir los data frames
TDF_no2simplificado_completa <- rbind(TDF_no2simplificado, totaless_no2)

# ==============================================================================
# 6. TABLA DE FRECUENCIAS SIMPLIFICADA (Tabla Nro. 2)
# ==============================================================================

TDF_no2simplificado_completa %>%
  gt() %>%
  tab_header(
    title = "Tabla Nro. 2",
    subtitle = "Distribución de frecuencia simplificada de concentración de Dióxido de Nitrógeno (NO₂), estudio calidad del aire en India entre 2015-2020"
  ) %>%
  tab_source_note(
    source_note = "Autor: Grupo 2\n Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india"
  ) %>%
  tab_options(
    table.border.top.color = "black",
    table.border.bottom.color = "black",
    table.border.top.style = "solid",
    table.border.bottom.style = "solid",
    column_labels.border.top.color = "black",
    column_labels.border.bottom.color = "black",
    column_labels.border.bottom.width = px(2),
    row.striping.include_table_body = TRUE,
    heading.border.bottom.color = "black",
    heading.border.bottom.width = px(2),
    table_body.hlines.color = "gray",
    table_body.border.bottom.color = "black"
  )
Tabla Nro. 2
Distribución de frecuencia simplificada de concentración de Dióxido de Nitrógeno (NO₂), estudio calidad del aire en India entre 2015-2020
Intervalo MC ni hi(%) Ni_asc Hi_asc (%) Ni_desc Hi_desc (%)
[0 - 20) 10 12018 46.32 12018 46.32 25946 100
[20 - 40) 30 8096 31.20 20114 77.52 13928 53.68
[40 - 60) 50 3436 13.24 23550 90.77 5832 22.48
[60 - 80) 70 1393 5.37 24943 96.13 2396 9.23
[80 - 100) 90 511 1.97 25454 98.1 1003 3.87
[100 - 120) 110 250 0.96 25704 99.07 492 1.9
[120 - 140) 130 101 0.39 25805 99.46 242 0.93
[140 - 160) 150 59 0.23 25864 99.68 141 0.54
[160 - 180) 170 41 0.16 25905 99.84 82 0.32
[180 - 200) 190 12 0.05 25917 99.89 41 0.16
[200 - 220) 210 13 0.05 25930 99.94 29 0.11
[220 - 240) 230 9 0.03 25939 99.97 16 0.06
[240 - 260) 250 2 0.01 25941 99.98 7 0.03
[260 - 280) 270 3 0.01 25944 99.99 5 0.02
[280 - 300) 290 1 0.00 25945 100 2 0.01
[300 - 320) 310 0 0.00 25945 100 1 0
[320 - 340) 330 0 0.00 25945 100 1 0
[340 - 360) 350 0 0.00 25945 100 1 0
[360 - 380) 370 1 0.00 25946 100 1 0
Totales - 25946 100.00 - - - -
Autor: Grupo 2 Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india
# ==============================================================================
# 7. GENERACIÓN DE GRÁFICOS (NO2)
# ==============================================================================

# ==============================================================================
# 7. GRÁFICA N°1: Histograma Local (NO2)
# ==============================================================================

hist(no2, breaks = 13,
     main = "Gr\u00E1fica N\u00B01: Distribuci\u00F3n de la Concentraci\u00F3n de Dióxido de Nitrógeno (NO₂)\npresente en el estudio sobre calidad del aire en India entre 2015-2020",
     xlab = "NO₂ (\u00B5g/m\u00B3)",
     ylab = "Cantidad",
     # max(nis_no2) es la altura máxima para el histograma 'local'
     ylim = c(0, max(nis_no2)),
     col = "darkseagreen3", # Nuevo color
     cex.main = 0.9,
     cex.lab = 1,
     cex.axis = 0.9,
     xaxt = "n")
axis(1, at = Histograma_no2$breaks,
     labels = round(Histograma_no2$breaks, 0), las = 1,
     cex.axis = 0.9)

# ----------------------------------
# Gráfica N°2: Histograma Global (Frecuencia Absoluta) - NO2
# ----------------------------------
hist(no2, breaks = 13,
     main = "Gr\u00E1fica N\u00B02: Distribuci\u00F3n de la Concentraci\u00F3n de Dióxido de Nitrógeno (NO₂)\npresente en el estudio sobre calidad del aire en India entre 2015-2020",
     xlab = "NO₂ (\u00B5g/m\u00B3)",
     ylab = "Cantidad",
     # length(no2) es la altura máxima
     ylim = c(0, length(no2)),
     col = "darkseagreen",
     cex.main = 1,
     cex.lab = 1,
     cex.axis = 0.9,
     xaxt = "n")
axis(1, at = Histograma_no2$breaks,
     labels = round(Histograma_no2$breaks, 0), las = 1,
     cex.axis = 0.9)

# ------------------------------------------------------------------------------
# Gráfica N°3: Histograma Porcentual Global (NO2)
# ------------------------------------------------------------------------------

# Para esta gráfica, usaremos el 'hi(%)' de la tabla simplificada.
porcentajes_no2 <- TDF_no2simplificado$`hi(%)`[1:(nrow(TDF_no2simplificado)-1)]
marcas_clase_no2 <- TDF_no2simplificado$MC[1:(nrow(TDF_no2simplificado)-1)]

post_no2 <- barplot(porcentajes_no2,
                    space = 0,
                    col = "skyblue",
                    main = "Gr\u00E1fica N\u00B03: Distribuci\u00F3n Porcentual Global de NO₂\nEstudio Calidad del Aire en India, 2015-2020",
                    xlab = "NO₂ (\u00B5g/m\u00B3)",
                    ylab = "Porcentaje (%)",
                    ylim = c(0, 100),
                    cex.main = 0.9,
                    cex.lab = 1,
                    xaxt = "n",
                    yaxt = "n") # <--- PARÉNTESIS DE CIERRE AÑADIDO

# Dibujamos las etiquetas del Eje X (Marca de Clase) rotadas y pequeñas
axis(side = 1,
     at = post_no2,
     labels = marcas_clase_no2,
     tck = -0.02,
     las = 2,        # <--- AÑADIDA COMA AQUÍ
     cex.axis = 0.6) # <--- AÑADIDO PARÉNTESIS DE CIERRE AQUÍ

# Dibujamos las marcas del Eje Y de forma explícita
axis(side = 2,
     at = seq(0, 100, by = 20),
     las = 1,
     cex.axis = 0.9)

# ------------------------------------------------------------------------------
# Gráfica N°4: Histograma Porcentual Local (NO2) - CORREGIDO
# ------------------------------------------------------------------------------

n_no2_sim <- as.numeric(nrow(TDF_no2simplificado))
porcentajes_no2_local <- TDF_no2simplificado$`hi(%)`[1:(n_no2_sim-1)]
marcas_clase_no2_local <- TDF_no2simplificado$MC[1:(n_no2_sim-1)]

pos_no2 <- barplot(
  porcentajes_no2_local,
  space = 0,
  main = "Gr\u00E1fica N\u00B04: Distribuci\u00F3n Porcentual de Concentraci\u00F3n de NO₂\nEstudio Calidad del Aire en India, 2015-2020",
  ylab = "Porcentaje (%)",
  xlab = "NO₂ (\u00B5g/m\u00B3)",
  
  # Ajuste de Y para que la barra más alta sobresalga ligeramente si es > 80
  ylim = c(0, max(porcentajes_no2_local) * 1.1),
  
  col = "darkseagreen",
  cex.main = 0.9,
  cex.lab = 1,
  
  # Ocultamos etiquetas automáticas para control manual
  xaxt = "n",
  yaxt = "n"
) # <--- ¡Paréntesis de cierre añadido aquí!

# Dibujamos las etiquetas del Eje X (Marca de Clase)
axis(side = 1,
     at = pos_no2,
     labels = marcas_clase_no2_local,
     tck = -0.04,   
     las = 2,       # Coma añadida aquí
     cex.axis = 0.6) # Paréntesis de cierre añadido aquí

# Dibujamos las marcas del Eje Y
axis(side = 2,
     at = seq(0, round(max(porcentajes_no2_local) * 1.1), by = 20),
     las = 1, # ¡Asegúrate de que la coma es el ÚNICO carácter después de '1'!
     cex.axis = 0.9)

# ------------------------------------------------------------------------------
# Gráfica N°5: Diagrama de Caja (Box Plot) para NO2 - CORREGIDO
# ------------------------------------------------------------------------------

CajaNO2 <- boxplot(no2,
                   horizontal = T,
                   col = "turquoise",
                   border = "black",
                   main = "Gr\u00E1fica N\u00B05: Distribuci\u00F3n de la concentraci\u00F3n de Dióxido de Nitrógeno (NO₂),\nestudio calidad del aire en India desde 2015-2020",
                   xlab = "NO₂ (\u00B5g/m\u00B3)",
                   cex.main = 0.9,
                   cex.lab = 1)

# ------------------------------------------------------------------------------
# Gráfica N°6: Ojiva Ascendente y Descendente (Cantidad) - NO2 - CORREGIDO
# ------------------------------------------------------------------------------

# 1. Definir los límites de clase extendidos (añadiendo el punto cero)
Limites_X_no2 <- c(Lis_no2[1], Lss_no2)

# 2. Definir frecuencias acumuladas extendidas (Cantidad)
Frec_Asc_Ext_no2 <- c(0, Nis_asc_no2) # <-- Limpio
Frec_Desc_Ext_no2 <- c(Nis_desc_no2, 0)

# Ojiva ascendente
plot(Limites_X_no2, Frec_Asc_Ext_no2, # <-- Limpio
     type = "b", # <-- Limpio
     main = "Gr\u00E1fica N\u00B06: Ojiva ascendente y descendente de la
     distribuci\u00F3n de la concentraci\u00F3n de Dióxido de Nitrógeno (NO₂)",
     
     xlab = "NO₂ (\u00B5g/m\u00B3)",
     ylab = "Cantidad", # <-- Limpio
     pch = 19,
     col = "turquoise", # <-- Limpio
     ylim = c(0, N_no2), # <-- Limpio
     xlim = c(0, max(Lss_no2)), # <-- Limpio
     
     cex.main = 0.9,
     cex.lab = 1,
     cex.axis = 0.9
) # <-- El paréntesis de cierre debe ser el último carácter de la función

# Ojiva descendente
lines(Limites_X_no2, Frec_Desc_Ext_no2, # <-- Limpio
      type = "b", # <-- Limpio
      col = "black", # <-- Limpio
      pch = 19)

# ------------------------------------------------------------------------------
# Gráfica N°7: Ojiva Ascendente y Descendente PORCENTUAL (NO2) - CORREGIDO
# ------------------------------------------------------------------------------

# 1. Definir los límites de clase extendidos
Limites_X_no2 <- c(Lis_no2[1], Lss_no2)

# 2. Definir frecuencias PORCENTUALES acumuladas extendidas
Frec_H_Asc_Ext_no2 <- c(0, His_asc_no2)
Frec_H_Desc_Ext_no2 <- c(His_desc_no2, 0)

# Ojiva ascendente
plot(Limites_X_no2, Frec_H_Asc_Ext_no2,
     type = "b",
     main = "Gr\u00E1fica N\u00B07: Ojiva ascendente y descendente de la distribuci\u00F3n PORCENTUAL de Dióxido de Nitrógeno (NO₂)",
     
     xlab = "NO₂ (\u00B5g/m\u00B3)",
     ylab = "Porcentaje (%)",
     
     pch = 19,
     col = "blue",
     
     ylim = c(0, 100),
     xlim = c(0, max(Lss_no2)),
     
     cex.main = 0.9,
     cex.lab = 1,
     cex.axis = 0.9
)

# Ojiva descendente
lines(Limites_X_no2, Frec_H_Desc_Ext_no2,
      type = "b",
      col = "red",
      pch = 19)

# Opcional: Añadir leyenda para claridad
legend("topright",
       legend = c("Ojiva Ascendente", "Ojiva Descendente"),
       col = c("blue", "red"),
       pch = 19,
       bty = "n")

# ==============================================================================
# 8. CÁLCULO DE INDICADORES ESTADÍSTICOS (NO2)
# ==============================================================================

# --------------------------------
# Indicadores de Tendencia Central
# --------------------------------

# Mediana (Me)
Me_no2 <- median(no2)

# Media (X)
X_no2 <- mean(no2)

# Moda (Mo)
moda_index_no2 <- which.max(TDF_no2simplificado$ni[1:(nrow(TDF_no2simplificado)-1)])
Mo_no2 <- TDF_no2simplificado$Intervalo[moda_index_no2]


# --------------------------------
# Indicadores de Dispersión
# --------------------------------

# Varianza
Var_no2 <- var(no2)

# Desviación estándar (sd)
desv_no2 <- sd(no2)

# Coeficiente de variación (CV)
CV_no2 <- (desv_no2 / X_no2) * 100


# --------------------------------
# Indicadores de Forma
# --------------------------------

# Coeficiente de Asimetría (As)
As_no2 <- skewness(no2)

# Curtosis (K)
K_no2 <- kurtosis(no2)


# --------------------------------
# Creación del Data Frame (Tabla_indicadores_NO2) - CORREGIDO
# --------------------------------

Variable_NO2 <- "Dióxido de Nitrógeno (NO₂)"
Rango_NO2 <- paste0("[", round(min_no2, 2), " - ", round(max_no2, 2), "]")

Tabla_indicadores_NO2 <- data.frame(
  Variable = Variable_NO2,
  Rango = Rango_NO2,
  X = round(X_no2, 3),
  Me = round(Me_no2, 3), # <--- ¡LIMPIO!
  Mo = Mo_no2,
  sd = round(desv_no2, 2),
  CV = round(CV_no2, 2),
  As = round(As_no2, 2),
  K = round(K_no2, 2)
)

# Renombrar columnas para la tabla
colnames(Tabla_indicadores_NO2) <- c("Variable", "Rango", "Media (X)", "Mediana (Me)", "Moda (Mo)", "Desv. Est. (sd)", "CV (%)", "Asimetría (As)", "Curtosis (K)")


# ==============================================================================
# 9. TABLA DE INDICADORES ESTADÍSTICOS (Tabla Nro. 3) - Usando GT
# ==============================================================================

Tabla_indicadores_NO2 %>%
  gt() %>%
  tab_header(
    title = md("Tabla Nro. 3"),
    subtitle = md("*Indicadores Estadísticos de concentración de Dióxido de Nitrógeno (NO₂), estudio calidad del aire en India entre 2015-2020 *")
  ) %>%
  tab_source_note(
    source_note = md("Autor: Grupo 2\n Fuente:https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india")
  ) %>%
  # Agrupamos las columnas por categoría
  tab_spanner(
    label = "Tendencia Central",
    columns = c("Media (X)", "Mediana (Me)", "Moda (Mo)")
  ) %>%
  tab_spanner(
    label = "Dispersión",
    columns = c("Desv. Est. (sd)", "CV (%)")
  ) %>%
  tab_spanner(
    label = "Forma",
    columns = c("Asimetría (As)", "Curtosis (K)")
  ) %>%
  # Formateo de números
  fmt_number(
    columns = c("Media (X)", "Mediana (Me)", "Desv. Est. (sd)", "CV (%)", "Asimetría (As)", "Curtosis (K)"),
    decimals = 2
  ) %>%
  # Opciones de estilo
  tab_options(
    table.border.top.color = "black",
    table.border.bottom.color = "black",
    table.border.top.style = "solid",
    table.border.bottom.style = "solid",
    column_labels.border.top.color = "black",
    column_labels.border.bottom.color = "black",
    column_labels.border.bottom.width = px(2),
    row.striping.include_table_body = TRUE,
    heading.border.bottom.color = "black",
    heading.border.bottom.width = px(2),
    table_body.hlines.color = "gray",
    table_body.border.bottom.color = "black"
  )
Tabla Nro. 3
*Indicadores Estadísticos de concentración de Dióxido de Nitrógeno (NO₂), estudio calidad del aire en India entre 2015-2020 *
Variable Rango
Tendencia Central
Dispersión
Forma
Media (X) Mediana (Me) Moda (Mo) Desv. Est. (sd) CV (%) Asimetría (As) Curtosis (K)
Dióxido de Nitrógeno (NO₂) [0.01 - 362.21] 28.56 21.69 [0 - 20) 24.47 85.69 2.46 11.21
Autor: Grupo 2 Fuente:https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india