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 PARTÍCULAS PM10
# ==============================================================================

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

# Tamaño muestral después de la limpieza
cat("Tamaño muestral de PM10 (sin '-'):", length(pm10), "\n")
## Tamaño muestral de PM10 (sin '-'): 18391
# Conversión a numérico
pm10 <- as.numeric(pm10)

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

N_pm10 <- length(pm10)
min_pm10 <- min(pm10)
max_pm10 <- max(pm10)
R_pm10 <- max_pm10 - min_pm10

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

# Amplitud de clase (A)
A_pm10 <- R_pm10 / k_detallado_pm10

# Generación de límites de intervalos
Li_pm10 <- seq(from = min_pm10, to = max_pm10 - A_pm10, by = A_pm10)
Ls_pm10 <- c(seq(from = min_pm10 + A_pm10, to = max_pm10 - A_pm10, by = A_pm10), max_pm10)

# Redondeo para cálculos de intervalos precisos
pm10 <- round(pm10, 3)
Li_pm10 <- round(Li_pm10, 3)
Ls_pm10 <- round(Ls_pm10, 3)

# Marcas de Clase (MC)
MC_pm10 <- (Li_pm10 + Ls_pm10) / 2

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

# Frecuencias relativas y acumuladas
hi_pm10 <- (ni_pm10 / N_pm10) * 100
Ni_asc_pm10 <- cumsum(ni_pm10)
Ni_desc_pm10 <- rev(cumsum(rev(ni_pm10)))
Hi_asc_pm10 <- cumsum(hi_pm10)
Hi_desc_pm10 <- rev(cumsum(rev(hi_pm10)))

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

# Crear el Data Frame (TDF)
TDF_pm10 <- data.frame(
  Intervalo = Intervalo_pm10,
  MC = round(MC_pm10, 2),
  ni = ni_pm10,
  hi = round(hi_pm10, 2),
  Ni_ascendente = Ni_asc_pm10,
  Ni_descendente = Ni_desc_pm10,
  Hi_ascendente = round(Hi_asc_pm10, 2),
  Hi_descendente = round(Hi_desc_pm10, 2)
)

# Agregar la fila de totales
totales_pm10 <- data.frame(
  Intervalo = "Totales",
  MC = "-",
  ni = sum(ni_pm10),
  hi = sum(hi_pm10),
  Ni_ascendente = "-",
  Ni_descendente = "-",
  Hi_ascendente = "-",
  Hi_descendente = "-"
)
TDF_pm10_completa <- rbind(TDF_pm10, totales_pm10)

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

TDF_pm10_completa %>%
  gt() %>%
  tab_header(
    title = "Tabla Nro. 1",
    subtitle = "Distribución de frecuencia de concentración de Partículas PM₁₀, 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 Partículas PM₁₀, estudio calidad del aire en India entre 2015-2020
Intervalo MC ni hi Ni_ascendente Ni_descendente Hi_ascendente Hi_descendente
[0.01 - 29.42) 14.72 1239 6.74 1239 18391 6.74 100
[29.42 - 58.83) 44.13 3672 19.97 4911 17152 26.7 93.26
[58.83 - 88.24) 73.54 3468 18.86 8379 13480 45.56 73.3
[88.24 - 117.66) 102.95 3166 17.21 11545 10012 62.78 54.44
[117.66 - 147.07) 132.36 2098 11.41 13643 6846 74.18 37.22
[147.07 - 176.48) 161.77 1458 7.93 15101 4748 82.11 25.82
[176.48 - 205.89) 191.18 930 5.06 16031 3290 87.17 17.89
[205.89 - 235.3) 220.6 588 3.20 16619 2360 90.36 12.83
[235.3 - 264.71) 250.01 427 2.32 17046 1772 92.69 9.64
[264.71 - 294.12) 279.42 336 1.83 17382 1345 94.51 7.31
[294.12 - 323.54) 308.83 241 1.31 17623 1009 95.82 5.49
[323.54 - 352.95) 338.24 214 1.16 17837 768 96.99 4.18
[352.95 - 382.36) 367.65 161 0.88 17998 554 97.86 3.01
[382.36 - 411.77) 397.06 120 0.65 18118 393 98.52 2.14
[411.77 - 441.18) 426.48 81 0.44 18199 273 98.96 1.48
[441.18 - 470.59) 455.89 50 0.27 18249 192 99.23 1.04
[470.59 - 500) 485.3 52 0.28 18301 142 99.51 0.77
[500 - 529.42) 514.71 33 0.18 18334 90 99.69 0.49
[529.42 - 558.83) 544.12 14 0.08 18348 57 99.77 0.31
[558.83 - 588.24) 573.53 11 0.06 18359 43 99.83 0.23
[588.24 - 617.65) 602.94 8 0.04 18367 32 99.87 0.17
[617.65 - 647.06) 632.36 5 0.03 18372 24 99.9 0.13
[647.06 - 676.47) 661.77 4 0.02 18376 19 99.92 0.1
[676.47 - 705.88) 691.18 1 0.01 18377 15 99.92 0.08
[705.88 - 735.3) 720.59 2 0.01 18379 14 99.93 0.08
[735.3 - 764.71) 750 4 0.02 18383 12 99.96 0.07
[764.71 - 794.12) 779.41 1 0.01 18384 8 99.96 0.04
[794.12 - 823.53) 808.83 2 0.01 18386 7 99.97 0.04
[823.53 - 852.94) 838.24 1 0.01 18387 5 99.98 0.03
[852.94 - 882.35) 867.65 0 0.00 18387 4 99.98 0.02
[882.35 - 911.77) 897.06 0 0.00 18387 4 99.98 0.02
[911.77 - 941.18) 926.47 1 0.01 18388 4 99.98 0.02
[941.18 - 970.59) 955.88 0 0.00 18388 3 99.98 0.02
[970.59 - 1000] 985.29 3 0.02 18391 3 100 0.02
Totales - 18391 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) - PM10
# ==============================================================================

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

# Extraer elementos simplificados
Lis_pm10 <- Histograma_pm10$breaks[1:(length(Histograma_pm10$breaks) - 1)]
Lss_pm10 <- Histograma_pm10$breaks[2:length(Histograma_pm10$breaks)]
MCs_pm10 <- (Lis_pm10 + Lss_pm10) / 2
nis_pm10 <- Histograma_pm10$counts

# Frecuencias relativas y acumuladas simplificadas
his_pm10 <- (nis_pm10 / N_pm10) * 100
Nis_asc_pm10 <- cumsum(nis_pm10)
His_asc_pm10 <- cumsum(his_pm10)
Nis_desc_pm10 <- rev(cumsum(rev(nis_pm10)))
His_desc_pm10 <- rev(cumsum(rev(his_pm10)))

# Crear el Data Frame Simplificado
TDF_pm10simplificado <- data.frame(
  Intervalo = paste0("[", round(Lis_pm10, 2), " - ", round(Lss_pm10, 2), ")"),
  MC = round(MCs_pm10, 2),
  ni = nis_pm10,
  hi = round(his_pm10, 2),
  Ni_asc = Nis_asc_pm10,
  Hi_asc = round(His_asc_pm10, 2),
  Ni_desc = Nis_desc_pm10,
  Hi_desc = round(His_desc_pm10, 2)
)

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

# Agregar la fila de totales
totaless_pm10 <- data.frame(
  Intervalo = "Totales",
  MC = "-",
  ni = sum(nis_pm10),
  `hi(%)` = sum(his_pm10),
  Ni_asc = "-",
  `Hi_asc (%)` = "-",
  Ni_desc = "-",
  `Hi_desc (%)` = "-"
)
# Asegurar que las columnas de totaless coincidan con los nombres finales
colnames(totaless_pm10) <- colnames(TDF_pm10simplificado)

# Unir los data frames
TDF_pm10simplificado_completa <- rbind(TDF_pm10simplificado, totaless_pm10)

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

TDF_pm10simplificado_completa %>%
  gt() %>%
  tab_header(
    title = "Tabla Nro. 2",
    subtitle = "Distribución de frecuencia simplificada de concentración de Partículas PM₁₀, 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 Partículas PM₁₀, estudio calidad del aire en India entre 2015-2020
Intervalo MC ni hi(%) Ni_asc Hi_asc (%) Ni_desc Hi_desc (%)
[0 - 100) 50 9704 52.76 9704 52.76 18391 100
[100 - 200) 150 6172 33.56 15876 86.32 8687 47.24
[200 - 300) 250 1571 8.54 17447 94.87 2515 13.68
[300 - 400) 350 633 3.44 18080 98.31 944 5.13
[400 - 500) 450 221 1.20 18301 99.51 311 1.69
[500 - 600) 550 62 0.34 18363 99.85 90 0.49
[600 - 700) 650 14 0.08 18377 99.92 28 0.15
[700 - 800) 750 8 0.04 18385 99.97 14 0.08
[800 - 900) 850 2 0.01 18387 99.98 6 0.03
[900 - 1000) 950 4 0.02 18391 100 4 0.02
Totales - 18391 100.00 - - - -
Autor: Grupo 2 Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india
# ==============================================================================
# 7. GENERACIÓN DE GRÁFICOS (PM10)
# ==============================================================================

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

hist(pm10, breaks = 13,
     main = "Gr\u00E1fica N\u00B01: Distribuci\u00F3n de la Concentraci\u00F3n de Partículas PM₁₀\npresente en el estudio sobre calidad del aire en India entre 2015-2020",
     xlab = "PM₁₀ (\u00B5g/m\u00B3)",
     ylab = "Cantidad",
     # max(nis_pm10) es la altura máxima para el histograma 'local'
     ylim = c(0, max(nis_pm10)),
     col = "darkseagreen3", # Nuevo color
     cex.main = 0.9,
     cex.lab = 1,
     cex.axis = 0.9,
     xaxt = "n")
axis(1, at = Histograma_pm10$breaks,
     labels = round(Histograma_pm10$breaks, 0), las = 1,
     cex.axis = 0.9)

# ----------------------------------
# Gráfica N°2: Histograma Global (Frecuencia Absoluta) - PM10
# ----------------------------------
hist(pm10, breaks = 13,
     main = "Gr\u00E1fica N\u00B02: Distribuci\u00F3n de la Concentraci\u00F3n de Partículas PM₁₀\npresente en el estudio sobre calidad del aire en India entre 2015-2020",
     xlab = "PM₁₀ (\u00B5g/m\u00B3)",
     ylab = "Cantidad",
     # length(pm10) es la altura máxima
     ylim = c(0, length(pm10)),
     col = "darkseagreen",
     cex.main = 1,
     cex.lab = 1,
     cex.axis = 0.9,
     xaxt = "n")
axis(1, at = Histograma_pm10$breaks,
     labels = round(Histograma_pm10$breaks, 0), las = 1,
     cex.axis = 0.9)

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

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

post_pm10 <- barplot(porcentajes_pm10,
                     space = 0,
                     col = "skyblue",
                     main = "Gr\u00E1fica N\u00B03: Distribuci\u00F3n Porcentual Global de PM₁₀\nEstudio Calidad del Aire en India, 2015-2020",
                     xlab = "PM₁₀ (\u00B5g/m\u00B3)",
                     ylab = "Porcentaje (%)",
                     ylim = c(0, 100),
                     cex.main = 0.9,
                     cex.lab = 1,
                     xaxt = "n",
                     yaxt = "n")

# Dibujamos las etiquetas del Eje X (Marca de Clase) rotadas y pequeñas
axis(side = 1,
     at = post_pm10,
     labels = marcas_clase_pm10,
     tck = -0.02,
     las = 2,
     cex.axis = 0.6)

# 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 (PM10)
# ------------------------------------------------------------------------------

n_pm10_sim <- as.numeric(nrow(TDF_pm10simplificado))
porcentajes_pm10_local <- TDF_pm10simplificado$`hi(%)`[1:(n_pm10_sim-1)]
marcas_clase_pm10_local <- TDF_pm10simplificado$MC[1:(n_pm10_sim-1)]

pos_pm10 <- barplot(
  porcentajes_pm10_local,
  space = 0,
  main = "Gr\u00E1fica N\u00B04: Distribuci\u00F3n Porcentual de Concentraci\u00F3n de Partículas PM₁₀\nEstudio Calidad del Aire en India, 2015-2020",
  ylab = "Porcentaje (%)",
  xlab = "PM₁₀ (\u00B5g/m\u00B3)",
  
  # Ajuste de Y para que la barra más alta sobresalga ligeramente si es > 80
  ylim = c(0, max(porcentajes_pm10_local) * 1.1),
  
  col = "darkseagreen",
  cex.main = 0.9,
  cex.lab = 1,
  
  # Ocultamos etiquetas automáticas para control manual
  xaxt = "n",
  yaxt = "n"
)

# Dibujamos las etiquetas del Eje X (Marca de Clase)
axis(side = 1,
     at = pos_pm10,
     labels = marcas_clase_pm10_local,
     tck = -0.04,
     las = 2,
     cex.axis = 0.6)

# Dibujamos las marcas del Eje Y
axis(side = 2,
     at = seq(0, round(max(porcentajes_pm10_local) * 1.1), by = 20),
     las = 1,
     cex.axis = 0.9)

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

CajaPM10 <- boxplot(pm10,
                    horizontal = T,
                    col = "turquoise",
                    border = "black",
                    main = "Gr\u00E1fica N\u00B05: Distribuci\u00F3n de la concentraci\u00F3n de Partículas PM₁₀,\nestudio calidad del aire en India desde 2015-2020",
                    xlab = "PM₁₀ (\u00B5g/m\u00B3)",
                    cex.main = 0.9,
                    cex.lab = 1)

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

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

# 2. Definir frecuencias acumuladas extendidas (Cantidad)
Frec_Asc_Ext_pm10 <- c(0, Nis_asc_pm10)
Frec_Desc_Ext_pm10 <- c(Nis_desc_pm10, 0)

# Ojiva ascendente
plot(Limites_X_pm10, Frec_Asc_Ext_pm10,
     type = "b",
     main = "Gr\u00E1fica N\u00B06: Ojiva ascendente y descendente de la
     distribuci\u00F3n de la concentraci\u00F3n de Partículas PM₁₀",
     
     xlab = "PM₁₀ (\u00B5g/m\u00B3)",
     ylab = "Cantidad",
     pch = 19,
     col = "turquoise",
     ylim = c(0, N_pm10),
     xlim = c(0, max(Lss_pm10)),
     
     cex.main = 0.9,
     cex.lab = 1,
     cex.axis = 0.9
)

# Ojiva descendente
lines(Limites_X_pm10, Frec_Desc_Ext_pm10,
      type = "b",
      col = "black",
      pch = 19)

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

# 1. Definir los límites de clase extendidos
Limites_X_pm10 <- c(Lis_pm10[1], Lss_pm10)

# 2. Definir frecuencias PORCENTUALES acumuladas extendidas
Frec_H_Asc_Ext_pm10 <- c(0, His_asc_pm10)
Frec_H_Desc_Ext_pm10 <- c(His_desc_pm10, 0)

# Ojiva ascendente
plot(Limites_X_pm10, Frec_H_Asc_Ext_pm10,
     type = "b",
     main = "Gr\u00E1fica N\u00B07: Ojiva ascendente y descendente de la distribuci\u00F3n PORCENTUAL de Partículas PM₁₀",
     
     xlab = "PM₁₀ (\u00B5g/m\u00B3)",
     ylab = "Porcentaje (%)",
     
     pch = 19,
     col = "blue",
     
     ylim = c(0, 100),
     xlim = c(0, max(Lss_pm10)),
     
     cex.main = 0.9,
     cex.lab = 1,
     cex.axis = 0.9
)

# Ojiva descendente
lines(Limites_X_pm10, Frec_H_Desc_Ext_pm10,
      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 (PM10)
# ==============================================================================

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

# Mediana (Me)
Me_pm10 <- median(pm10)

# Media (X)
X_pm10 <- mean(pm10)

# Moda (Mo)
moda_index_pm10 <- which.max(TDF_pm10simplificado$ni[1:(nrow(TDF_pm10simplificado)-1)])
Mo_pm10 <- TDF_pm10simplificado$Intervalo[moda_index_pm10]


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

# Varianza
Var_pm10 <- var(pm10)

# Desviación estándar (sd)
desv_pm10 <- sd(pm10)

# Coeficiente de variación (CV)
CV_pm10 <- (desv_pm10 / X_pm10) * 100


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

# Coeficiente de Asimetría (As)
As_pm10 <- skewness(pm10)

# Curtosis (K)
K_pm10 <- kurtosis(pm10)


# --------------------------------
# Creación del Data Frame (Tabla_indicadores_PM10)
# --------------------------------

Variable_PM10 <- "Partículas PM₁₀"
Rango_PM10 <- paste0("[", round(min_pm10, 2), " - ", round(max_pm10, 2), "]")

Tabla_indicadores_PM10 <- data.frame(
  Variable = Variable_PM10,
  Rango = Rango_PM10,
  X = round(X_pm10, 3),
  Me = round(Me_pm10, 3),
  Mo = Mo_pm10,
  sd = round(desv_pm10, 2),
  CV = round(CV_pm10, 2),
  As = round(As_pm10, 2),
  K = round(K_pm10, 2)
)

# Renombrar columnas para la tabla
colnames(Tabla_indicadores_PM10) <- 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_PM10 %>%
  gt() %>%
  tab_header(
    title = md("Tabla Nro. 3"),
    subtitle = md("*Indicadores Estadísticos de concentración de Partículas PM₁₀, 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 Partículas PM₁₀, 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)
Partículas PM₁₀ [0.01 - 1000] 118.13 95.68 [0 - 100) 90.61 76.70 2.05 6.74
Autor: Grupo 2 Fuente:https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india