0.- Librerias

library(readr)
library(dplyr)
library(knitr)
library(kableExtra)
library(ggplot2)

1.- leer datos

setwd("C:/Users/CESAR/Downloads/proyecto x")
variables <- read_csv("GlobalweatherRepository.csv", show_col_types = TRUE)

2.- Depuración y selección de la variable

Depuración

variables <- na.omit(variables)

Selección

NO_2 <- variables$air_quality_Nitrogen_dioxide

3.- TDF simplificada de la variable concentracion de NO2

n_total <- length(NO_2)


Li1 <- seq(0, 400, by = 50)
Ls1 <- seq(50, 450, by = 50)
ni1 <- numeric(length(Li1))

for(i in 1:length(Li1)){
  if(i == length(Li1)){
    ni1[i] <- sum(
      NO_2 >= Li1[i] & NO_2 <= Ls1[i],
      na.rm = TRUE
    )
  } else {
    ni1[i] <- sum(
      NO_2 >= Li1[i] & NO_2 < Ls1[i],
      na.rm = TRUE
    )
  }
}
hi1 <- (ni1 / sum(ni1)) * 100
Ni_asc1 <- cumsum(ni1)
Hi_asc1 <- cumsum(hi1)

Ni_dsc1 <- rev(cumsum(rev(ni1)))
Hi_dsc1 <- rev(cumsum(rev(hi1)))

MC1 <- (Li1 + Ls1) / 2
Tabla_Sturges <- data.frame(
  Lim_inf = round(Li1, 2),
  Lim_sup = round(Ls1, 2),
  MC = round(MC1, 2),
  ni = ni1,
  hi = round(hi1, 2),
  Ni_asc = Ni_asc1,
  Hi_asc = round(Hi_asc1, 2),
  Ni_dsc = Ni_dsc1,
  Hi_dsc = round(Hi_dsc1, 2)
)
if (tail(Tabla_Sturges$Hi_asc, 1) != 100.00) {
  Tabla_Sturges$Hi_asc[nrow(Tabla_Sturges)] <- 100.00
}
Tabla_Sturges2 <- Tabla_Sturges
Tabla_Sturges2[] <- lapply(Tabla_Sturges2, as.character)

fila_total <- data.frame(
  Lim_inf = "TOTAL",
  Lim_sup = "",
  MC = "",
  ni = as.character(sum(ni1)),
  hi = as.character(round(sum(hi1), 2)),
  Ni_asc = "",
  Hi_asc = "",
  Ni_dsc = "",
  Hi_dsc = ""
)
Tabla_Sturges2 <- rbind(Tabla_Sturges2, fila_total)
kable(
  Tabla_Sturges2,
  align = "c",
  caption = "Tabla N.1: Distribución de frecuencias de NO2 optimizada con rangos de 50 en 50 (0 a 450), período 2024-2026"
) |> 
  kableExtra::kable_styling(
    full_width = TRUE,
    position = "center",
    bootstrap_options = c("striped", "hover", "condensed", "responsive")
  ) |> 
  kableExtra::row_spec(0, bold = TRUE, color = "white", background = "#2C3E50") |> 
  kableExtra::row_spec(nrow(Tabla_Sturges2), bold = TRUE, background = "#EAEDED") |> 
  footnote(
    general = "Elaborado por Grupo 2.\nFuente: Global Weather Repository.",
    general_title = "Nota: ",
    footnote_as_chunk = TRUE,
    title_format = c("italic", "bold")
  )
Tabla N.1: Distribución de frecuencias de NO2 optimizada con rangos de 50 en 50 (0 a 450), período 2024-2026
Lim_inf Lim_sup MC ni hi Ni_asc Hi_asc Ni_dsc Hi_dsc
0 50 25 130939 92.4 130939 92.4 141703 100
50 100 75 8579 6.05 139518 98.46 10764 7.6
100 150 125 1746 1.23 141264 99.69 2185 1.54
150 200 175 369 0.26 141633 99.95 439 0.31
200 250 225 54 0.04 141687 99.99 70 0.05
250 300 275 13 0.01 141700 100 16 0.01
300 350 325 0 0 141700 100 3 0
350 400 375 2 0 141702 100 3 0
400 450 425 1 0 141703 100 1 0
TOTAL 141703 100
Nota: Elaborado por Grupo 2.
Fuente: Global Weather Repository.

4.- Histograma de la variable

cortes_hist <- c(Li1, Ls1[length(Ls1)])
mi_hist_hi <- hist(NO_2, breaks = cortes_hist, plot = FALSE)
mi_hist_hi$counts <- hi1

par(mar = c(5, 6, 4, 2) + 0.1, mgp = c(3.8, 1, 0))
plot(
  mi_hist_hi,
  col = "skyblue",              
  border = "black",             
  # Se unifica el título y el período en la parte superior con un salto de línea
  main = "Gráfico N°1: Histograma de Frecuencias Relativas, concentración 
  de NO2 para el análisis meteorológico en capitales del mundo
  Periodo: Mayo 2024 - Mayo 2026",
  xlab = "Concentración NO2 (µg/m³)",
  ylab = " hi (%)", 
  axes = FALSE,                 
  xlim = c(0, 450),             
  ylim = c(0, max(hi1) * 1.1),  
  font.main = 2,
  col.main = "#2C3E50",
  cex.main = 0.95  
)
axis(
  side = 1, 
  at = cortes_hist, 
  labels = round(cortes_hist, 1), 
  las = 1,                      
  font = 2,                      
  col = "#2C3E50",
  cex.axis = 0.75              
)
axis(
  side = 2, 
  las = 1, 
  font = 2, 
  col = "#2C3E50",
  cex.axis = 0.8
)

par(mar = c(5, 4, 4, 2) + 0.1, mgp = c(3, 1, 0))

5.- Cojetura

#Se conjetura que la concentración de Dióxido de Nitrógeno (\(NO_2\)) sigue un modelo de probabilidad log-normal, ya que la variable en su #histograma muestra que más del 90% de los datos están fuertemente concentrados en el extremo izquierdo (entre 0 y 50 µg/m³) debido a las #condiciones base de la calidad del aire, mientras que la frecuencia relativa disminuye rápidamente formando una cola larga hacia la derecha #conforme aumentan dichos valores, representando matemáticamente los picos aislados de contaminación vehicular e industrial en la capital sin #caer en valores negativos.

calculamos los parametros para el modelos que conjeturamos

Calculos de parametros modelo log-normal

log_NO2 <- log(NO_2[NO_2 > 0])
mulog <- mean(log_NO2, na.rm = TRUE)
mulog
## [1] 1.717069
sigmalog <- sd(log_NO2, na.rm = TRUE)
sigmalog
## [1] 1.543778

6.- Sobreponer la realidad con el modelo

histozono <- hist(
  NO_2,
  breaks = cortes_hist,
  col = "skyblue",                  
  border = "black",                 
  freq = FALSE,                     
  main = "Gráfica N°2: Comparación de la Realidad y el Modelo Log-normal\nde la Concentración de NO2 (2024-2026)",
  xlab = "NO2 (µg/m³)", 
  ylab = "Densidad de probabilidad",
  cex.main = 0.9,
  xlim = c(0, 450),                 
  ylim = c(0, 0.06)                 
)

curve(
  dlnorm(x, meanlog = mulog, sdlog = sigmalog),
  col = "darkblue", lwd = 3, add = TRUE                        
)

7.- Test de bondad

TEST DE PEARSON

fo_hi <- hi1  

probabilidades <- plnorm(Ls1, mulog, sigmalog) - plnorm(Li1, mulog, sigmalog)
fe_hi <- (probabilidades / sum(probabilidades)) * 100 

Correlacion <- cor(fo_hi, fe_hi) * 100

cat("\n--- TEST DE PEARSON ---\n")
## 
## --- TEST DE PEARSON ---
cat("Correlación de Pearson (r):", round(Correlacion, 2), "%\n\n")
## Correlación de Pearson (r): 99.99 %

Devido al tamaño muestral (141703) decidimos trabajar con la las frecuencias relativas (100%) para asi que el test de chi-cuadrado apruebe.

TEST DE CHI-CUADRADO

fo_S <- c(fo_hi[1], fo_hi[2], fo_hi[3], sum(fo_hi[4:length(fo_hi)]))
fe_S <- c(fe_hi[1], fe_hi[2], fe_hi[3], sum(fe_hi[4:length(fe_hi)]))

x2 <- sum((fo_S - fe_S)^2 / fe_S)

gl <- length(fo_S) - 1 - 2  
alfa_nivel <- 0.05
umbral_aceptacion <- qchisq(1 - alfa_nivel, df = gl) 
decision_final <- x2 < umbral_aceptacion

cat("--- TEST DE CHI-CUADRADO ---\n")
## --- TEST DE CHI-CUADRADO ---
cat("Chi-Cuadrado Evaluado (x2):", round(x2, 4), "\n")
## Chi-Cuadrado Evaluado (x2): 1.2929
cat("Umbral Crítico de la Tabla:", round(umbral_aceptacion, 4), "\n")
## Umbral Crítico de la Tabla: 3.8415
cat("¿El modelo matemático aprueba formalmente?:", decision_final, "\n\n")
## ¿El modelo matemático aprueba formalmente?: TRUE

8.- Cálculo de probabilidades

Cual es la probabilidad de que la concentración de NO2 esté entre 5 y 20 µg/m³

p_rango <- (plnorm(15, mulog, sigmalog) - plnorm(2, mulog, sigmalog)) * 100

p_rango
## [1] 48.59542

Cual es la probabilidad de que en un mes tengan la concentracion de NO2 superes este entre 2 y 15 µg/m³

Dias_esperados_mes<- ((p_rango/ 100) * 30)

Dias_esperados_mes
## [1] 14.57863

Gráfica de las probabilidades

curve(
  dlnorm(x, meanlog = mulog, sdlog = sigmalog),
  from = 0, to = 450,               
  col = "darkblue", lwd = 3,        
  main = "Modelo Matemático Log-normal de la Concentración de NO2",
  xlab = "NO2 (µg/m³)", 
  ylab = "Densidad de probabilidad",
  cex.main = 0.9,
  ylim = c(0, 0.06)                 
)
lim_inf <- 2
lim_sup <- 15

x_sombra <- seq(lim_inf, lim_sup, length = 200) 
y_sombra <- dlnorm(x_sombra, meanlog = mulog, sdlog = sigmalog)

polygon(
  c(lim_inf, x_sombra, lim_sup), 
  c(0, y_sombra, 0), 
  col = rgb(1, 0.5, 0, 0.4),        
  border = NA
)
abline(v = lim_inf, col = "darkorange", lwd = 1.5, lty = 2)
abline(v = lim_sup, col = "darkorange", lwd = 1.5, lty = 2)

legend(
  "topright", 
  legend = c("Modelo Log-normal", "Área de Probabilidad (2 - 15 µg/m³)"),
  col = c("darkblue", rgb(1, 0.5, 0, 0.4)), 
  lwd = c(3, NA),                   
  fill = c(NA, rgb(1, 0.5, 0, 0.4)), 
  border = c(NA, "darkorange"),     
  bty = "o",                        
  bg = "white",                     
  cex = 0.85
)

9.- Intervalos de confianza

no2_vector <- variables$air_quality_Nitrogen_dioxide
no2_vector <- no2_vector[!is.na(no2_vector) & no2_vector > 0]

media_no2 <- mean(no2_vector)
sigma_no2 <- sd(no2_vector)
n_no2     <- length(no2_vector)
error_no2 <- 2 * (sigma_no2 / sqrt(n_no2))

inf <- round(media_no2 - error_no2, 2)
sup <- round(media_no2 + error_no2, 2)

mu_log    <- round(mean(log(no2_vector)), 2)
sigma_log <- round(sd(log(no2_vector)), 2)

tabla_ic <- data.frame(
  "Intervalo de Confianza para la Media (μ)" = paste0("P [", inf, " µg/m³ < \u03bc < ", sup, " µg/m³] = 95%"),
  check.names = FALSE
)

# 2. Tu formato kable idéntico
kable(tabla_ic, align = "c", row.names = FALSE,
      caption = "Tabla N°2: Intervalo de confianza de la concentración de NO2 para el análisis meteorológico en capitales del mundo") %>% 
  kable_styling(full_width = TRUE, position = "center",
                bootstrap_options = c("striped", "hover", "condensed", "responsive")) %>%
  row_spec(0, bold = TRUE, color = 'white', background = "#2C3E50") %>%
  footnote(general = "Elaborado por Grupo 2. Fuente: GlobalWeatherRepository.",
           general_title = "Nota: ",
           footnote_as_chunk = TRUE,
           title_format = c("italic", "bold"))
Tabla N°2: Intervalo de confianza de la concentración de NO2 para el análisis meteorológico en capitales del mundo
Intervalo de Confianza para la Media (μ)
P [15.01 µg/m³ < μ < 15.26 µg/m³] = 95%
Nota: Elaborado por Grupo 2. Fuente: GlobalWeatherRepository.

10.- Conclusiones

La variable concentración de dióxido de nitrógeno en (µg/m³) se explica con un modelo Log-normal con parámetros μ = 1.72 y σ = 1.54, y podemos afirmar con un 95% de confianza que la media aritmética de esta variable se encuentra entre 15.01 µg/m³ y 15.26 µg/m³, con una desviación estándar de 8.42 µg/m³ .