UNIVERSIDAD CENTRAL DEL ECUADOR- FIGEMPA, INGENIERÍA AMBIENTAL
#Estadística Inferencial
#17/01/2026
#Lorien Arcentales
# Carga de paquetes
library(gt)
library(dplyr)
#1. CARGA DE DATOS
datos<-read.csv("city_day.csv", header = TRUE, dec = ".",
sep = ",")
#Extraccion de la variabela OZONO y los "-" de la variable porque son valores inexistentes,
# para un mejor analisis, cambia tamaño muestral de 29531 a 25509
ozono <- datos$O3[datos$O3 != "-"]
length(ozono)
## [1] 25509
ozono <- as.numeric(ozono)
#Justificación porque la variable es continua: porque puede tomar cualquier valor dentro de los números reales positivos, incluido el cero, sin presentar saltos en su dominio o la variable cambia de manera gradual y no pasa bruscamente de un valor a otro.
# 2. TDF simplificada
Histograma_ozono<-hist(ozono,plot = FALSE)
#Elemnetos simplificados
breaks <- Histograma_ozono$breaks
Li <- breaks[1:(length(breaks)-1)]
Ls <- breaks[2:length(breaks)]
ni<-Histograma_ozono$counts
N<-length(ozono)
hi<- (ni / N) * 100
TDF_ozonosimplificado <- data.frame(
Intervalo = paste0("[", round(Li,2), " - ", round(Ls,2), ")"),
ni = ni,
hi= round(hi, 2))
colnames(TDF_ozonosimplificado) <- c(
"Intervalo",
"ni",
"hi(%)"
)
totales<- data.frame(
Intervalo = "Totales",
ni = sum(ni), # suma total de ni
hi = sum(hi)
)
colnames(totales) <- c(
"Intervalo",
"ni",
"hi(%)"
)
# Agregar al final de la tabla
TDF_ozonosimplificado <- rbind(TDF_ozonosimplificado, totales)
TDF_ozonosimplificado %>%
gt() %>%
tab_header(
title = md("*Tabla Nro. 1*"),
subtitle = md("**Distribucion de frecuencia simplificado de concentración de ozono,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")
) %>%
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 |
| **Distribucion de frecuencia simplificado de concentración de ozono,estudio calidad del aire en India entre 2015-2020 ** |
| Intervalo |
ni |
hi(%) |
| [0 - 20) |
7022 |
27.53 |
| [20 - 40) |
10006 |
39.23 |
| [40 - 60) |
5647 |
22.14 |
| [60 - 80) |
1896 |
7.43 |
| [80 - 100) |
600 |
2.35 |
| [100 - 120) |
224 |
0.88 |
| [120 - 140) |
75 |
0.29 |
| [140 - 160) |
24 |
0.09 |
| [160 - 180) |
11 |
0.04 |
| [180 - 200) |
2 |
0.01 |
| [200 - 220) |
1 |
0.00 |
| [220 - 240) |
0 |
0.00 |
| [240 - 260) |
1 |
0.00 |
| Totales |
25509 |
100.00 |
| Autor: Grupo 2
Fuente:https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india |
# 3. GDF-Histograma de la variable
par(mar = c(5.1, 4.1, 4.1, 2.1))
post<-barplot(TDF_ozonosimplificado$`hi(%)`[1:(nrow(TDF_ozonosimplificado)-1)],
space = 0,
col = "skyblue",
main = "Gráfica N°1:Distribución de la Concentración de Ozono,
estudio calidad del aire en India, 2015-2020",
xlab = "Ozono (µg/m3)",
ylab = "Porcentaje (%)",
ylim = c(0,100), xaxt = "n")
limites <- c(post[1] - diff(post)[1]/2,
post + diff(post)[1]/2)
axis(
side = 1,
at = limites,
labels = round(breaks, 2),
tck = -0.02
)

# 4. CONJETURA
#Se conjetura que la concentración de ozono sigue un modelo de probabilidad log-normal, ya que la variable en su histograma presenta barras asimétricas hacia la derecha, con una mayor concentración de observaciones en intervalos bajos y una cola larga hacia valores altos, lo que indica una distribución sesgada positiva.
# 5. CÁLCULO DE PARÁMETROS DISTRIBUCIÓN LOG-NORMAL
min(ozono)
## [1] 0.01
log_ozono <- log(ozono)
mulog <- mean(log_ozono)
sigmalog <- sd(log_ozono)
# 6. GDF-HISTOGRAMA DENSIDAD DE PROBABILIDAD
histozono <- hist(
ozono,
breaks = breaks,
col = "skyblue",
freq = FALSE,
main = "Gráfica N°2: Comparación de la Realidad y el Modelo Log-normal
de la Concentración de Ozono (India, 2015–2020)",
xlab = " Ozono (µg/m3)",
ylab = "Densidad de probabilidad",
cex.main = 0.9, ylim = c(0,0.025)
)
x <- seq(min(ozono), max(ozono), by=0.001)
curve(
dlnorm(x, meanlog = mulog, sdlog = sigmalog),
col = "darkblue",
lwd = 3,
add = TRUE
)

# 7. TEST DE BONDAD
# Test de Pearson
fo<- ni
fo
## [1] 7022 10006 5647 1896 600 224 75 24 11 2 1 0
## [13] 1
fe<- N * (plnorm(Ls, mulog, sigmalog) - plnorm(Li, mulog, sigmalog))
Correlación<-cor(fo,fe)*100
Correlación
## [1] 96.73587
#Test de Chi-cuadrado
x2 <- sum((fo - fe)^2 / fe)
x2
## [1] 2194.129
k <- length(fo)
gl <- k - 1 - 2
gl
## [1] 10
umbral_aceptacion <- qchisq(0.9999999999, df = gl)
umbral_aceptacion
## [1] 68.16762
x2<umbral_aceptacion
## [1] FALSE
# 8. OMITIR VALORES ATÍPICOS TEMPORALMETE PARA UN MEJOR AJUSTE DEL MODELO
Cajaozono<-boxplot(ozono, horizontal = T,col = "turquoise", border = "black",
main= "Gráfica No. 3: Distribución de la concentración de ozono,
estudio calidad del aire en India desde 2015-2020",
xlab="Ozono (µg/m3)")

Q1 <- quantile(ozono, 0.25)
Q3 <- quantile(ozono, 0.75)
IQR_ozono <- Q3 - Q1
lim_inf <- Q1 - 1.5 * IQR_ozono
lim_sup <- Q3 + 1.5 * IQR_ozono
ozono_sin_atipicos <- ozono[
ozono >= lim_inf & ozono <= lim_sup]
length(ozono) # antes
## [1] 25509
length(ozono_sin_atipicos) # después
## [1] 24796
# 8.2 TDF simplificada
lim_inf <- floor(min(ozono_sin_atipicos) / 10) * 10
lim_sup <- ceiling(max(ozono_sin_atipicos) / 10) * 10
breaks_10 <- seq(lim_inf, lim_sup, by = 10)
#Elemnetos simplificados
Li <- breaks_10[1:(length(breaks_10)-1)]
Ls <- breaks_10[2:length(breaks_10)]
clases <- cut(
ozono_sin_atipicos,
breaks = breaks_10,
right = FALSE
)
ni <- as.numeric(table(clases))
N<-length(ozono_sin_atipicos)
hi<- (ni / N) * 100
TDF_ozono_sin_atícos <- data.frame(
Intervalo = paste0("[", round(Li,2), " - ", round(Ls,2), ")"),
ni = ni,
hi= round(hi, 2))
colnames(TDF_ozono_sin_atícos) <- c(
"Intervalo",
"ni",
"hi(%)"
)
totales<- data.frame(
Intervalo = "Totales",
ni = sum(ni), # suma total de ni
hi = sum(hi)
)
colnames(totales) <- c(
"Intervalo",
"ni",
"hi(%)"
)
# Agregar al final de la tabla
TDF_ozono_sin_atícos <- rbind(TDF_ozono_sin_atícos, totales)
TDF_ozono_sin_atícos %>%
gt() %>%
tab_header(
title = md("*Tabla Nro. 2*"),
subtitle = md("**Distribucion de frecuencia simplificado de concentración de ozono,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")
) %>%
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 |
| **Distribucion de frecuencia simplificado de concentración de ozono,estudio calidad del aire en India entre 2015-2020 ** |
| Intervalo |
ni |
hi(%) |
| [0 - 10) |
2310 |
9.32 |
| [10 - 20) |
4708 |
18.99 |
| [20 - 30) |
5323 |
21.47 |
| [30 - 40) |
4683 |
18.89 |
| [40 - 50) |
3430 |
13.83 |
| [50 - 60) |
2218 |
8.94 |
| [60 - 70) |
1229 |
4.96 |
| [70 - 80) |
669 |
2.70 |
| [80 - 90) |
226 |
0.91 |
| Totales |
24796 |
100.00 |
| Autor: Grupo 2
Fuente:https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india |
# 8.3 GDF-Histograma de la variable sin valores atípicos
par(mar = c(5.1, 4.1, 4.1, 2.1))
post<-barplot(TDF_ozono_sin_atícos$`hi(%)`[1:(nrow(TDF_ozono_sin_atícos)-1)],
space = 0,
col = "skyblue",
main = "Gráfica N°4:Distribución de la Concentración de Ozono,
estudio calidad del aire en India, 2015-2020",
xlab = "Ozono (µg/m3)",
ylab = "Porcentaje (%)",
ylim = c(0,30), xaxt = "n")
limites <- c(post[1] - diff(post)[1]/2,
post + diff(post)[1]/2)
axis(
side = 1,
at = limites,
labels = round(breaks_10, 2),
tck = -0.02
)

# 8.4 CONJETURA
#Se conjetura que la concentración de ozono sin valores atípicos sigue un modelo de probabilidad log-normal, ya que la variable en su histograma presenta barras asimétricas hacia la derecha, con una mayor concentración de observaciones en intervalos bajos y una cola larga hacia valores altos, lo que indica una distribución sesgada positiva.
# 8.5 CÁLCULO DE PARÁMETROS DISTRIBUCIÓN LOG-NORMAL
min(ozono_sin_atipicos)
## [1] 0.01
log_ozono_sinatípicos <- log(ozono_sin_atipicos)
mulog <- mean(log_ozono_sinatípicos)
sigmalog <- sd(log_ozono_sinatípicos)
# 8.6 GDF-HISTOGRAMA DENSIDAD DE PROBABILIDAD
histozono_sinatípicos <- hist(
ozono_sin_atipicos,
breaks = breaks_10,
col = "skyblue",
freq = FALSE,
main = "Gráfica N°5: Comparación de la Realidad y el Modelo Log-normal
de la Concentración de Ozono (India, 2015–2020)",
xlab = " Ozono (µg/m3)",
ylab = "Densidad de probabilidad",
cex.main = 0.9, ylim = c(0,0.030)
)
x <- seq(min(ozono_sin_atipicos), max(ozono_sin_atipicos), by=0.001)
curve(
dlnorm(x, meanlog = mulog, sdlog = sigmalog),
col = "darkblue",
lwd = 3,
add = TRUE
)

# 8.7 TEST DE BONDAD
# Test de Pearson
fo<- ni
fe<- N * (plnorm(Ls, mulog, sigmalog) - plnorm(Li, mulog, sigmalog))
Correlación<-cor(fo,fe)*100
Correlación
## [1] 90.06752
#Test de Chi-cuadrado
# fo y fe fracción
fo<- (ni/N)
fo
## [1] 0.093160187 0.189869334 0.214671721 0.188861107 0.138328763 0.089449911
## [7] 0.049564446 0.026980158 0.009114373
P<-c(0)
for (i in 1:9) {P[i] <-(plnorm(Histograma_ozono$breaks[i+1],mulog,
sigmalog)- plnorm(Histograma_ozono$breaks[i],mulog,sigmalog))}
fe<- P
fe
## [1] 0.362488740 0.344250935 0.150462954 0.067804843 0.032992591 0.017207902
## [7] 0.009511116 0.005516612 0.003331817
x2 <- sum((fo - fe)^2 / fe)
x2
## [1] 1.414686
k <- length(fo)
gl <- k - 1
gl
## [1] 8
umbral_aceptacion <- qchisq(1- 0.95, df = gl)
umbral_aceptacion
## [1] 2.732637
x2<umbral_aceptacion
## [1] TRUE
# 9. CÁLCULO DE PROBABILIDAD
# ¿Cuál es la probabilidad de que la concentración diaria de ozono se encuentre entre 40 y 50 µg/m³?
plnorm(50, mulog, sigmalog) - plnorm(40, mulog, sigmalog)
## [1] 0.09062237
#¿Cuál es la probabilidad de que la concentración de ozono no supere los 30 µg/m³?
plnorm(30, mulog, sigmalog)
## [1] 0.5683347
#Demostración:
x <- seq(min(ozono_sin_atipicos), max(ozono_sin_atipicos), by=0.001)
plot(x, dlnorm(x, mulog,sigmalog), col = "skyblue3", lwd = 1, xlim = c(0,100), ylim=c(0,0.030),
main="Gráfica N°6: Cálculo de probabilidad",
ylab="Densidad de probabilidad",xlab="Ozono (µg/m3)", xaxt="n")
# Definir el rango de la sección que quieres pintar
x <- seq(40, 50,0.001)
y_section <- dlnorm(x, mulog,sigmalog)
# Pintar la sección de la curva
lines(x, y_section, col = "red", lwd = 2)
# Pintar el área debajo de la línea roja
polygon(c(x, rev(x)), c(y_section, rep(0, length(y_section))), col = rgb(1, 0, 0, 0.6))
x_section2 <- seq(0, 30, by=0.001)
y_section2 <- dlnorm(x_section2, mulog, sigmalog)
lines(x_section2, y_section2, col="green", lwd=2)
polygon(c(x_section2, rev(x_section2)),
c(y_section2, rep(0, length(y_section2))),
col=rgb(0,1,0,0.4)) # verde semi-transparente
# Añadir leyenda
legend("topright", legend = c("Modelo", "Área de Probabilidad","Área de Probabilidad"), col = c("skyblue3", "red","green"), lwd = 2, pch = c(NA, 15))
# Ajustar la escala del eje x a intervalos de 25
axis(1, at = seq(0, 250, by = 10), labels = seq(0, 250, by = 10), las = 2)
