#Variable Cuantitativa Continua
# Ozono
#Autor: Ariana Viteri
#Fecha:31/05/2026

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(e1071)
## Warning: package 'e1071' was built under R version 4.5.3

1.- Carga de Datos

#Cargar los datos 
datos <- read.csv("~/semestre 3 y 4/Estadistica/Datos Cambiados.csv",
                  header = TRUE, dec = ".", sep = ",")

2.- Selección de variable

# Selección de variable
ozono<- datos$O3

# NOTA: Asumimos que la columna se llama 'O3'
ozono <- datos$O3[datos$O3 != "-"]

# Conversión a numérico
ozono <- as.numeric(ozono)

3.- Frecuencia (Conteo)

# =========================================================
# FRECUENCIAS PARA ozono
# Conteo para ozono
# Preparamos los datos que vamos a necesitar para realizar Sturges
# Regla de Sturges: k = 1 + 3.322 * log10(n)
# A = R/K
# =========================================================

# Tamaño de muestra
n <- length(ozono)

# Valor mínimo y máximo
min_ozono <- min(ozono, na.rm = TRUE)
max_ozono <- max(ozono, na.rm = TRUE)

# Rango
R <- max_ozono - min_ozono

# Número de intervalos (Regla de Sturges)
k_detallado <- ceiling(1 + 3.322 * log10(n))

# Amplitud de clase
A <- R / k_detallado

# Mostrar resultados
cat("Número de intervalos (k):", k_detallado, "\n")
## Número de intervalos (k): 16
cat("Amplitud de clase:", A, "\n")
## Amplitud de clase: 16.1075
# Generación de límites de intervalos
Li <- seq(from = min_ozono, to = max_ozono - A, by = A)
Ls <- c(seq(from = min_ozono + A, to = max_ozono - A, by = A), max_ozono)

# Redondeo
ozono <- round(ozono, 3)
Li <- round(Li, 3)
Ls <- round(Ls, 3)

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

# Frecuencias absolutas
ni <- numeric(length(Li))

for(i in 1:length(Li)){
  if(i < length(Li)){
    ni[i] <- sum(ozono >= Li[i] & ozono < Ls[i])
  } else {
    ni[i] <- sum(ozono >= Li[i] & ozono <= 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)))

# Intervalos
Intervalo <- paste0("[", round(Li, 2), " - ", round(Ls, 2), ")")

# Último intervalo cerrado
Intervalo[length(Intervalo)] <- paste0(
  "[",
  round(Li[length(Li)], 2),
  " - ",
  round(Ls[length(Ls)], 2),
  "]"
)

# Tabla de distribución de frecuencias
TDF_ozono <- 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)
)

# Fila de totales
totales <- data.frame(
  Intervalo = "Totales",
  MC = "-",
  ni = sum(ni),
  hi = round(sum(hi), 2),
  Ni_ascendente = "-",
  Ni_descendente = "-",
  Hi_ascendente = "-",
  Hi_descendente = "-"
)
# Tabla completa
TDF_ozono_completa <- rbind(TDF_ozono, totales)

4.- Tabla distribución de frecuencia

Tabla con Regla de Sturges

#TABLA DE FRECUENCIAS DETALLADA

TDF_ozono_completa %>%
  gt() %>%
  tab_header(
    title = "Tabla Nro. 1",
    subtitle = "Distribución de frecuencia de concentración de Ozono (O3), estudio calidad del aire en India entre 2015-2020"
  ) %>%
  tab_source_note(
    source_note = md("Grupo: 1 <br> Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india ")
  ) %>%
  tab_style(
    style = cell_borders(sides = "left", color = "black", weight = px(2)),
    locations = cells_body()
  ) %>%
  tab_style(
    style = cell_borders(sides = "right", color = "black", weight = px(2)),
    locations = cells_body()
  ) %>%
  tab_style(
    style = cell_borders(sides = "left", color = "black", weight = px(2)),
    locations = cells_column_labels()
  ) %>%
  tab_style(
    style = cell_borders(sides = "right", color = "black", weight = px(2)),
    locations = cells_column_labels()
  ) %>%
  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 Ozono (O3), estudio calidad del aire en India entre 2015-2020
Intervalo MC ni hi Ni_ascendente Ni_descendente Hi_ascendente Hi_descendente
[0.01 - 16.12) 8.06 4880 19.13 4880 25509 19.13 100
[16.12 - 32.23) 24.17 8602 33.72 13482 20629 52.85 80.87
[32.23 - 48.33) 40.28 6518 25.55 20000 12027 78.4 47.15
[48.33 - 64.44) 56.39 3291 12.90 23291 5509 91.31 21.6
[64.44 - 80.55) 72.49 1298 5.09 24589 2218 96.39 8.69
[80.55 - 96.66) 88.6 521 2.04 25110 920 98.44 3.61
[96.66 - 112.76) 104.71 226 0.89 25336 399 99.32 1.56
[112.76 - 128.87) 120.82 96 0.38 25432 173 99.7 0.68
[128.87 - 144.98) 136.92 45 0.18 25477 77 99.87 0.3
[144.98 - 161.08) 153.03 19 0.07 25496 32 99.95 0.13
[161.08 - 177.19) 169.14 9 0.04 25505 13 99.98 0.05
[177.19 - 193.3) 185.25 1 0.00 25506 4 99.99 0.02
[193.3 - 209.41) 201.35 2 0.01 25508 3 100 0.01
[209.41 - 225.51) 217.46 0 0.00 25508 1 100 0
[225.51 - 241.62) 233.57 0 0.00 25508 1 100 0
[241.62 - 257.73] 249.68 1 0.00 25509 1 100 0
Totales - 25509 100.00 - - - -
Grupo: 1
Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india

Tabla Simplificada

# ==============================================================================
# Por una gran cantidad de intervalos se realizara una reducción de filas en la
# tabla Nro. 2 creando solo 10 intervalos
# ==============================================================================

# 1. Calculamos el rango y definimos la amplitud necesaria para 10 intervalos
min_oz <- floor(min(ozono, na.rm = TRUE))
max_oz <- ceiling(max(ozono, na.rm = TRUE))

# Redondeamos la amplitud hacia arriba para asegurar que cubra el rango en 10 pasos
A_ajustada <- ceiling((max_oz - min_oz) / 10)

# 2. Definimos los cortes (breaks) forzando los 10 intervalos
mis_breaks <- seq(from = min_oz, by = A_ajustada, length.out = 11)

# 3. Generamos el histograma con esos breaks
histo_ozono <- hist(ozono, breaks = mis_breaks, plot = FALSE)

# 4. Extraemos límites y calculamos estadísticas
Li2 <- histo_ozono$breaks[1:(length(histo_ozono$breaks)-1)]
Ls2 <- histo_ozono$breaks[2:length(histo_ozono$breaks)]

MC2 <- (Li2 + Ls2) / 2

ni2 <- histo_ozono$counts
hi2 <- (ni2 / sum(ni2)) * 100

Ni2_asc <- cumsum(ni2)
Hi2_asc <- cumsum(hi2)

Ni2_desc <- rev(cumsum(rev(ni2)))
Hi2_desc <- rev(cumsum(rev(hi2)))

# 5. Creamos los intervalos como texto
Intervalo2 <- paste0("[", Li2, " - ", Ls2, ")")

Intervalo2[length(Intervalo2)] <- paste0(
  "[",
  Li2[length(Li2)],
  " - ",
  Ls2[length(Ls2)],
  "]"
)

# 6. Construcción de la tabla
TDF_ozono_final <- data.frame(
  Intervalo = Intervalo2,
  MC = MC2,
  ni = ni2,
  hi = round(hi2, 2),
  Ni_asc = Ni2_asc,
  Hi_asc = round(Hi2_asc, 2),
  Ni_desc = Ni2_desc,
  Hi_desc = round(Hi2_desc, 2)
)

# 7. Totales
totaless <- data.frame(
  Intervalo = "Totales",
  MC = "-",
  ni = sum(ni2),
  hi = sum(hi2),
  Ni_asc = "-",
  Hi_asc = "-",
  Ni_desc = "-",
  Hi_desc = "-"
)

TDF_ozono_final <- rbind(TDF_ozono_final, totaless)

# 8. Tabla con gt()
TDF_ozono_final %>%
  gt() %>%
  tab_header(
    title = md("*Tabla Nro. 2*"),
    subtitle = md("*Distribución de frecuencia simplificada de concentración de Ozono, estudio calidad del aire en India 2015-2020*")
  ) %>%
  tab_source_note(
    source_note = md("Autor: Grupo 1 <br> Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india")
  ) %>%
  tab_style(
    style = cell_borders(sides = c("left", "right"), color = "black", weight = px(2)),
    locations = cells_body()
  ) %>%
  tab_style(
    style = cell_borders(sides = c("left", "right"), color = "black", weight = px(2)),
    locations = cells_column_labels()
  ) %>%
  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 Ozono, estudio calidad del aire en India 2015-2020
Intervalo MC ni hi Ni_asc Hi_asc Ni_desc Hi_desc
[0 - 26) 13 10183 39.92 10183 39.92 25509 100
[26 - 52) 39 10801 42.34 20984 82.26 15326 60.08
[52 - 78) 65 3493 13.69 24477 95.95 4525 17.74
[78 - 104) 91 759 2.98 25236 98.93 1032 4.05
[104 - 130) 117 200 0.78 25436 99.71 273 1.07
[130 - 156) 143 53 0.21 25489 99.92 73 0.29
[156 - 182) 169 16 0.06 25505 99.98 20 0.08
[182 - 208) 195 3 0.01 25508 100 4 0.02
[208 - 234) 221 0 0.00 25508 100 1 0
[234 - 260] 247 1 0.00 25509 100 1 0
Totales - 25509 100.00 - - - -
Autor: Grupo 1
Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india

5.- Gráficos distribución de frecuencia

Poligono de frecuencia

# ==============================================================================
# Histograma de Ozono con poligono de frecuencia 
hist(ozono,
     breaks = mis_breaks,
     main = "Gráfica Nro. 1\nHistograma con el polígono de frecuencias de Ozono\nen el estudio calidad del aire en India de 2015-2020",
     xlab = "Ozono (µg/m³)",
     ylab = "Cantidad",
     col = "lightsteelblue",
     xaxt = "n",
     cex.main = 0.9,
     ylim = c(0, max(histo_ozono$counts) * 1.1))

# Cuadrícula
abline(v = mis_breaks, col = "gray70", lty = 2, lwd = 0.8)
abline(h = axTicks(2), col = "gray70", lty = 2, lwd = 0.8)
# Redibujar histograma encima de la cuadrícula
hist(ozono,breaks = mis_breaks,col = "lightsteelblue",add = TRUE)
# Polígono de frecuencias
lines(MC2, ni2,
      type = "o",
      col = "red3",
      pch = 16,
      lwd = 2)

# Eje X personalizado
axis(1,at = mis_breaks,labels = round(mis_breaks, 0),las = 1,cex.axis = 0.9)

Histogramas de cantidad

# Histograma de Ozono generado por R Studio
# ==============================================================================
# 1. Creamos el histograma y guardamos la información
histo_ozono <- hist(ozono,breaks = mis_breaks,plot = FALSE)

# 2. Creamos el marco del gráfico
hist(ozono,
     breaks = mis_breaks,
     main = "Gráfica Nro. 2\nDistribución de frecuencias de concentración de Ozono\nen el estudio calidad del aire en India de 2015-2020",
     xlab = "Ozono (µg/m³)",
     ylab = "Cantidad",
     col = "darkseagreen3",
     ylim = c(0, max(histo_ozono$counts) * 1.1),
     xaxt = "n",
     cex.main = 0.9)

# 3. Agregamos las líneas de la cuadrícula
abline(v = mis_breaks,col = "gray70",lty = 2,lwd = 0.8)

abline(h = axTicks(2),col = "gray70",lty = 2,lwd = 0.8)

# 4. Redibujamos el histograma encima para que las barras queden al frente
hist(ozono,breaks = mis_breaks,col = "darkseagreen3",add = TRUE)

# 5. Creamos el eje X personalizado
axis(1,
     at = mis_breaks,
     labels = round(mis_breaks, 0),
     las = 1,
     cex.axis = 0.9)

#======================================================
#Histograma con relación a la totalidad de los datos
par(mgp = c(4, 1, 0))
hist(ozono,
     breaks = mis_breaks,
     main = "Gráfica Nro. 3\nDistribución de frecuencias de concentración de Ozono\nen el estudio calidad del aire en India de 2015-2020",
     xlab = "Ozono (µg/m³)",
     ylab = "Cantidad",
     col = "darkseagreen3",
     ylim = c(0, length(ozono)),
     xaxt = "n",
     yaxt = "n",   # <- importante
     cex.main = 0.9)

# Cuadrícula
abline(v = mis_breaks, col = "gray70", lty = 2, lwd = 0.8)

abline(h = seq(0, ceiling(length(ozono)/5000)*5000, by = 5000),
       col = "gray70", lty = 2, lwd = 0.8)

# Redibujamos el histograma
hist(ozono,
     breaks = mis_breaks,
     col = "darkseagreen3",
     add = TRUE)

# Eje X
axis(1,
     at = mis_breaks,
     labels = round(mis_breaks, 0),
     las = 1,
     cex.axis = 0.9)

# Eje Y cada 5000
axis(2,
     at = seq(0, ceiling(length(ozono)/5000)*5000, by = 5000),
     las = 1)

Histogramas Porcentuales

# ================================
# Histograma que genera r studio porcentual
plot(histo_ozono,
     freq = FALSE,
     main = "Gráfica Nro. 4\nDistribución porcentual de concentración de Ozono\nen el estudio calidad del aire en India de 2015-2020",
     xlab = "Ozono (µg/m³)",
     ylab = "Porcentaje ",
     xaxt = "n",
     cex.main = 1,
     ylim = c(0, max(hi2) * 1.1))

# Cuadrícula
abline(v = mis_breaks, col = "gray70", lty = 2, lwd = 0.8)
abline(h = axTicks(2), col = "gray70", lty = 2, lwd = 0.8)

# Barras porcentuales
rect(histo_ozono$breaks[-length(histo_ozono$breaks)],
     0,
     histo_ozono$breaks[-1],
     hi2, #hi2 es hi simplificado 
     col = "darkseagreen3",
     border = "black")

# Eje X personalizado
axis(1,
     at = mis_breaks,
     labels = round(mis_breaks, 0),
     las = 1,
     cex.axis = 0.9)

#=================================================
# Histograma porcentual con respecto al total
plot(histo_ozono,
     freq = FALSE,
     main = "Gráfica Nro. 5\nDistribución porcentual de concentración de Ozono\nen el estudio calidad del aire en India de 2015-2020",
     xlab = "Ozono (µg/m³)",
     ylab = "Porcentaje",
     xaxt = "n",
     cex.main = 1,
     ylim = c(0, 100))

# Cuadrícula
abline(v = mis_breaks, col = "gray70", lty = 2, lwd = 0.8)
abline(h = axTicks(2), col = "gray70", lty = 2, lwd = 0.8)

# Barras porcentuales
rect(histo_ozono$breaks[-length(histo_ozono$breaks)],
     0,
     histo_ozono$breaks[-1],
     hi2, # hi2 es hi simplificado
     col = "darkseagreen3",
     border = "black")

# Eje X personalizado
axis(1,
     at = mis_breaks,
     labels = round(mis_breaks, 0),
     las = 1,
     cex.axis = 0.9)

6.- Diagrama de caja y bigotes

# Diagrama de caja de Ozono

boxplot(ozono,
        horizontal = TRUE,
        main = "Gráfica Nro. 6\nDiagrama de caja de la concentración de Ozono\nen el estudio calidad del aire en India de 2015-2020",
        xlab = "Ozono (µg/m³)",
        col = "turquoise",
        border = "black",
        cex.main = 0.9,
        xaxt = "n")

# Líneas grises entrecortadas cada 20 unidades
abline(v = seq(0, 260, by = 20),
       col = "gray70",
       lty = 2,
       lwd = 0.8)

# Eje X cada 20 unidades
axis(1,
     at = seq(0, 260, by = 20),
     labels = seq(0, 260, by = 20),
     cex.axis = 0.9)

7.- Diagrama de Ojivas

Ojiva cantidad

#=================================================
# Ojivas ascendente y descendente
par(mgp = c(3.3, 1, 0))
plot(Ls2, Ni2_asc,
     type = "o",
     pch = 16,
     col = "firebrick4",
     lwd = 2,
     main = "Gráfica Nro. 7\nDistribución de frecuencia ascendente y descendente de Ozono\nen el estudio calidad del aire en India de 2015-2020",
     xlab = "Ozono (µg/m³)",
     ylab = "Frecuencia",
     ylim = c(0, n),
     xaxt = "n",
     yaxt = "n",
     cex.main = 0.9)

# Cuadrícula
abline(v = mis_breaks,
       col = "gray70",
       lty = 2,
       lwd = 0.8)
# Ojiva descendente
lines(Ls2, Ni2_desc,
      type = "o",
      pch = 16,
      col = "steelblue4",
      lwd = 2)

# Eje X personalizado
axis(1,
     at = mis_breaks,
     labels = round(mis_breaks, 0),
     las = 1,
     cex.axis = 0.9)

# Eje Y cada 5000
axis(2,
     at = seq(0, n, by = 5000),
     las = 1)

# Cuadrícula horizontal
abline(h = seq(0, n, by = 5000),
       col = "gray70",
       lty = 2,
       lwd = 0.8)
# Leyenda
legend("right",
       legend = c("Ojiva ascendente", "Ojiva descendente"),
       col = c("firebrick4", "steelblue4"),
       lwd = 2,
       pch = 16)

Ojiva porcentual

# Ojivas porcentuales ascendente y descendente

plot(Ls2, Hi2_asc,
     type = "o",
     pch = 16,
     col = "firebrick4",
     lwd = 2,
     main = "Gráfica Nro. 8\nDistribución de frecuencia ascendente y descendente de Ozono\nen el estudio calidad del aire en India de 2015-2020",
     xlab = "Ozono (µg/m³)",
     ylab = "Porcentaje",
     ylim = c(0, 100),
     xlim = c(min(Ls2), max(Ls2)),
     xaxt = "n",
     cex.main = 0.9)

# Cuadrícula
abline(v = Ls2,
       col = "gray70",
       lty = 2,
       lwd = 0.8)

abline(h = seq(0, 100, by = 20),
       col = "gray70",
       lty = 2,
       lwd = 0.8)

# Ojiva descendente
lines(Ls2, Hi2_desc,
      type = "o",
      pch = 16,
      col = "steelblue4",
      lwd = 2)

# Eje X personalizado (sin el 0)
axis(1,
     at = Ls2,
     labels = round(Ls2, 0),
     las = 1,
     cex.axis = 0.9)

# Leyenda
legend("right",
       legend = c("Ojiva ascendente", "Ojiva descendente"),
       col = c("firebrick4", "steelblue4"),
       lwd = 2,
       pch = 16)

8.-Indicadores Estadísticos

# =========================================================
# TABLA Nro. 3 - INDICADORES ESTADÍSTICOS DE OZONO
# =========================================================

library(gt)
library(e1071)
library(dplyr)

# =========================================================
# MEDIDAS DE TENDENCIA CENTRAL
# =========================================================

# Media
X <- mean(ozono, na.rm = TRUE)

# Mediana
Me <- median(ozono, na.rm = TRUE)

# Moda (intervalo modal de la tabla simplificada)
tabla_sin_totales <- TDF_ozono_final[-nrow(TDF_ozono_final), ]
moda_index <- which.max(tabla_sin_totales$ni)
Mo <- tabla_sin_totales$Intervalo[moda_index]
# =========================================================
# MEDIDAS DE DISPERSIÓN
# =========================================================

# Rango
min_oz <- min(ozono, na.rm = TRUE)
max_oz <- max(ozono, na.rm = TRUE)

Rango <- paste0(
  "[",
  round(min_oz, 2),
  " - ",
  round(max_oz, 2),
  "]"
)

# Desviación estándar
sd_oz <- sd(ozono, na.rm = TRUE)

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

# =========================================================
# MEDIDAS DE FORMA
# =========================================================

# Asimetría
As <- skewness(ozono, na.rm = TRUE)

# Curtosis
K <- kurtosis(ozono, na.rm = TRUE)

# =========================================================
# VALORES ATÍPICOS (MISMO MÉTODO DEL BOXPLOT DE R)
# =========================================================

# Valores atípicos detectados por el diagrama de caja
atipicos <- boxplot.stats(ozono)$out

# Contar atípicos por intervalo de la tabla simplificada
conteo_atipicos <- numeric(length(Li2))

for(i in 1:length(Li2)){
  
  if(i < length(Li2)){
    
    conteo_atipicos[i] <- sum(
      atipicos >= Li2[i] &
        atipicos < Ls2[i]
    )
    
  } else {
    
    conteo_atipicos[i] <- sum(
      atipicos >= Li2[i] &
        atipicos <= Ls2[i]
    )
  }
}

# Intervalo de la tabla simplificada con más valores atípicos
Intervalo_Atipico <- Intervalo2[which.max(conteo_atipicos)]
# =========================================================
# TABLA DE INDICADORES
# =========================================================

Tabla_Indicadores_Ozono <- data.frame(
  Variable = "Ozono",
  Rango = Rango,
  Media = round(X, 2),
  Mediana = round(Me, 2),
  Moda = Mo,
  Desv_Est = round(sd_oz, 2),
  CV = round(CV, 2),
  Asimetria = round(As, 2),
  Curtosis = round(K, 2),
  Valores_Atipicos = Intervalo_Atipico
)
# =========================================================
# TABLA Nro. 3
# =========================================================

Tabla_Indicadores_Ozono %>%
  gt() %>%
  
  tab_header(
    title = "Tabla Nro. 3",
    subtitle = "Indicadores Estadísticos de la concentración de Ozono, estudio calidad del aire en India entre 2015-2020"
  ) %>%
  
  tab_spanner(
    label = "Tendencia Central",
    columns = c(Media, Mediana, Moda)
  ) %>%
  
  tab_spanner(
    label = "Dispersión",
    columns = c(Desv_Est, CV)
  ) %>%
  
  tab_spanner(
    label = "Forma",
    columns = c(Asimetria, Curtosis)
  ) %>%
  
  cols_label(
    Variable = "Variable",
    Rango = "Rango",
    Media = "Media (X)",
    Mediana = "Mediana (Me)",
    Moda = "Moda (Mo)",
    Desv_Est = "Desv. Est. (sd)",
    CV = "CV (%)",
    Asimetria = "Asimetría (As)",
    Curtosis = "Curtosis (K)",
    Valores_Atipicos = "Valores Atípicos"
  ) %>%
  
  tab_source_note(
    source_note = md(
      "Autor: Grupo 1<br>Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india"
    )
  ) %>%
  
  # Líneas verticales del cuerpo
  tab_style(
    style = cell_borders(
      sides = c("left", "right"),
      color = "black",
      weight = px(1)
    ),
    locations = cells_body()
  ) %>%
  
  # Líneas verticales de encabezados
  tab_style(
    style = cell_borders(
      sides = c("left", "right"),
      color = "black",
      weight = px(1)
    ),
    locations = cells_column_labels()
  ) %>%
  
  # Líneas verticales de grupos
  tab_style(
    style = cell_borders(
      sides = c("left", "right"),
      color = "black",
      weight = px(1)
    ),
    locations = cells_column_spanners()
  ) %>%
  
  tab_options(
    
    table.border.top.color = "black",
    table.border.bottom.color = "black",
    table.border.top.width = px(2),
    table.border.bottom.width = px(2),
    column_labels.border.top.color = "black",
    column_labels.border.bottom.color = "black",
    column_labels.border.bottom.width = px(1),
    heading.border.bottom.color = "black",
    heading.border.bottom.width = px(1),
    table_body.hlines.color = "gray70",
    row.striping.include_table_body = FALSE
  )
Tabla Nro. 3
Indicadores Estadísticos de la concentración de Ozono, estudio calidad del aire en India entre 2015-2020
Variable Rango
Tendencia Central
Dispersión
Forma
Valores Atípicos
Media (X) Mediana (Me) Moda (Mo) Desv. Est. (sd) CV (%) Asimetría (As) Curtosis (K)
Ozono [0.01 - 257.73] 34.49 30.84 [26 - 52) 21.69 62.9 1.33 3.43 [78 - 104)
Autor: Grupo 1
Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india

9.- Conclusión

En conclusión:

La variable Ozono fluctúa entre un mínimo de 0.01 y un máximo de 257.73 microgramos por metro cúbico (µg/m³), con una mediana de 30.84 y una desviación estándar de 21.69. Debido a un coeficiente de variación del 62.90%, se concluye que es un conjunto de valores heterogéneos. Los datos se acumulan de manera predominante en el intervalo modal [26-52),lo que indica una concentración moderadamente alta con asimetría positiva, se han detectado 713 valores atípicos, mayormente ubicados en el intervalo [78-104], los cuales representan concentraciones inusualmente elevadas de ozono que pueden influir en la calidad del aire.

Por lo expuesto anteriormente, el comportamiento de la variable ozono presenta un impacto moderadamente negativo en el medio ambiente.