1.Carga de datos

# Librerías
library(kableExtra)
library(knitr)
library(magrittr)
library(dplyr)
## 
## Adjuntando el paquete: 'dplyr'
## The following object is masked from 'package:kableExtra':
## 
##     group_rows
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(e1071)

# Cargar datos
datos <- read.csv("china_water_pollution_data.csv",
                  header = TRUE,
                  sep = ",",
                  dec = ".")
COD <- datos$COD_mg_L

2. Extracción de la variable

COD <- na.omit(COD)
COD <- COD[COD >= 0]

n <- length(COD)
n
## [1] 3000

3. Tabla de distribución de frecuencia

3.1 Construcción manual (Regla de Sturges)

minimo <- min(COD)
maximo <- max(COD)
K <- floor(1 + 3.322 * log10(n))

# Creamos el rango y lo guardamos bien
rango_ajustado <- seq(from = minimo - 0.01, to = maximo + 0.01, length.out = K + 1)

intervalos <- cut(COD, breaks = rango_ajustado, include.lowest = TRUE, right = TRUE)
ni <- as.numeric(table(intervalos))

# Parche para asegurar los 3000
if(sum(ni) != n){
  ni[which.max(ni)] <- ni[which.max(ni)] + (n - sum(ni))
}

Li <- rango_ajustado[-length(rango_ajustado)]
Ls <- rango_ajustado[-1]
Mc <- (Li + Ls)/2
hi <- (ni / sum(ni)) * 100
Ni_asc <- cumsum(ni)
Hi_asc <- cumsum(hi)

TDF_COD <- data.frame(
  Lim_inf = Li,
  Lim_sup = Ls,
  MC = Mc,
  ni = ni,
  hi = hi,
  Ni_asc = Ni_asc,
  Hi_asc = Hi_asc
)

kable(TDF_COD, digits = 3, align = "c",
      col.names = c("Lím. Inf.", "Lím. Sup.", "MC", "ni", "hi (%)", "Ni Asc.", "Hi Asc. (%)"),
      caption = paste("TABLA FINAL - TOTAL DATOS:", sum(ni))) %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover"))
TABLA FINAL - TOTAL DATOS: 3000
Lím. Inf. Lím. Sup. MC ni hi (%) Ni Asc. Hi Asc. (%)
2.080 5.056 3.568 4 0.133 4 0.133
5.056 8.032 6.544 22 0.733 26 0.867
8.032 11.008 9.520 73 2.433 99 3.300
11.008 13.983 12.495 239 7.967 338 11.267
13.983 16.959 15.471 476 15.867 814 27.133
16.959 19.935 18.447 683 22.767 1497 49.900
19.935 22.911 21.423 675 22.500 2172 72.400
22.911 25.887 24.399 470 15.667 2642 88.067
25.887 28.863 27.375 241 8.033 2883 96.100
28.863 31.838 30.350 88 2.933 2971 99.033
31.838 34.814 33.326 24 0.800 2995 99.833
34.814 37.790 36.302 5 0.167 3000 100.000

3.2. Simplificación

La tabla de distribución de frecuencia del Carbono Orgánico Disuelto fue construida inicialmente aplicando la Regla de Sturges para determinar el número óptimo de clases.

Posteriormente, el procedimiento se simplificó utilizando la función hist(), obteniendo automáticamente los intervalos y frecuencias, confirmando los resultados obtenidos manualmente.

# Usamos el objeto ni del bloque anterior para que coincida perfectamente
Hist_COD <- hist(COD, breaks = rango_ajustado, plot = FALSE)

TDF_simplificada <- data.frame(
  Lim_inf = round(Hist_COD$breaks[-length(Hist_COD$breaks)], 2),
  Lim_sup = round(Hist_COD$breaks[-1], 2),
  ni = ni, 
  hi = round((ni/sum(ni))*100, 2)
)

kable(TDF_simplificada, align="c", 
      caption="Tabla simplificada obtenida mediante hist()") %>%
  kable_styling(full_width = FALSE)
Tabla simplificada obtenida mediante hist()
Lim_inf Lim_sup ni hi
2.08 5.06 4 0.13
5.06 8.03 22 0.73
8.03 11.01 73 2.43
11.01 13.98 239 7.97
13.98 16.96 476 15.87
16.96 19.94 683 22.77
19.94 22.91 675 22.50
22.91 25.89 470 15.67
25.89 28.86 241 8.03
28.86 31.84 88 2.93
31.84 34.81 24 0.80
34.81 37.79 5 0.17

4. Gráficas

4.1 Histograma

hist(COD, breaks = rango_ajustado,
     main = "Gráfica N°1: Distribución de la COD",
     xlab = "COD (mg/L)", ylab = "Cantidad",
     col = "lightgreen")

4.2 Histograma general

hist(COD, breaks = 10,
     main = "Gráfica N°2: Distribución general de la COD
     en el estudio de contaminación del agua en China 2023",
     xlab = "COD (mg/L)",
     ylab = "Cantidad",
     ylim = c(0, max(ni)),
     col = "lightgreen")

4.3 Histograma Porcentual General

barplot(height = TDF_COD$hi, space = 0, col = "skyblue",
  main = "Gráfica N°3: Distribución porcentual de la COD",
  xlab = "COD (mg/L)", ylab = "Porcentaje (%)",
  names.arg = round(TDF_COD$MC, 2))

5. Diagrama de Caja

boxplot(COD, horizontal = TRUE, col = "green",
        main = "Gráfica N°6: Diagrama de caja de la COD",
        xlab = "COD (mg/L)")

6. Ojivas

6.1 Ojivas Ascendentes y Descendentes (ni)

Ni_asc <- cumsum(ni)
Ni_desc <- rev(cumsum(rev(ni)))

plot(Ls, Ni_asc,
     type = "o",
     col = "orange",
     lwd = 3,
     xlab = "COD (mg/L)",
     ylab = "Frecuencia acumulada",
     main = "Gráfica N°7: Ojiva Ascendente y Descendente")

lines(Li, Ni_desc,
      type = "o",
      col = "green",
      lwd = 3)

6.2 Ojivas Ascendentes y Descendentes (hi)

Hi_asc <- cumsum(hi)
Hi_desc <- rev(cumsum(rev(hi)))

plot(Ls, Hi_asc,
     type = "o",
     col = "blue",
     lwd = 3,
     xlab = "COD (mg/L)",
     ylab = "Porcentaje acumulado (%)",
     main = "Gráfica N°8: Ojiva porcentual Ascendente y Descendente")

lines(Li, Hi_desc,
      type = "o",
      col = "red",
      lwd = 3)

7. Indicadores Estadísticos

7.1 Indicadores de Tendencia Central

media <- round(mean(COD),2)
mediana <- median(COD)

max_ni <- max(TDF_COD$ni)
moda <- TDF_COD$MC[TDF_COD$ni == max_ni]

media
## [1] 19.99
mediana
## [1] 19.94
moda
## [1] 18.44708

7.2 Indicadores de Dispersión

varianza <- var(COD)
sd <- sd(COD)
cv <- round((sd/media)*100,2)

varianza
## [1] 25.08409
sd
## [1] 5.008402
cv
## [1] 25.05

7.3 Indicadores de Forma

library(e1071)

asimetria <- skewness(COD, type = 2)
curtosis <- kurtosis(COD)

asimetria
## [1] 0.02124703
curtosis
## [1] -0.03511734

8. Tabla de Resumen

tabla_indicadores <- data.frame(
  "Variable" = "COD (mg/L)",
  "Rango" = paste0("[",min(COD),";",max(COD),"]"),
  "X" = media,
  "Me" = round(mediana,2),
  "Mo" = moda,
  "V" = round(varianza,2),
  "Sd" = round(sd,2),
  "Cv" = cv,
  "As" = round(asimetria,2),
  "K" = round(curtosis,2)
)

kable(tabla_indicadores, align='c',
      caption="Conclusiones de la variable COD (mg/L)")
Conclusiones de la variable COD (mg/L)
Variable Rango X Me Mo V Sd Cv As K
COD (mg/L) [2.09;37.78] 19.99 19.94 18.44708 25.08 5.01 25.05 0.02 -0.04

9. Conclusión

La variable COD (mg/L) fluctúa entre 2.09 y 37.78 mg/L, y sus valores giran en torno a 19.99 mg/L, con una desviación estándar de 5.01 mg/L, siendo un conjunto de datos con variabilidad moderada (CV = 25.05%). Los valores se distribuyen de manera prácticamente simétrica (As ≈ 0.02), indicando que no existe una concentración marcada hacia valores bajos o altos, y presentan una curtosis cercana a cero (K = -0.04), evidenciando una distribución muy similar a la normal. Por lo anterior, el comportamiento de la variable COD (mg/L) puede considerarse estable y representativo para el análisis de la calidad del agua en China durante el año 2023.