UNIVERSIDAD CENTRAL DEL ECUADOR

PROYECTO:ESTUDIO ESTADÍSTICO DE LA CALIDAD DEL AIRE EN INDIA

FECHA: 22/11/2025

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

# Cargar librerías necesarias
library(gt)
library(dplyr)

# Carga de datos
# El archivo ya está cargado en el entorno
datos <- read.csv("C:/Users/JOSELYN/Desktop/kangle/Datos Cambiados.csv", # ¡ATENCIÓN! Ruta cambiada para usar el archivo cargado.
                  header = TRUE,
                  sep = ",",
                  dec = ".")
# ==============================================================================
# 2. PREPARACIÓN Y LIMPIEZA DE DATOS DE MATERIA PARTICULADA PM2.5
# ==============================================================================

# Extracción de los "-" (valores inexistentes) de la variable PM2.5
# Usando la notación de corchetes con el nombre de la columna que contiene el punto
pm25 <- datos$PM2.5[datos$PM2.5 != "-"]

# Tamaño muestral después de la limpieza
cat("Tamaño muestral de la Materia Particulada PM2.5 (sin '-'):", length(pm25), "\n")
## Tamaño muestral de la Materia Particulada PM2.5 (sin '-'): 24933
# Conversión a numérico
pm25 <- as.numeric(pm25)

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

N <- length(pm25)
min_pm25 <- min(pm25)
max_pm25 <- max(pm25)
R <- max_pm25 - min_pm25

# Número de clases (k): Se mantienen 34 clases para replicar la estructura original
k_detallado <- 34

# Amplitud de clase (A)
A <- R / k_detallado

# Generación de límites de intervalos
Li <- seq(from = min_pm25, to = max_pm25 - A, by = A)
Ls <- c(seq(from = min_pm25 + A, to = max_pm25 - A, by = A), max_pm25)

# Redondeo para cálculos de intervalos precisos
pm25 <- round(pm25, 3)
Li <- round(Li, 3)
Ls <- round(Ls, 3)

# Marcas de Clase (MC)
MC <- (Li + Ls) / 2

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

# Frecuencias relativas y acumuladas
hi <- (ni / N) * 100
Ni_asc <- cumsum(ni)
Ni_desc <- rev(cumsum(rev(ni)))
Hi_asc <- cumsum(hi)
Hi_desc <- rev(cumsum(rev(hi)))

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

# Crear el Data Frame (TDF)
TDF_pm25 <- data.frame(
  Intervalo = Intervalo,
  MC = round(MC, 2),
  ni = ni,
  hi = round(hi, 2),
  Ni_ascendente = Ni_asc,
  Ni_descendente = Ni_desc,
  Hi_ascendente = round(Hi_asc, 2),
  Hi_descendente = round(Hi_desc, 2)
)

# Agregar la fila de totales
totales <- data.frame(
  Intervalo = "Totales",
  MC = "-",
  ni = sum(ni),
  hi = sum(hi),
  Ni_ascendente = "-",
  Ni_descendente = "-",
  Hi_ascendente = "-",
  Hi_descendente = "-"
)
TDF_pm25_completa <- rbind(TDF_pm25, totales)

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

TDF_pm25_completa %>%
  gt() %>%
  tab_header(
    title = "Tabla Nro. 1",
    subtitle = "Distribución de frecuencia de concentración de Materia Particulada (PM2.5), 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 Materia Particulada (PM2.5), estudio calidad del aire en India entre 2015-2020
Intervalo MC ni hi Ni_ascendente Ni_descendente Hi_ascendente Hi_descendente
[0.04 - 27.98) 14.01 5946 23.85 5946 24933 23.85 100
[27.98 - 55.92) 41.95 8318 33.36 14264 18987 57.21 76.15
[55.92 - 83.86) 69.89 4831 19.38 19095 10669 76.59 42.79
[83.86 - 111.8) 97.83 2178 8.74 21273 5838 85.32 23.41
[111.8 - 139.74) 125.77 1159 4.65 22432 3660 89.97 14.68
[139.74 - 167.68) 153.71 753 3.02 23185 2501 92.99 10.03
[167.68 - 195.62) 181.65 533 2.14 23718 1748 95.13 7.01
[195.62 - 223.56) 209.59 370 1.48 24088 1215 96.61 4.87
[223.56 - 251.5) 237.53 284 1.14 24372 845 97.75 3.39
[251.5 - 279.44) 265.47 177 0.71 24549 561 98.46 2.25
[279.44 - 307.38) 293.41 122 0.49 24671 384 98.95 1.54
[307.38 - 335.32) 321.35 55 0.22 24726 262 99.17 1.05
[335.32 - 363.26) 349.29 59 0.24 24785 207 99.41 0.83
[363.26 - 391.2) 377.23 38 0.15 24823 148 99.56 0.59
[391.2 - 419.14) 405.17 25 0.10 24848 110 99.66 0.44
[419.14 - 447.08) 433.11 21 0.08 24869 85 99.74 0.34
[447.08 - 475.02) 461.04 17 0.07 24886 64 99.81 0.26
[475.02 - 502.96) 488.98 10 0.04 24896 47 99.85 0.19
[502.96 - 530.89) 516.92 6 0.02 24902 37 99.88 0.15
[530.89 - 558.83) 544.86 6 0.02 24908 31 99.9 0.12
[558.83 - 586.77) 572.8 4 0.02 24912 25 99.92 0.1
[586.77 - 614.71) 600.74 2 0.01 24914 21 99.92 0.08
[614.71 - 642.65) 628.68 2 0.01 24916 19 99.93 0.08
[642.65 - 670.59) 656.62 2 0.01 24918 17 99.94 0.07
[670.59 - 698.53) 684.56 2 0.01 24920 15 99.95 0.06
[698.53 - 726.47) 712.5 1 0.00 24921 13 99.95 0.05
[726.47 - 754.41) 740.44 1 0.00 24922 12 99.96 0.05
[754.41 - 782.35) 768.38 0 0.00 24922 11 99.96 0.04
[782.35 - 810.29) 796.32 0 0.00 24922 11 99.96 0.04
[810.29 - 838.23) 824.26 3 0.01 24925 11 99.97 0.04
[838.23 - 866.17) 852.2 1 0.00 24926 8 99.97 0.03
[866.17 - 894.11) 880.14 1 0.00 24927 7 99.98 0.03
[894.11 - 922.05) 908.08 5 0.02 24932 6 100 0.02
[922.05 - 949.99] 936.02 1 0.00 24933 1 100 0
Totales - 24933 100.00 - - - -
Autor: Grupo 2 Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india
#============================
# 1. CARGA DE PAQUETES Y DATOS (Replicado para integridad)
# ==============================================================================

# Cargar librerías necesarias
library(gt)
library(dplyr)

# Carga de datos
datos <- read.csv("C:/Users/JOSELYN/Desktop/kangle/Datos Cambiados.csv",
                  header = TRUE,
                  sep = ",",
                  dec = ".")

# ==============================================================================
# 2. PREPARACIÓN Y LIMPIEZA DE DATOS DE MATERIA PARTICULADA PM2.5 (Replicado para integridad)
# ==============================================================================

# Extracción de los "-" (valores inexistentes) de la variable PM2.5
pm25 <- datos$PM2.5[datos$PM2.5 != "-"]
# Conversión a numérico
pm25 <- as.numeric(pm25)
# Redondeo para cálculos de intervalos precisos
pm25 <- round(pm25, 3)

# Definir N (Tamaño muestral)
N <- length(pm25)
min_pm25 <- min(pm25)
max_pm25 <- max(pm25)

# ==============================================================================
# 5. CÁLCULOS PARA LA DISTRIBUCIÓN SIMPLIFICADA (13 CLASES)
# ==============================================================================

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

# Extraer elementos simplificados
Lis <- Histograma_pm25$breaks[1:(length(Histograma_pm25$breaks) - 1)]
Lss <- Histograma_pm25$breaks[2:length(Histograma_pm25$breaks)]
MCs <- (Lis + Lss) / 2
nis <- Histograma_pm25$counts

# Frecuencias relativas y acumuladas simplificadas
his <- (nis / N) * 100
Nis_asc <- cumsum(nis)
His_asc <- cumsum(his)
Nis_desc <- rev(cumsum(rev(nis)))
His_desc <- rev(cumsum(rev(his)))

# Crear el Data Frame Simplificado
TDF_pm25simplificado <- data.frame(
  Intervalo = paste0("[", round(Lis, 2), " - ", round(Lss, 2), ")"),
  MC = round(MCs, 2),
  ni = nis,
  hi = round(his, 2),
  Ni_asc = Nis_asc,
  Hi_asc = round(His_asc, 2),
  Ni_desc = Nis_desc,
  Hi_desc = round(His_desc, 2)
)

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

# Agregar la fila de totales (Usando nombres temporales para compatibilidad)
totaless <- data.frame(
  Intervalo = "Totales",
  MC = "-",
  ni = sum(nis),
  hi = sum(his),
  Ni_asc = "-",
  Hi_asc = "-",
  Ni_desc = "-",
  Hi_desc = "-"
)

# Asegurar que las columnas de totaless coincidan con los nombres finales
colnames(totaless) <- colnames(TDF_pm25simplificado)

# Unir los data frames
TDF_pm25simplificado_completa <- rbind(TDF_pm25simplificado, totaless)

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

TDF_pm25simplificado_completa %>%
  gt() %>%
  tab_header(
    title = "Tabla Nro. 2",
    # *** Título actualizado a PM2.5 ***
    subtitle = "Distribución de frecuencia simplificada de concentración de Materia Particulada (PM2.5), 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 Materia Particulada (PM2.5), estudio calidad del aire en India entre 2015-2020
Intervalo MC ni hi(%) Ni_asc Hi_asc (%) Ni_desc Hi_desc (%)
[0 - 100) 50 20516 82.28 20516 82.28 24933 100
[100 - 200) 150 3281 13.16 23797 95.44 4417 17.72
[200 - 300) 250 843 3.38 24640 98.82 1136 4.56
[300 - 400) 350 193 0.77 24833 99.6 293 1.18
[400 - 500) 450 63 0.25 24896 99.85 100 0.4
[500 - 600) 550 18 0.07 24914 99.92 37 0.15
[600 - 700) 650 6 0.02 24920 99.95 19 0.08
[700 - 800) 750 2 0.01 24922 99.96 13 0.05
[800 - 900) 850 6 0.02 24928 99.98 11 0.04
[900 - 1000) 950 5 0.02 24933 100 5 0.02
Totales - 24933 100.00 - - - -
Autor: Grupo 2 Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india
# El código asume que las variables 'pm25' y 'TDF_pm25simplificado' (creadas en los pasos anteriores)
# y 'Histograma_pm25' (creada en la Sección 5) están disponibles en el entorno.

# Usaremos la variable Histograma_pm25 generada previamente
# Histograma_pm25 <- hist(pm25, breaks = 13, plot = FALSE)
# nis <- Histograma_pm25$counts
# TDF_pm25simplificado <- # Data Frame simplificado (Tabla Nro. 2 sin totales)

# ------------------------------------------------------------------------------
# 7. GRÁFICA N°1: Histograma Local (Frecuencia Absoluta - Eje Y ajustado a la frecuencia más alta)
# ------------------------------------------------------------------------------

hist(pm25, breaks = 13,
     # *** Título y variable actualizados a PM2.5 ***
     main = "Gr\u00E1fica N\u00B01: Distribuci\u00F3n de la Concentraci\u00F3n de Materia Particulada (PM2.5)
     presente en el estudio sobre calidad del aire en India entre 2015-2020",
     # *** Etiqueta del eje X actualizada a PM2.5 ***
     xlab = "PM2.5 (\u00B5g/m\u00B3)",
     ylab = "Cantidad",
     # max(nis) es la altura máxima de la frecuencia absoluta más alta (7871)
     ylim = c(0, max(Histograma_pm25$counts)),
     col = "darkseagreen3", # Nuevo color
     cex.main = 0.9,
     cex.lab = 1,
     cex.axis = 0.9,
     xaxt = "n")
axis(1, at = Histograma_pm25$breaks,
     labels = round(Histograma_pm25$breaks, 0), las = 1,
     cex.axis = 0.9)

# ----------------------------------
# Gráfica N°2: Histograma Global (Frecuencia Absoluta - Eje Y ajustado al tamaño total de la muestra)
# ----------------------------------
hist(pm25, breaks = 13,
     # *** Título y variable actualizados a PM2.5 ***
     main = "Gr\u00E1fica N\u00B02: Distribuci\u00F3n de la Concentraci\u00F3n de Materia Particulada (PM2.5)
     presente en el estudio sobre calidad del aire en India entre 2015-2020",
     # *** Etiqueta del eje X actualizada a PM2.5 ***
     xlab = "PM2.5 (\u00B5g/m\u00B3)",
     ylab = "Cantidad",
     # length(pm25) es la altura máxima (32549)
     ylim = c(0, length(pm25)),
     col = "darkseagreen",
     cex.main = 1,
     cex.lab = 1,
     cex.axis = 0.9,
     xaxt = "n")
axis(1, at = Histograma_pm25$breaks,
     labels = round(Histograma_pm25$breaks, 0), las = 1,
     cex.axis = 0.9)

# ------------------------------------------------------------------------------
# Gráfica N°3: Histograma Porcentual Global (Superposición Eje Y 0-100%)
# ------------------------------------------------------------------------------

# Para esta gráfica, usaremos el 'hi(%)' de la tabla simplificada.
n <- as.numeric(nrow(TDF_pm25simplificado))
porcentajes <- TDF_pm25simplificado$`hi(%)`[1:(n-1)]
marcas_clase <- TDF_pm25simplificado$MC[1:(n-1)]

post <- barplot(porcentajes,
                space = 0,
                col = "skyblue",
                # *** Título actualizado a PM2.5 ***
                main = "Gr\u00E1fica N\u00B03: Distribuci\u00F3n Porcentual Global de PM2.5
                Estudio Calidad del Aire en India, 2015-2020",
                # *** Etiqueta del eje X actualizada a PM2.5 ***
                xlab = "PM2.5 (\u00B5g/m\u00B3)",
                ylab = "Porcentaje (%)",
                # Fijamos el límite Y entre 0 y 100
                ylim = c(0, 100), 
                cex.main = 0.9,
                cex.lab = 1,
                xaxt = "n",
                yaxt = "n") 

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

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

# ------------------------------------------------------------------------------
# Gráfica N°4: Histograma Porcentual Local (Ajustado para máximo en 80)
# ------------------------------------------------------------------------------

n <- as.numeric(nrow(TDF_pm25simplificado))
porcentajes <- TDF_pm25simplificado$`hi(%)`[1:(n-1)]
marcas_clase <- TDF_pm25simplificado$MC[1:(n-1)]

pos <- barplot(
  porcentajes,
  space = 0,
  # *** Título actualizado a PM2.5 ***
  main = "Gr\u00E1fica N\u00B04: Distribuci\u00F3n Porcentual de Concentraci\u00F3n de PM2.5
  Estudio Calidad del Aire en India, 2015-2020",
  ylab = "Porcentaje (%)",
  # *** Etiqueta del eje X actualizada a PM2.5 ***
  xlab = "PM2.5 (\u00B5g/m\u00B3)",
  
  # AJUSTE CLAVE 1: Fijamos el límite Y en 80 (para que la barra más alta, 24.18%, sobresalga)
  ylim = c(0, 80),
  
  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,
     labels = marcas_clase,
     tck = -0.04,    
     las = 2,      # Rota etiquetas verticalmente
     cex.axis = 0.6) 

# AJUSTE CLAVE 2: Dibujamos las marcas del Eje Y solo hasta 80
axis(side = 2,
     at = seq(0, 80, by = 20), 
     las = 1,      # Horizontal
     cex.axis = 0.9)

# El código asume que las variables 'pm25', 'N', 'Lis', 'Lss',
# 'Nis_asc', 'Nis_desc', 'His_asc', 'His_desc' (creadas en los pasos anteriores)
# están disponibles en el entorno.

# Símbolo para microgramos/metro cúbico (µg/m³)
unidades_pm25 <- "PM2.5 (\u00B5g/m\u00B3)"

# El código asume que las variables 'pm25', 'N', 'Lis', 'Lss',
# 'Nis_asc', 'Nis_desc' (creadas en los pasos anteriores)
# están disponibles en el entorno.

# Símbolo para microgramos/metro cúbico (µg/m³)
unidades_pm25 <- "PM2.5 (\u00B5g/m\u00B3)"

# ------------------------------------------------------------------------------
# Gráfica N°5: Diagrama de Caja (Box Plot) para Materia Particulada (PM2.5)
# ------------------------------------------------------------------------------

CajaPM25 <- boxplot(pm25, 
                    horizontal = TRUE,
                    col = "turquoise", 
                    border = "black",
                    # *** Título y variable actualizados a PM2.5 ***
                    main = "Gr\u00E1fica N\u00B05: Distribuci\u00F3n de la concentraci\u00F3n de Materia Particulada (PM2.5),
                    estudio calidad del aire en India desde 2015-2020",
                    # *** Etiqueta del eje X actualizada a PM2.5 ***
                    xlab = "PM2.5",
                    # Ajustes de texto
                    cex.main = 0.9,
                    cex.lab = 1)

# ------------------------------------------------------------------------------
# Gráfica N°6: Ojiva Ascendente y Descendente (Frecuencia Absoluta) para PM2.5
# ------------------------------------------------------------------------------

# 1. Definir los límites de clase extendidos (añadiendo el punto cero)
# Esto asegura que la gráfica inicie en 0 y termine en el máximo.
Limites_X <- c(Lis[1], Lss) # [Min_PM25, Ls1, Ls2, ..., Ls_max]

# 2. Definir frecuencias acumuladas extendidas

# Frecuencia Ascendente: [0, Ni_asc1, Ni_asc2, ..., N]
Frec_Asc_Ext <- c(0, Nis_asc) 

# Frecuencia Descendente: [N, Ni_desc1, Ni_desc2, ..., 0]
# La frecuencia descendente de la última clase es 0, no la de la penúltima.
Frec_Desc_Ext <- c(Nis_desc, 0)

# Ojiva ascendente
plot(Limites_X, Frec_Asc_Ext, 
     type = "b", 
     # *** Título y variable actualizados a PM2.5 ***
     main = "Gr\u00E1fica N\u00B06: Ojiva ascendente y descendente de la
     distribuci\u00F3n de la concentraci\u00F3n de Materia Particulada (PM2.5)",
     
     # Ajustamos la etiqueta X para PM2.5
     xlab = "PM2.5",
     ylab = "Cantidad", 
     
     pch = 19,
     col = "turquoise", 
     
     # Aseguramos que el eje Y cubra desde 0 hasta el total de datos (N)
     ylim = c(0, N), 
     
     # Aseguramos que el eje X vaya desde 0 hasta el límite superior máximo
     xlim = c(0, max(Lss)), 
     
     cex.main = 0.9,
     cex.lab = 1,
     cex.axis = 0.9
)

# Ojiva descendente (Usa los mismos Limites_X extendidos)
lines(Limites_X, Frec_Desc_Ext, 
      type = "b", 
      col = "black", 
      pch = 19)

# El código asume que las variables 'pm25', 'N', 'Lis', 'Lss',
# 'His_asc', 'His_desc' (creadas en los pasos anteriores)
# están disponibles en el entorno.

# La etiqueta del eje X es simplemente la variable:
etiqueta_eje_x <- "PM2.5"

# ------------------------------------------------------------------------------
# Gráfica N°7: Ojiva Ascendente y Descendente PORCENTUAL para Materia Particulada (PM2.5)
# ------------------------------------------------------------------------------

# 1. Definir los límites de clase extendidos (igual que en la Gráfica N°6)
# Esto asegura que la gráfica inicie y termine correctamente en el eje X.
Limites_X <- c(Lis[1], Lss) 

# 2. Definir frecuencias PORCENTUALES acumuladas extendidas

# Frecuencia Ascendente: [0, Hi_asc1, Hi_asc2, ..., 100]
Frec_H_Asc_Ext <- c(0, His_asc) 

# Frecuencia Descendente: [100, Hi_desc1, Hi_desc2, ..., 0]
# Nota: La última clase debe terminar en 0%.
Frec_H_Desc_Ext <- c(His_desc, 0)

# Ojiva ascendente (usa Límites Extendidos y Frecuencia Relativa Acumulada Ascendente)
plot(Limites_X, Frec_H_Asc_Ext, 
     type = "b", 
     # *** Título y variable actualizados a PM2.5 ***
     main = "Gr\u00E1fica N\u00B07: Ojiva ascendente y descendente de la
     distribuci\u00F3n PORCENTUAL de Materia Particulada (PM2.5)",
     
     # Etiqueta X simplificada a "PM2.5"
     xlab = "PM2.5",
     # Etiqueta Y para Porcentaje
     ylab = "Porcentaje (%)", 
     
     pch = 19,
     col = "blue", # Color azul para la ascendente
     
     # Ajuste CLAVE: El eje Y va de 0 a 100
     ylim = c(0, 100), 
     
     # Aseguramos que el eje X vaya desde 0 hasta el límite superior máximo
     xlim = c(0, max(Lss)), 
     
     cex.main = 0.9,
     cex.lab = 1,
     cex.axis = 0.9
)

# Ojiva descendente (Usa los mismos Limites_X extendidos)
lines(Limites_X, Frec_H_Desc_Ext, 
      type = "b", 
      col = "red", # Color rojo para la descendente
      pch = 19)

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

# El código asume que las variables 'pm25', 'min_pm25', 'max_pm25' y
# 'TDF_pm25simplificado' (creadas en los pasos anteriores) están disponibles.

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

# Carga de librería para Asimetría y Curtosis
library(e1071) 
# Librerías gt y dplyr ya cargadas.

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

# Mediana (Me)
Me <- median(pm25)

# Media (X)
X <- mean(pm25)

# Moda (Mo)
# Obtenemos el intervalo de la clase con la frecuencia más alta (Moda de la distribución simplificada)
moda_index <- which.max(TDF_pm25simplificado$ni[1:(nrow(TDF_pm25simplificado)-1)])
Mo <- TDF_pm25simplificado$Intervalo[moda_index]


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

# Varianza
Var_pm25 <- var(pm25)

# Desviación estándar (sd)
desv <- sd(pm25)

# Coeficiente de variación (CV)
CV <- (desv / X) * 100

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

# Coeficiente de Asimetria (As)
As <- skewness(pm25)

# Curtosis (K)
K <- kurtosis(pm25)


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

Variable_PM25 <- "Materia Particulada (PM2.5)"
Rango_PM25 <- paste0("[", round(min_pm25, 2), " - ", round(max_pm25, 2), "]")

Tabla_indicadores <- data.frame(
  Variable = Variable_PM25,
  Rango = Rango_PM25,
  X = round(X, 3),
  Me = round(Me, 3), 
  Mo = Mo,
  sd = round(desv, 2),
  CV = round(CV, 2),
  As = round(As, 2),
  K = round(K, 2)
)

# Renombrar columnas para la tabla (Mejora de Legibilidad)
colnames(Tabla_indicadores) <- c("Variable", "Rango", "Media (X)", "Mediana (Me)", "Moda (Mo)", "Desv. Est. (sd)", "CV (%)", "Asimetria (As)", "kurtosis (K)")


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

Tabla_indicadores %>%
  gt() %>%
  tab_header(
    title = md("Tabla Nro. 3"),
    # Usando códigos Unicode en el subtítulo para "Estadísticos" y "Concentración"
    subtitle = md("*Indicadores Estad\u00EDsticos de concentraci\u00F3n de Materia Particulada (PM2.5), 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 (Mejora de la presentación)
  tab_spanner(
    label = "Tendencia Central",
    columns = c("Media (X)", "Mediana (Me)", "Moda (Mo)")
  ) %>%
  tab_spanner(
    # Usando código Unicode para 'Dispersión'
    label = "Dispersion",
    columns = c("Desv. Est. (sd)", "CV (%)")
  ) %>%
  tab_spanner(
    label = "Forma",
    # Usando código Unicode para seleccionar las columnas "Asimetria (As)" y "Curtosis (K)"
    columns = c("Asimetria (As)", "kurtosis (K)")
  ) %>%
  # Formateo de números
  fmt_number(
    # Usando código Unicode para referenciar las columnas
    columns = c("Media (X)", "Mediana (Me)", "Desv. Est. (sd)", "CV (%)", "Asimetria (As)", "kurtosis (K)"),
    decimals = 2
  ) %>%
  # Opciones de estilo (basado en tu plantilla)
  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 Materia Particulada (PM2.5), estudio calidad del aire en India entre 2015-2020 *
Variable Rango
Tendencia Central
Dispersion
Forma
Media (X) Mediana (Me) Moda (Mo) Desv. Est. (sd) CV (%) Asimetria (As) kurtosis (K)
Materia Particulada (PM2.5) [0.04 - 949.99] 67.45 48.57 [0 - 100) 64.66 95.86 3.37 21.13
Autor: Grupo 2 Fuente:https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india