#Estadística descriptiva 
#Variable cuantitativa continua: Amoniaco
#Autor: Llumitasig Daniela 
#Fecha: 30/05/2026

0. Cargar librerias

library(gt)
library(dplyr)
## 
## 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

1. Carga de datos

datos<-read.csv("~/Documentos R/TABLAS A/city_day (2).csv")

2. Selección de la variable

anomiaco<-datos$NH3

#Extraccion de los "-" de la variable Benzene debido a que son valores inexistentes, 
# para un mejor analisis, cambia tamaño muestral de 29531 a 19203   

datos$NH3[datos$NH3 == "-"] <- NA

datos$NH3 <- as.numeric(datos$NH3)

amoniaco <- na.omit(datos$NH3)

#Filtrar NH3
amoniaco <- subset(datos$NH3, datos$NH3 >= 0)

 length(amoniaco)
## [1] 19203

3. Frecuencia

# Calcular el mínimo y máximo de NH3
min_amoniaco <- min(amoniaco)
max_amoniaco <- max(amoniaco)

min_amoniaco
## [1] 0.01
max_amoniaco
## [1] 352.89
#Calcular rango 
R <- max_amoniaco - min_amoniaco

#Calcular intervalos 
K <- floor(1 + 3.33 * log10(length(amoniaco)))
K
## [1] 15
#Calcular amplitud 
A <-R/K

#Limite inferior 
Li <- round(seq(from = min_amoniaco,
                to = max_amoniaco - A,
                by = A), 2)
#Limite superior
Ls <- round(Li + A, 2)
#Marca de clase 
Mc <- (Li+Ls)/2
Mc
##  [1]  11.775  35.305  58.825  82.355 105.875 129.405 152.925 176.455 199.975
## [10] 223.505 247.025 270.555 294.075 317.605 341.125
# Vector vacío para guardar las frecuencias de cada clase
ni <- c()

for (i in 1:K) {
  if (i < K) {
    # Para las primeras clases: [Li , Ls)
    ni[i] <- length(subset(amoniaco, amoniaco >= Li[i] & amoniaco < Ls[i]))
  } else {
    # Para la última clase: [Li , Ls]
    ni[i] <- length(subset(amoniaco, amoniaco >= Li[i] & amoniaco <= Ls[i]))
  }
}

N <- sum(ni)
hi <- (ni / N) * 100
Ni_asc <- cumsum(ni)
Ni_desc <- rev(cumsum(rev(ni)))
Hi_asc <- cumsum(hi)
Hi_desc <- rev(cumsum(rev(hi)))
Intervalo <- paste0("[", round(Li,2), " - ", round(Ls,2), ")")
Intervalo[length(Intervalo)] <- paste0("[", round(Li[length(Li)],2), " - ", 
                                       round(Ls[length(Ls)],2), "]")
 
TDF_amoniaco <- data.frame(
  Intervalo = Intervalo,
  Mc = round(Mc, 2),
  ni = ni,
  hi = round(hi, 2),
  Ni_asc = Ni_asc,
  Ni_desc = Ni_desc,
  Hi_asc = round(Hi_asc, 2),
  Hi_desc = round(Hi_desc, 2)
)
# Crear fila de totales para amoniaco
totales <- data.frame(
  Intervalo = "Totales",
  Mc = "-",
  ni = sum(ni),
  hi = round(sum(hi), 2),
  Ni_asc = "-",
  Ni_desc = "-",
  Hi_asc= "-",
  Hi_desc = "-"
)

TDF_amoniaco <- rbind(TDF_amoniaco, totales)

4. Tablas de distribución de frecuencias

4.1. Tabla general

# Tabla 1

TDF_amoniaco %>%
  gt() %>%
  tab_header(
    title = md("*Tabla Nro. 1*"),
    subtitle = md("*Distribución de frecuencias de la concentración de amoniaco en el estudio de calidad del aire en la India*")
  ) %>%
  tab_source_note(
    source_note = md("Autor: Grupo 1
                     \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
Distribución de frecuencias de la concentración de amoniaco en el estudio de calidad del aire en la India
Intervalo Mc ni hi Ni_asc Ni_desc Hi_asc Hi_desc
[0.01 - 23.54) 11.78 12403 64.59 12403 19203 64.59 100
[23.54 - 47.07) 35.3 4775 24.87 17178 6800 89.45 35.41
[47.06 - 70.59) 58.83 1306 6.80 18484 2025 96.26 10.55
[70.59 - 94.12) 82.36 305 1.59 18789 719 97.84 3.74
[94.11 - 117.64) 105.88 176 0.92 18965 414 98.76 2.16
[117.64 - 141.17) 129.4 85 0.44 19050 238 99.2 1.24
[141.16 - 164.69) 152.93 43 0.22 19093 153 99.43 0.8
[164.69 - 188.22) 176.45 43 0.22 19136 110 99.65 0.57
[188.21 - 211.74) 199.98 22 0.11 19158 67 99.77 0.35
[211.74 - 235.27) 223.5 10 0.05 19168 45 99.82 0.23
[235.26 - 258.79) 247.02 11 0.06 19179 35 99.88 0.18
[258.79 - 282.32) 270.56 5 0.03 19184 24 99.9 0.12
[282.31 - 305.84) 294.08 15 0.08 19199 19 99.98 0.1
[305.84 - 329.37) 317.6 3 0.02 19202 4 99.99 0.02
[329.36 - 352.89] 341.12 1 0.01 19203 1 100 0.01
Totales - 19203 100.00 - - - -
Autor: Grupo 1

Fuente:https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india

4.2 Tabla simplificada

# PROCESO DE SIMPLIFICACIÓN PARA NH3 (10 intervalos)


# 1. Mínimo y máximo
min_nh3 <- floor(min(amoniaco, na.rm = TRUE))
max_nh3 <- ceiling(max(amoniaco, na.rm = TRUE))

# 2. Amplitud para 10 intervalos
A_ajustada <- ceiling((max_nh3 - min_nh3) / 10)

# 3. Definir breaks (11 puntos = 10 intervalos)
mis_breaks <- seq(
  from = min_nh3,
  by = A_ajustada,
  length.out = 11
)

# 4. Histograma con los nuevos breaks
histo_amoniaco <- hist(
  amoniaco,
  breaks = mis_breaks,
  plot = FALSE
)

# 5. Límites de clase
Lis <- histo_amoniaco$breaks[1:(length(histo_amoniaco$breaks)-1)]
Lss <- histo_amoniaco$breaks[2:length(histo_amoniaco$breaks)]

# 6. Marca de clase
MCs <- (Lis + Lss) / 2

# 7. Frecuencias
nis <- histo_amoniaco$counts
his <- (nis / sum(nis)) * 100

# 8. Frecuencias acumuladas
Nis_asc <- cumsum(nis)
His_asc <- cumsum(his)

Nis_desc <- rev(cumsum(rev(nis)))
His_desc <- rev(cumsum(rev(his)))

# 9. Intervalos como texto
Intervalos <- paste0(
  "[", round(Lis, 2),
  " - ",
  round(Lss, 2),
  ")"
)

# Último intervalo cerrado
Intervalos[length(Intervalos)] <- paste0(
  "[",
  round(Lis[length(Lis)], 2),
  " - ",
  round(Lss[length(Lss)], 2),
  "]"
)

# 10. Crear tabla simplificada
TDF_amoniacosimplificado <- data.frame(
  Intervalo = Intervalos,
  MC = round(MCs, 2),
  ni = nis,
  hi = round(his, 2),
  Ni_asc = Nis_asc,
  Hi_asc = round(His_asc, 2),
  Ni_desc = Nis_desc,
  Hi_desc = round(His_desc, 2)
)

# 11. Fila de totales
totaless <- data.frame(
  Intervalo = "Totales",
  MC = "-",
  ni = sum(nis),
  hi = round(sum(his), 2),
  Ni_asc = "-",
  Hi_asc = "-",
  Ni_desc = "-",
  Hi_desc = "-"
)

# 12. Agregar totales
TDF_amoniacosimplificado <- rbind(
  TDF_amoniacosimplificado,
  totaless
)

# TABLA 2

TDF_amoniacosimplificado %>%
  gt() %>%
  tab_header(
    title = md("*Tabla Nro. 2*"),
    subtitle = md("*Distribución de frecuencia simplificada de concentración de amoniaco en el estudio de calidad del aire en la India*")
  ) %>%
  tab_source_note(
    source_note = md("Autor: Grupo 1
                     \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"
  )
Tabla Nro. 2
Distribución de frecuencia simplificada de concentración de amoniaco en el estudio de calidad del aire en la India
Intervalo MC ni hi Ni_asc Hi_asc Ni_desc Hi_desc
[0 - 36) 18 15608 81.28 15608 81.28 19203 100
[36 - 72) 54 2896 15.08 18504 96.36 3595 18.72
[72 - 108) 90 412 2.15 18916 98.51 699 3.64
[108 - 144) 126 143 0.74 19059 99.25 287 1.49
[144 - 180) 162 63 0.33 19122 99.58 144 0.75
[180 - 216) 198 38 0.20 19160 99.78 81 0.42
[216 - 252) 234 18 0.09 19178 99.87 43 0.22
[252 - 288) 270 11 0.06 19189 99.93 25 0.13
[288 - 324) 306 12 0.06 19201 99.99 14 0.07
[324 - 360] 342 2 0.01 19203 100 2 0.01
Totales - 19203 100.00 - - - -
Autor: Grupo 1

Fuente: https://www.kaggle.com/datasets/rohanrao/air-quality-data-in-india

5. Gráficas de distribución de frecuencias

5.1. Polígono de frecuecnia

# Histograma de Ozono con poligono de frecuencia 
hist(amoniaco,
     breaks = mis_breaks,
     main = "Gráfica Nro. 1\nHistograma con el polígono de frecuencias de Amoniaco\n en el estudio de la calidad del aire en la India (2015-2020)",
     xlab = "Amoniaco (µg/m³)",
     ylab = "Cantidad",
     col = "#D8BFD8",
     xaxt = "n",
     cex.main = 0.9,
     ylim = c(0, max(histo_amoniaco$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(amoniaco,breaks = mis_breaks,col = "#D8BFD8",add = TRUE)
# Polígono de frecuencias
lines(MCs, nis,
      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)

5.2. Histogramas de cantidad

#Histograma generado por RStudio 


# 1. Creamos el histograma y guardamos la información
histo_amoniaco <- hist(
  amoniaco,
  breaks = mis_breaks,
  plot = FALSE
)

# 2. Creamos el marco del gráfico

hist(
  amoniaco,
  breaks = mis_breaks,
  main = "Gráfica Nro. 2\nDistribución de la concentración de Amoniaco
     presente en el estudio de la calidad del aire en la India (2015-2020)",
  xlab = "Amoniaco (µg/m³)",
  ylab = "Cantidad",
  col = "#D8BFD8",
  ylim = c(0, max(histo_amoniaco$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(
  amoniaco,
  breaks = mis_breaks,
  col = "#D8BFD8",
  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 Amoniaco

hist(
  amoniaco,
  breaks = mis_breaks,
  main = "Gráfica Nro. 3\nDistribución de la concentración de Amoniaco
     presente en el estudio de la calidad del aire en la India (2015-2020)",
  xlab = "Amoniaco (µg/m³)",
  ylab = "Cantidad",
  col = "#D8BFD8",
  ylim = c(0, length(amoniaco)),  # Eje Y hasta el tamaño muestral
  xaxt = "n",
  cex.main = 0.9
)

# Líneas de cuadrícula verticales
abline(
  v = mis_breaks,
  col = "gray70",
  lty = 2,
  lwd = 0.8
)

# Líneas de cuadrícula horizontales
abline(
  h = axTicks(2),
  col = "gray70",
  lty = 2,
  lwd = 0.8
)

# Redibujar histograma encima de la cuadrícula
hist(
  amoniaco,
  breaks = mis_breaks,
  col = "#D8BFD8",
  add = TRUE
)

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

5.2 Histogramas porcentuales

# Histograma que genera RStudio porcentual

plot(histo_amoniaco,
     freq = FALSE,
     main = "Gráfica Nro. 4\nDistribución porcentual de concentración de Amoniaco
     presente en el estudio de la calidad del aire en la India (2015-2020)",
     xlab = "Amoniaco (µg/m³)",
     ylab = "Porcentaje ",
     xaxt = "n",
     cex.main = 1,
     ylim = c(0, max(his) * 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_amoniaco$breaks[-length(histo_amoniaco$breaks)],
     0,
     histo_amoniaco$breaks[-1],
     his, 
     col = "#D8BFD8",
     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_amoniaco,
     freq = FALSE,
     main = "Gráfica Nro. 5\nDistribución porcentual de concentración de Amoniaco
     presente en el estudio de la calidad del aire en la India (2015-2020)",
     xlab = "Amoniaco (µ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_amoniaco$breaks[-length(histo_amoniaco$breaks)],
     0,
     histo_amoniaco$breaks[-1],
     his, 
     col = "#D8BFD8",
     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 bigote

# Diagrama de caja del Amoniaco 

boxplot(amoniaco,
        horizontal = TRUE,
        main = "Gráfica Nro. 6\nDistribución de la concentración de Amoniaco
        en el estudio de la calidad del aire en la India (2015-2020)",
        xlab = "Ozono (µg/m³)",
        col = "#D8BFD8",
        border = "black",
        cex.main = 0.9)

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

7. Diagrama de ojivas

7.1 Ojivas ascendente y descendente (Ni)

# Ojivas ascendente y descendente

plot(Lss, Nis_asc,
     type = "o",
     pch = 16,
     col = "peachpuff", 
     lwd = 2,
     main = "Gráfica Nro. 7\nDistribución de frecuencia ascendete y descendente
     de la concentración de amoniaco",
     xlab = "Amoniaco (µg/m³)",
     ylab = "Frecuencia",
     ylim = c(0, max(Nis_asc)),
     xaxt = "n",
     cex.main = 0.9)

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

# Ojiva descendente
lines(Lss, Nis_desc,
      type = "o",
      pch = 16,
      col = "lightblue",
      lwd = 2)

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

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

7.2 Ojiva porcentual

## Ojiva porcentuales

# Ojivas porcentuales ascendente y descendente

plot(Lss, His_asc,
     type = "o",
     pch = 16,
     col = "peachpuff",
     lwd = 2,
     main = "Gráfica Nro. 8\nDistribución de frecuencia ascendete y descendente
     de la concentración de amoniaco",
     xlab = "Amoniaco (µg/m³)",
     ylab = "Porcentaje",
     ylim = c(0, 100),
     xaxt = "n",
     cex.main = 0.9)

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

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

# Ojiva descendente
lines(Lss, His_desc,
      type = "o",
      pch = 16,
      col = "lightblue",
      lwd = 2)

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

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

8. Indicadores estadísticos

library(e1071)
## Warning: package 'e1071' was built under R version 4.5.3
#Indicadores de posición

#Media aritmetica 

X <- sum(amoniaco) / length(amoniaco)
X
## [1] 23.48348
#Mediana

Me <- median(amoniaco)
Me
## [1] 15.85
# Moda

Mo <- "[0,36]"
Mo
## [1] "[0,36]"
#Porque la tabla simplificada, la clase número 1 en el intervalo [0,36] tiene la frecuencia más alta.
#La mayor frecuencia es 15608, que está en la posición 1 del vector

# Indicadores de dispersión

# Varianza

var<- var(amoniaco)
var
## [1] 659.682
# Desviación estandar 
sd <- sd(amoniaco)
sd
## [1] 25.68427
# Coeficiente de variación (%)

CV <- (sd / X) * 100
CV
## [1] 109.3717
# Indicadores de forma 

# Coeficiente de asimetria

install.packages("e1071")
## Warning: package 'e1071' is in use and will not be installed
library(e1071)

As <- skewness(amoniaco)
As
## [1] 4.083355
# Curtosis 
library(e1071)

Cu <- kurtosis(amoniaco)
Cu
## [1] 27.95379
# Outliers

cajaBigotes <- boxplot(amoniaco, plot = FALSE)

outliers <- cajaBigotes$out
min(outliers)
## [1] 62.2
max(outliers)
## [1] 352.89
length(outliers)
## [1] 1015
Variable<-"amoniaco"

Rango<-Rango <- "[0.01, 352.89]"


VA <- paste0(
  length(outliers),
  " (",
  round(min(outliers), 2),
  " – ",
  round(max(outliers), 2),
  ")"
)

tabla_indicadores <- data.frame(
  Variable = c("Amoniaco"),
  Rango = paste0("[", min(amoniaco), "; ", max(amoniaco), "]"),
  X = X,
  Me = round(Me, 2),
  Mo = Mo,
  V = round(var, 2),
  Sd = round(sd, 2),
  CV = CV,
  As = round(As, 2),
  K = round(K, 2),
  "Valores Atípicos" = "1015 [62.2 ; 352.89]"
)

library(knitr)

kable(
  tabla_indicadores,
  align = "c",
  caption = "Conclusiones de la variable Amoniaco"
)
Conclusiones de la variable Amoniaco
Variable Rango X Me Mo V Sd CV As K Valores.Atípicos
Amoniaco [0.01; 352.89] 23.48348 15.85 [0,36] 659.68 25.68 109.3717 4.08 15 1015 [62.2 ; 352.89]

9. Conclusiones

En conclusión:

La variable Amoniaco dada en (µg/ m3) fluctúa entre 0,01 y 582,89 (µg/m3), y sus valores giran entorno a 15.85 con una desviación estándar de 25,68 (µg/m3) siendo un conjunto de valores muy heterogéneos. Los valores se acumulan de manera fuerte en la parte media a alta de la variable, dejando ver un sesgo positivo Con la presencia de 1015 valores atípicos en el intervalo de 62.2 a 352.89 (µg/m3). Por todo lo anterior el compotamiento de la variable es medianamente buena para el ambiente, sin embrgo la presencia de valores atípicos muy marcados representan un riesgo.