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

0.- Carga de Librerias

#Carga de Librerias
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
# NOTA: Asumimos que la columna se llama 'NOx'
NOx <- datos$NOx[datos$NOx != "-"]

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

3.- Frecuencia

# =========================================================
# FRECUENCIAS PARA NOx
# Tamaño de muestra
n <- length(NOx)

# Valor mínimo y máximo
min_NOx <- min(NOx, na.rm = TRUE)
max_NOx <- max(NOx, na.rm = TRUE)

# Rango
R <- max_NOx - min_NOx

# 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: 29.22687
# Generación de límites de intervalos
Li <- seq(from = min_NOx, to = max_NOx - A, by = A)
Ls <- c(seq(from = min_NOx + A, to = max_NOx - A, by = A), max_NOx)

# Redondeo
NOx <- round(NOx, 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(NOx >= Li[i] & NOx < Ls[i])
  } else {
    ni[i] <- sum(NOx >= Li[i] & NOx <= 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_NOx <- 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_NOx_completa <- rbind(TDF_NOx, totales)

4.- Tabla de distribución de frecuencia

Tabla con regla de Sturges

#TABLA DE FRECUENCIAS DETALLADA

TDF_NOx_completa %>%
  gt() %>%
  tab_header(
    title = "Tabla Nro. 1",
    subtitle = "Distribución de frecuencia de concentración de Óxidos de Nitrógeno (NOx), 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 Óxidos de Nitrógeno (NOx), estudio calidad del aire en India entre 2015-2020
Intervalo MC ni hi Ni_ascendente Ni_descendente Hi_ascendente Hi_descendente
[0 - 29.23) 14.61 15554 61.37 15554 25346 61.37 100
[29.23 - 58.45) 43.84 6269 24.73 21823 9792 86.1 38.63
[58.45 - 87.68) 73.07 1961 7.74 23784 3523 93.84 13.9
[87.68 - 116.91) 102.29 830 3.27 24614 1562 97.11 6.16
[116.91 - 146.13) 131.52 401 1.58 25015 732 98.69 2.89
[146.13 - 175.36) 160.75 191 0.75 25206 331 99.45 1.31
[175.36 - 204.59) 189.97 76 0.30 25282 140 99.75 0.55
[204.59 - 233.82) 219.2 35 0.14 25317 64 99.89 0.25
[233.82 - 263.04) 248.43 18 0.07 25335 29 99.96 0.11
[263.04 - 292.27) 277.66 5 0.02 25340 11 99.98 0.04
[292.27 - 321.5) 306.88 2 0.01 25342 6 99.98 0.02
[321.5 - 350.72) 336.11 0 0.00 25342 4 99.98 0.02
[350.72 - 379.95) 365.34 2 0.01 25344 4 99.99 0.02
[379.95 - 409.18) 394.56 1 0.00 25345 2 100 0.01
[409.18 - 438.4) 423.79 0 0.00 25345 1 100 0
[438.4 - 467.63] 453.02 1 0.00 25346 1 100 0
Totales - 25346 100.00 - - - -
Grupo: 1
Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india

Tabla de intervalos reducidos

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

# TABLA 2
k_tabla2 <- 10

# Nueva amplitud
A2 <- R / k_tabla2

# Nuevos límites
Li2 <- seq(from = min_NOx, to = max_NOx - A2, by = A2)
Ls2 <- c(seq(from = min_NOx + A2, to = max_NOx - A2, by = A2), max_NOx)

# Redondeo
Li2 <- round(Li2, 3)
Ls2 <- round(Ls2, 3)

# Marcas de clase
MC2 <- (Li2 + Ls2) / 2

# Frecuencias absolutas
ni2 <- numeric(length(Li2))

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

# Frecuencias relativas y acumuladas
hi2 <- (ni2 / n) * 100
Ni2_asc <- cumsum(ni2)
Ni2_desc <- rev(cumsum(rev(ni2)))
Hi2_asc <- cumsum(hi2)
Hi2_desc <- rev(cumsum(rev(hi2)))

# Intervalos
Intervalo2 <- paste0("[", round(Li2,2), " - ", round(Ls2,2), ")")

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

# Tabla 2
TDF_NOx_10 <- data.frame(
  Intervalo = Intervalo2,
  MC = round(MC2,2),
  ni = ni2,
  hi = round(hi2,2),
  Ni_ascendente = Ni2_asc,
  Ni_descendente = Ni2_desc,
  Hi_ascendente = round(Hi2_asc,2),
  Hi_descendente = round(Hi2_desc,2)
)

# Totales
totales2 <- data.frame(
  Intervalo = "Totales",
  MC = "-",
  ni = sum(ni2),
  hi = sum(hi2),
  Ni_ascendente = "-",
  Ni_descendente = "-",
  Hi_ascendente = "-",
  Hi_descendente = "-"
)

TDF_NOx_10_completa <- rbind(TDF_NOx_10, totales2)

# TABLA 2: Distribución de frecuencias de NOx con 10 intervalos

TDF_NOx_10_completa %>%
  gt() %>%
  tab_header(
    title = "Tabla Nro. 2",
    subtitle = "Distribución de frecuencia de concentración de Óxidos de Nitrógeno (NOx), 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. 2
Distribución de frecuencia de concentración de Óxidos de Nitrógeno (NOx), estudio calidad del aire en India entre 2015-2020
Intervalo MC ni hi Ni_ascendente Ni_descendente Hi_ascendente Hi_descendente
[0 - 46.76) 23.38 20268 79.97 20268 25346 79.97 100
[46.76 - 93.53) 70.14 3703 14.61 23971 5078 94.58 20.03
[93.53 - 140.29) 116.91 984 3.88 24955 1375 98.46 5.42
[140.29 - 187.05) 163.67 286 1.13 25241 391 99.59 1.54
[187.05 - 233.82) 210.43 76 0.30 25317 105 99.89 0.41
[233.82 - 280.58) 257.2 21 0.08 25338 29 99.97 0.11
[280.58 - 327.34) 303.96 4 0.02 25342 8 99.98 0.03
[327.34 - 374.1) 350.72 0 0.00 25342 4 99.98 0.02
[374.1 - 420.87) 397.49 3 0.01 25345 4 100 0.02
[420.87 - 467.63] 444.25 1 0.00 25346 1 100 0
Totales - 25346 100.00 - - - -
Grupo: 1
Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india

5.- Graficos de distribución de frecuencia

Histogramas de cantidad

#===========================
# Histograma de R studio
# Primero: Crea el objeto sin graficar
Histograma_NOx <- hist(NOx, breaks = 13, plot = FALSE)

# Segundo: Ahora sí, usa el objeto en el gráfico
hist(NOx, breaks = 13,
     main = "Grafica Nro.1 de distribución de frecuencias de concentración de NOx\nen el estudio calidad del aire en India de 2015-2020",
     xlab = "NOx (\u00B5g/m\u00B3)",
     ylab = "Cantidad",
     ylim = c(0, max(Histograma_NOx$counts)),
     col = "darkseagreen3", 
     cex.main = 0.9,
     cex.lab = 1,
     cex.axis = 0.9,
     xaxt = "n")
axis(1, at = Histograma_NOx$breaks,
     labels = round(Histograma_NOx$breaks, 0), las = 1,
     cex.axis = 0.9)
grid()

#================================
#Histograma con relación a la totalidad de los datos
# Crear objeto histograma
Histograma_NOx <- hist(NOx, breaks = 13, plot = FALSE)
par(mgp = c(3.2, 1, 0))
hist(NOx, breaks = 13,
     main = "Grafica Nro.2 de distribución de frecuencias de concentración de NOx\nen el estudio calidad del aire en India de 2015-2020",
     xlab = "NOx (µg/m³)",
     ylab = "Cantidad",
     ylim = c(0, 25300),
     col = "darkseagreen3",
     cex.main = 0.9,
     cex.lab = 1,
     cex.axis = 0.9,
     xaxt = "n",
     yaxt = "n")

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

# Eje Y
axis(2,
     at = seq(0, 25000, by = 5000),
     labels = seq(0, 25000, by = 5000),
     las = 1,
     cex.axis = 0.9)
grid()

Histogramas Porcentuales

# ================================
# Histograma que genera r studio porcentual
bp <- barplot(hi2,
              space = 0,
              names.arg = FALSE,
              xaxt = "n",
              main = "Grafica Nro.3 de distribución porcentual de NOx\nen el estudio calidad del aire en India de 2015-2020",
              xlab = "NOx (µg/m³)",
              ylab = "Porcentaje (%)",
              col = "darkseagreen3",
              border = "black",
              ylim = c(0, max(hi2) + 5),
              cex.main = 0.9,
              cex.lab = 1,
              cex.axis = 0.9)

# Obtener los bordes de las barras
bordes <- c(bp[1] - 0.5, bp + 0.5)
axis(1,
     at = bordes[c(1,3,5,7,9,11)],
     labels = seq(0, 500, by = 100),
     las = 1,
     tck = -0.03)
grid()

# Histograma con relación a la totalidad porcentualmente
bp <- barplot(hi2,
              space = 0,
              names.arg = FALSE,
              xaxt = "n",
              yaxt = "n",
              main = "Grafica Nro.4 de distribución porcentual de NOx\nen el estudio calidad del aire en India de 2015-2020",
              xlab = "NOx (µg/m³)",
              ylab = "Porcentaje (%)",
              col = "darkseagreen3",
              border = "black",
              ylim = c(0, 100),   # Hasta 100%
              cex.main = 0.9,
              cex.lab = 1,
              cex.axis = 0.9)

# Eje X
bordes <- c(bp[1] - 0.5, bp + 0.5)

axis(1,
     at = bordes[c(1,3,5,7,9,11)],
     labels = seq(0, 500, by = 100),
     las = 1,
     tck = -0.03)
# Eje Y
axis(2,
     at = seq(0, 100, by = 20),
     labels = paste0(seq(0, 100, by = 20)),
     las = 1)
grid()

Diagrama de caja y bigotes

#-----------------------------------------------------------
# Diagrama de caja y bigotes
boxplot(NOx,
        horizontal = TRUE,
        xaxt = "n",
        yaxt = "n",
        main = "Gráfica Nro.5: Diagrama de caja de la concentración de NOx\nen el estudio calidad del aire en India de 2015-2020",
        xlab = "NOx (µg/m³)",
        col = "turquoise3",
        border = "black",
        cex.main = 0.9,
        cex.lab = 1,
        cex.axis = 0.9)

# Eje X personalizado
axis(1,
     at = seq(0, 1000, by = 100),
     labels = seq(0, 1000, by = 100),
     las = 1)
grid()

Diagrama de Ojivas

# ==============================================================================
# OJIVA ASCENDENTE Y DESCENDENTE generada por R studio
plot(Ls2, Ni2_asc,
     type = "b",
     pch = 16,
     col = "turquoise3",
     lwd = 1,
     ylim = c(0, n),
     xlim = c(40, 400),
     xaxt = "n",
     xlab = "NOx",
     ylab = "Cantidad",
     main = "Gráfica N°6: Ojiva ascendente y descendente de la\nconcentración de Óxidos de Nitrógeno (NOx)",
     cex.main = 1)
# Eje X cada 200 unidades
axis(1, at = seq(0, 400, by = 100))

# Ojiva descendente
lines(Ls2, Ni2_desc,
      type = "b",
      pch = 16,
      col = "black",
      lwd = 1)
grid()
box()

# ==============================================================================
# OJIVA PORCENTUAL ASCENDENTE Y DESCENDENTE

plot(Ls2, Hi2_asc,
     type = "b",
     pch = 16,
     col = "turquoise3",
     lwd = 1,
     ylim = c(0, 100),
     xlim = c(40, 400),
     xaxt = "n",
     xlab = "NOx",
     ylab = "Porcentaje (%)",
     main = "Gráfica N°7: Ojiva porcentual ascendente y descendente de la\nconcentración de Óxidos de Nitrógeno (NOx)",
     cex.main = 1)

# Eje X cada 200 unidades
axis(1, at = seq(0, 400, by = 100))

# Ojiva porcentual descendente
lines(Ls2, Hi2_desc,
      type = "b",
      pch = 16,
      col = "black",
      lwd = 1)
grid()
box()

6.-Indicadores Estadísticos

# =========================================================
# Calculo previo de indicadores
X <- mean(NOx, na.rm = TRUE)       # Media
Me <- median(NOx, na.rm = TRUE)    # Mediana

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

desv <- sd(NOx, na.rm = TRUE)      # Desviacion estandar
CV <- (desv / X) * 100             # Coeficiente de variacion

# Libreria para Asimetria y Curtosis
library(e1071)

As <- skewness(NOx, na.rm = TRUE)
K <- kurtosis(NOx, na.rm = TRUE)

# Creacion del data frame
Tabla_indicadores <- data.frame(
  Variable = "NOx",
  Rango = paste0("[", round(min(NOx),2), " - ", round(max(NOx),2), "]"),
  Media = X,
  Mediana = Me,
  Moda = Mo,
  DesvEst = desv,
  CV = CV,
  Asimetria = As,
  Curtosis = K
)

# Visualizacion de la tabla
library(gt)
Tabla_indicadores %>%
  gt() %>%
  cols_label(
    Variable = "Variable",
    Rango = "Rango",
    Media = "Media (X)",
    Mediana = "Mediana (Me)",
    Moda = "Moda (Mo)",
    DesvEst = "Desv. Est. (sd)",
    CV = "CV (%)",
    Asimetria = "Asimetria (As)",
    Curtosis = "Curtosis (K)"
  ) %>%
  tab_header(
    title = "Tabla Nro. 3",
    subtitle = "Indicadores Estadisticos de la concentracion de NOx, estudio calidad del aire en India entre 2015-2020"
  ) %>%
  tab_source_note(
    source_note = "Autor: Grupo 1 | Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india"
  ) %>%
  tab_spanner(
    label = "Tendencia Central",
    columns = c(Media, Mediana, Moda)
  ) %>%
  tab_spanner(
    label = "Dispersion",
    columns = c(DesvEst, CV)
  ) %>%
  tab_spanner(
    label = "Forma",
    columns = c(Asimetria, Curtosis)
  ) %>%
  fmt_number(
    columns = c(Media, Mediana, DesvEst, CV, Asimetria, Curtosis),
    decimals = 2
  ) %>%
  tab_style(
    style = cell_borders(
      sides = c("left", "right", "top", "bottom"),
      color = "black",
      weight = px(1)
    ),
    locations = list(
      cells_body(columns = everything(), rows = everything()),
      cells_column_labels(columns = everything()),
      cells_column_spanners(spanners = everything())
    )
  ) %>%
  tab_options(
    table.border.top.color = "black",
    table.border.bottom.color = "black",
    table.border.left.color = "black",
    table.border.right.color = "black",
    table_body.hlines.color = "black",
    table_body.vlines.color = "black",
    column_labels.border.bottom.width = px(2)
  )
Tabla Nro. 3
Indicadores Estadisticos de la concentracion de NOx, 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) Curtosis (K)
NOx [0 - 467.63] 32.31 23.52 [0 - 46.76) 31.65 97.95 2.57 10.83
Autor: Grupo 1 | Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india

7.- Conclusión

En conclusión:

La variable Óxidos de Nitrógeno (NOx) fluctúa entre un mínimo de 0 y un máximo de 467.63 microgramos por metro cúbico (µg/m³), con una media de 32.31 y una desviación estándar de 31.65. Debido a un coeficiente de variación del 97.95%, se concluye que es un conjunto de valores heterogéneos con una alta dispersión. Los datos se acumulan de manera predominante en el primer intervalo [0 - 46.76). No obstante, se han detectado 1,868 valores atípicos, los cuales representan picos de contaminación que pueden afectar moderadamente al medio ambiente.”