# Estadística Inferencial - Preparación de Datos
# Variable Cuantitativa Discreta (AQI)
# Autor: Ariel Chiluisa

# 0. CARGA DE LIBRERÍAS
library(gt)
## Warning: package 'gt' was built under R version 4.5.3
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.5.3
## 
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(dplyr)

# 1. CARGA DE DATOS
datos <- read.csv(
  "MAPA QGIS/Datos Cambiados.csv",
  header = TRUE,
  sep = ",",
  dec = "."
)

# 2. SELECCIÓN Y LIMPIEZA DE LA VARIABLE AQI
AQI <- datos$AQI
AQI <- AQI[AQI != "-"]
AQI <- as.numeric(AQI)
AQI <- AQI[!is.na(AQI)]

# 3. EXTRACCIÓN DE FRECUENCIAS Y PROBABILIDAD
# Definición de límites numéricos
Li <- c(0, 100, 200, 300, 400, 500)
Ls <- c(100, 200, 300, 400, 500, max(AQI))

# Conteo de frecuencia absoluta (ni) usando tu lógica original
ni <- numeric(length(Li))

for(i in 1:length(Li)){
  if(i < length(Li)){
    ni[i] <- sum(AQI >= Li[i] & AQI < Ls[i])
  } else {
    ni[i] <- sum(AQI >= Li[i] & AQI <= Ls[i]) # El último intervalo se cierra
  }
}

N <- sum(ni)

# Cálculo de frecuencia relativa porcentual (hi) y probabilidad p(s)
hi <- (ni / N) * 100
p_s <- ni / N  # Esto es equivalente a hi/100

# Etiquetas de los intervalos en formato texto
Intervalo <- c(
  "[0 - 100)",
  "[100 - 200)",
  "[200 - 300)",
  "[300 - 400)",
  "[400 - 500)",
  paste0("[500 - ", max(AQI), "]")
)

# 4. CREACIÓN DE LA TABLA DE DISTRIBUCIÓN DE FRECUENCIAS (TDF)
# Ensamblamos el data frame solo con las 4 columnas requeridas
TDF_AQI_simplificada <- data.frame(
  Intervalo = Intervalo,
  ni = ni,
  hi = round(hi, 2),
  p_s = round(p_s, 2)
)

# Renombramos las columnas para que queden exactas a tu formato
colnames(TDF_AQI_simplificada) <- c("Intervalo", "ni", "hi(%)", "p(s)")

# Fila de totales corregida
totales <- data.frame(
  Intervalo = "Totales",
  ni = sum(ni),
  hi = 100,      # El total teórico siempre es 100%
  p_s = 1        # El total teórico siempre es 1
)

colnames(totales) <- c("Intervalo", "ni", "hi(%)", "p(s)")

# Unimos los datos con la fila de totales
TDF_AQI_simplificada <- rbind(TDF_AQI_simplificada, totales)

# 5. APLICACIÓN DEL DISEÑO
TDF_AQI_simplificada %>%
  gt() %>%
  # --- ESTA ES LA LÍNEA NUEVA ---
  fmt_number(
    columns = c("hi(%)", "p(s)"), 
    decimals = 2
  ) %>%
  # ------------------------------
tab_header(
  title = md("*Tabla Nro. 1*"),
  subtitle = md("**Distribución de frecuencia simplificada del Índice de Calidad del Aire (AQI), estudio calidad del aire en India entre 2015-2020**")
) %>%
  tab_source_note(
    source_note = md("Autor: Ariel Chiluisa\nFuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india")
  ) %>%
  tab_options(
    # Bordes horizontales superiores e inferiores
    table.border.top.color = "black",
    table.border.bottom.color = "black",
    table.border.top.style = "solid",
    table.border.bottom.style = "solid",
    
    # Bordes de las cabeceras
    column_labels.border.top.color = "black",
    column_labels.border.bottom.color = "black",
    column_labels.border.bottom.width = px(2),
    heading.border.bottom.color = "black",
    heading.border.bottom.width = px(2),
    
    # Líneas internas horizontales
    row.striping.include_table_body = TRUE,
    table_body.hlines.color = "gray",
    table_body.border.bottom.color = "black",
    
    # Líneas verticales para los márgenes exteriores (Estilo SO2)
    table.border.left.color = "black",
    table.border.left.style = "solid",
    table.border.left.width = px(1),
    table.border.right.color = "black",
    table.border.right.style = "solid",
    table.border.right.width = px(1),
    
    # Líneas verticales para separar las columnas internamente (Estilo SO2)
    column_labels.vlines.color = "black",
    column_labels.vlines.style = "solid",
    column_labels.vlines.width = px(1),
    table_body.vlines.color = "black",
    table_body.vlines.style = "solid",
    table_body.vlines.width = px(1)
  )
Tabla Nro. 1
Distribución de frecuencia simplificada del Índice de Calidad del Aire (AQI), estudio calidad del aire en India entre 2015-2020
Intervalo ni hi(%) p(s)
[0 - 100) 9343 37.60 0.38
[100 - 200) 9009 36.25 0.36
[200 - 300) 2790 11.23 0.11
[300 - 400) 2359 9.49 0.09
[400 - 500) 804 3.24 0.03
[500 - 2049] 545 2.19 0.02
Totales 24850 100.00 1.00
Autor: Ariel Chiluisa Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india
# 4. GRÁFICA DE DISTRIBUCIÓN DE FRECUENCIAS (GDF)

# Ajuste de márgenes para que los títulos y etiquetas largas no se corten
par(mar = c(5.1, 5.1, 4.1, 2.1)) 

# Usamos los vectores originales 'hi' e 'Intervalo' que calculamos en el Paso 3 
# (antes de que se les añadiera la fila de "Totales")
porcentajes_plot <- hi
nombres_plot <- Intervalo

# Creamos el lienzo base y guardamos las posiciones X de las barras en la variable 'barras'
# (Esta variable 'barras' te servirá en el siguiente paso para centrar el modelo geométrico)
barras <- barplot(
  height = porcentajes_plot,
  names.arg = nombres_plot,
  space = 0.4,             # Espacio entre barras, crucial para variables discretas
  col = "skyblue",         # Color distinto al naranja del SO2 para diferenciar variables
  border = "black",
  main = "Gráfica N°1: Distribución porcentual del Índice de Calidad del Aire (AQI)\nen estudio calidad del aire en India, 2015-2020",
  xlab = "Índice de Calidad del Aire (AQI)",
  ylab = "Porcentaje (%)",
  las = 1,                 # Valores del eje Y horizontales para fácil lectura
  ylim = c(0, max(porcentajes_plot) * 1.15), # Espacio extra en el tope
  cex.names = 0.85         # Ajusta el tamaño de los nombres de los intervalos
)

# Añadimos la cuadrícula horizontal (líneas guía)
abline(h = pretty(c(0, max(porcentajes_plot))), col = "gray70", lty = 2, lwd = 0.8)

# Truco estético: Volvemos a dibujar las barras encima usando add = TRUE 
# Esto hace que las líneas grises de la cuadrícula queden por debajo del color, viéndose más profesional
barplot(
  height = porcentajes_plot,
  space = 0.4,
  col = "skyblue",
  border = "black",
  add = TRUE,              # Superpone sobre la cuadrícula
  axes = FALSE,            # Evita que se repinten los ejes y se vean borrosos
  names.arg = rep("", length(nombres_plot)) # No repinta los nombres
)

# Borde exterior de la gráfica
box()

# 5. Conjetura
# Se conjetura que el Índice de Calidad del Aire (AQI), tratado aquí como una 
# variable discreta, se ajusta a un modelo de probabilidad geométrica. Esto se 
# justifica porque su diagrama de barras muestra que la mayor cantidad de datos 
# se concentra en el extremo izquierdo (intervalos de menor contaminación, [0-200)), 
# y la frecuencia decae drásticamente a medida que los valores del índice aumentan.
# Visualmente, representa el equivalente discreto de un decaimiento exponencial.

# 6. COMPARACIÓN DEL MODELO VS LA REALIDAD (Modelo Geométrico)

# A. Cálculo del parámetro del modelo geométrico (p)
# Mapeamos los 6 intervalos a valores discretos (0, 1, 2, 3, 4, 5)
x_mapped <- 0:5

# Usamos la probabilidad real en decimales (p_s original sin la fila de totales)
p_s_data <- hi / 100 

# Calculamos la esperanza matemática (media) multiplicando x por su probabilidad
media_x <- sum(x_mapped * p_s_data)

# Calculamos el parámetro de probabilidad (p) del modelo geométrico
prob_geom <- 1 / (1 + media_x)

# B. Cálculo de las probabilidades esperadas (Teóricas)
# Usamos dgeom() para los primeros 5 intervalos (x = 0 a 4)
esperada_normal <- dgeom(0:4, prob = prob_geom)

# Para el último intervalo [500 - max], al ser la "cola" derecha, sumamos todo lo que falta
esperada_cola <- 1 - pgeom(4, prob = prob_geom)

# Unimos las probabilidades teóricas y las pasamos a porcentaje
hi_modelo <- c(esperada_normal, esperada_cola) * 100

# C. Creación de la matriz para la gráfica agrupada
# Unimos la realidad (hi) y el modelo (hi_modelo) en una tabla de 2 filas
datos_comparacion <- rbind(Realidad = hi, Modelo = hi_modelo)

# D. Generación de la Gráfica
par(mar = c(6.1, 4.1, 4.1, 2.1)) # Márgenes para acomodar los títulos

# Creamos el barplot agrupado
grafica_comp <- barplot(
  datos_comparacion,
  beside = TRUE,              # ¡Esta es la clave para que salgan lado a lado!
  names.arg = Intervalo[1:6], # Etiquetas del Eje X
  col = c("blue", "red"),     # Colores según la imagen de referencia
  main = "Gráfica N° 2: Comparación de la Realidad vs el Modelo Geométrico\ndel Índice de Calidad del Aire (AQI) en India",
  xlab = "Índice de Calidad del Aire (AQI)",
  ylab = "Probabilidad (%)",
  ylim = c(0, max(datos_comparacion) * 1.35), # Damos bastante espacio arriba para la leyenda
  las = 1,
  cex.names = 0.85
)

# Añadimos cuadrícula de fondo para mejor lectura
abline(h = pretty(c(0, max(datos_comparacion))), col = "gray80", lty = 2)

# Repintamos las barras para que queden sobre las líneas de la cuadrícula
barplot(
  datos_comparacion,
  beside = TRUE,
  col = c("blue", "red"),
  add = TRUE,
  axes = FALSE,
  names.arg = rep("", 6)
)

# E. Añadimos la leyenda horizontal en la parte superior (como en la foto)
legend(
  "top",
  legend = c("Realidad", "Modelo geométrico"),
  fill = c("blue", "red"),
  bty = "n",       # "n" quita el borde de la caja
  horiz = TRUE,    # Hace que la leyenda sea horizontal
  inset = c(0, 0),
  cex = 0.9
)

# Cerramos con el borde exterior
box()

# 7. TEST DE BONDAD

# Rescatamos las probabilidades teóricas calculadas en el Paso 6
P_teorica <- c(esperada_normal, esperada_cola)

# --- TEST DE PEARSON ---

# Para Pearson mantenemos la estructura original del SO2 que usaba frecuencias absolutas
fo_pearson <- ni
fe_pearson <- N * P_teorica

Coef_Pearson <- cor(fo_pearson, fe_pearson) * 100

# Resultado de Pearson
cat("Coeficiente de Pearson (%):", round(Coef_Pearson, 2), "\n")
## Coeficiente de Pearson (%): 91.48
# --- TEST CHI-CUADRADO ---

# Total de datos 
N_chi <- sum(ni)

# Frecuencia relativa observada (Aplicando la estructura de tu código SO2)
fo <- ni / N_chi

# Número de intervalos
k <- length(fo)

# Probabilidades teóricas esperadas (ya calculadas en el Paso 6)
fe <- P_teorica 

# Chi-cuadrado calculado con frecuencias relativas
Chi_Calculado <- sum((fo - fe)^2 / fe)

# Grados de libertad
gl <- k - 1

# Valor crítico (α = 0.05)
Chi_Critico <- qchisq(0.95, df = gl)

# Resultados
cat("\nChi Calculado:", round(Chi_Calculado, 4), "\n")
## 
## Chi Calculado: 0.0929
cat("Chi Crítico:", round(Chi_Critico, 4), "\n")
## Chi Crítico: 11.0705
# Decisión
if (Chi_Calculado < Chi_Critico) {
  print("Evalua H0: El modelo geométrico es adecuado.")
} else {
  print("Se rechaza H0: El modelo geométrico no es adecuado.")
}
## [1] "Evalua H0: El modelo geométrico es adecuado."
# 8. CÁLCULO DE PROBABILIDAD E INTERVALO DE CONFIANZA

# A. Cálculo de la probabilidad (AQI > 100 puntos)
# Un AQI > 100 suele indicar que el aire empieza a ser perjudicial.
prob_supera_100 <- 1 - dgeom(0, prob = prob_geom)

cat("Probabilidad de registrar un AQI mayor a 100:", round(prob_supera_100 * 100, 2), "%\n")
## Probabilidad de registrar un AQI mayor a 100: 52.63 %
# B. Intervalo de Confianza (Tabla)
# Calculamos la media real usando los datos originales limpios de AQI
media_aqi <- mean(AQI)
desviacion_aqi <- sd(AQI)
n_aqi <- length(AQI)

# Nivel de confianza del 95% (Z = 1.96)
error_aqi <- 1.96 * (desviacion_aqi / sqrt(n_aqi)) 

# ¡CORRECCIÓN ESTADÍSTICA! 
# Redondeamos a 0 decimales porque el AQI es una variable DISCRETA
limite_inferior_aqi <- round(media_aqi - error_aqi, 0)
limite_superior_aqi <- round(media_aqi + error_aqi, 0)

tabla_intervalo_aqi <- data.frame(
  Intervalo = paste0("P [", limite_inferior_aqi, " < µ < ", limite_superior_aqi, "] = 95%")
)

# Aplicamos el formato estético de tu plantilla gt()
tabla_intervalo_aqi %>%
  gt() %>%
  tab_header(
    title = md("*Tabla Nro. 2*"),
    subtitle = md("**Intervalo de confianza del Índice de Calidad del Aire (AQI)**")
  ) %>%
  tab_source_note(
    source_note = md("Autor: Ariel Chiluisa\nFuente: 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",
    table.border.left.color = "black", table.border.left.style = "solid", table.border.left.width = px(1),
    table.border.right.color = "black", table.border.right.style = "solid", table.border.right.width = px(1)
  )
Tabla Nro. 2
Intervalo de confianza del Índice de Calidad del Aire (AQI)
Intervalo
P [165 < µ < 168] = 95%
Autor: Ariel Chiluisa Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india
# 9. CONCLUSIÓN DEL ANÁLISIS

# Definimos el texto integrando automáticamente los valores generados enteros
texto_conclusion_aqi <- paste0(
  "El análisis del Índice de Calidad del Aire (AQI) revela que la distribución de los datos se ajusta ",
  "a un modelo geométrico (p = ", round(prob_geom, 3), "), validado matemáticamente mediante la prueba de Pearson (",
  round(Coef_Pearson, 2), "%). Con un nivel de confianza del 95%, se estima que el promedio real de ",
  "la calidad del aire en la región se sitúa entre los [", limite_inferior_aqi, " y ", limite_superior_aqi, "] puntos. ",
  "Aunque existe una probabilidad del ", round(prob_supera_100 * 100, 2), "% de registrar un AQI perjudicial (>100), ",
  "la gráfica demuestra una fuerte concentración de valores en los intervalos iniciales, indicando que ",
  "la calidad del aire se mantiene en rangos aceptables la mayor parte del periodo estudiado (2015-2020)."
)

df_conclusion_aqi <- data.frame(Texto = texto_conclusion_aqi)

# Recuadro visual final de conclusión
df_conclusion_aqi %>%
  gt() %>%
  tab_header(
    title = md("## **CONCLUSIÓN DEL ANÁLISIS**")
  ) %>%
  tab_options(
    column_labels.hidden = TRUE,
    table.border.top.color = "black",
    table.border.bottom.color = "black",
    table.border.top.width = px(3),
    table.border.bottom.width = px(3),
    table.background.color = "#FDFEFE",
    table.width = pct(90)
  ) %>%
  tab_style(
    style = list(
      cell_text(align = "justify", size = px(15), font = "Arial"),
      cell_borders(sides = c("left", "right", "top", "bottom"), color = "#A6ACAF", weight = px(1.5))
    ),
    locations = cells_body()
  )

CONCLUSIÓN DEL ANÁLISIS

El análisis del Índice de Calidad del Aire (AQI) revela que la distribución de los datos se ajusta a un modelo geométrico (p = 0.474), validado matemáticamente mediante la prueba de Pearson (91.48%). Con un nivel de confianza del 95%, se estima que el promedio real de la calidad del aire en la región se sitúa entre los [165 y 168] puntos. Aunque existe una probabilidad del 52.63% de registrar un AQI perjudicial (>100), la gráfica demuestra una fuerte concentración de valores en los intervalos iniciales, indicando que la calidad del aire se mantiene en rangos aceptables la mayor parte del periodo estudiado (2015-2020).