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 = ".")
Turbidez <- datos$Turbidity_NTU

2. Extracción de la variable

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

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

3. Tabla de distribución de frecuencia

3.1 Construcción manual (Regla de Sturges)

# 1. Asegurar que Nitrito sea un vector limpio y numérico
Turbidez <- as.numeric(na.omit(datos$Turbidity_NTU))
Turbidez <- Turbidez[Turbidez >= 0]
n_total <- length(Turbidez) # Esto debe ser 3000

# 2. Definir parámetros
minimo <- min(Turbidez)
maximo <- max(Turbidez)
K <- floor(1 + 3.322 * log10(n_total))

# 3. EL TRUCO DEFINITIVO PARA LOS 3000:
# Creamos los cortes pero expandimos los extremos 
# para que el mínimo y el máximo REALES queden adentro del rango.
rango_ajustado <- seq(from = minimo - 0.001, to = maximo + 0.001, length.out = K + 1)

# 4. Generar la tabla de frecuencias
# 'include.lowest = TRUE' es vital para que el primer dato entre
intervalos <- cut(Turbidez, breaks = rango_ajustado, include.lowest = TRUE, right = TRUE)
tabla_base <- table(intervalos)
ni <- as.numeric(tabla_base)

# 5. Verificación de seguridad (Si falta algo, se suma a la última clase)
if(sum(ni) != n_total){
  diferencia <- n_total - sum(ni)
  ni[length(ni)] <- ni[length(ni)] + diferencia
}

# 6. Construcción de la tabla final
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_Turbidez <- data.frame(
  Lim_inf = Li,
  Lim_sup = Ls,
  MC = Mc,
  ni = ni,
  hi = hi,
  Ni_asc = Ni_asc,
  Hi_asc = Hi_asc
)

# 7. Mostrar con kable
library(knitr)
library(kableExtra)

kable(TDF_Turbidez, 
      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. (%)
-0.001 3.956 1.977 1653 55.100 1653 55.100
3.956 7.913 5.934 734 24.467 2387 79.567
7.913 11.869 9.891 333 11.100 2720 90.667
11.869 15.826 13.848 155 5.167 2875 95.833
15.826 19.783 17.805 78 2.600 2953 98.433
19.783 23.740 21.762 28 0.933 2981 99.367
23.740 27.697 25.718 9 0.300 2990 99.667
27.697 31.654 29.675 6 0.200 2996 99.867
31.654 35.610 33.632 2 0.067 2998 99.933
35.610 39.567 37.589 0 0.000 2998 99.933
39.567 43.524 41.546 1 0.033 2999 99.967
43.524 47.481 45.503 1 0.033 3000 100.000

3.2. Simplificación

La tabla de distribución de frecuencia de la Turbidez 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.

Hist_Turbidez <- hist(Turbidez,
                     breaks = K,
                     plot = FALSE)

Li <- Hist_Turbidez$breaks[-length(Hist_Turbidez$breaks)]
Ls <- Hist_Turbidez$breaks[-1]
ni <- Hist_Turbidez$counts
hi <- round((ni/sum(ni))*100,2)

TDF_simplificada <- data.frame(
  Lim_inf = round(Li,2),
  Lim_sup = round(Ls,2),
  ni = ni,
  hi = hi
)

kable(TDF_simplificada,
      align="c",
      caption="Tabla simplificada obtenida mediante hist()")
Tabla simplificada obtenida mediante hist()
Lim_inf Lim_sup ni hi
0 5 1911 63.70
5 10 678 22.60
10 15 272 9.07
15 20 94 3.13
20 25 32 1.07
25 30 6 0.20
30 35 4 0.13
35 40 1 0.03
40 45 1 0.03
45 50 1 0.03

4. Gráficas

4.1 Histograma

hist(Turbidez, breaks = 10,
     main = "Gráfica N°1: Distribución de la Turbidez
     en el estudio de contaminación del agua
     en China en el año 2023",
     xlab = "Turbidez (NTU)",
     ylab = "Cantidad",
     ylim = c(0, max(ni)),
     col = "lightgreen")

4.2 Histograma general

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

4.3 Histograma Porcentual General

barplot(
  height = TDF_Turbidez$hi, 
  space = 0,
  col = "skyblue",
  main = "Gráfica N°3: Distribución porcentual de la Turbidez\nen el estudio de contaminación del agua en China 2023",
  xlab = "Turbidez (NTU)",
  ylab = "Porcentaje (%)",
  names.arg = TDF_Turbidez$MC,
  ylim = c(0, max(TDF_Turbidez$hi) + 10) # Ajuste automático del eje Y
)

5. Diagrama de Caja

boxplot(Turbidez,
        horizontal = TRUE,
        main = "Gráfica N°6: Diagrama de caja de la Turbidez
        en el estudio de contaminación del agua en China 2023",
        xlab = "Turbidez (NTU)",
        col = "green",
        outline = TRUE)

summary(Turbidez)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   0.000   1.430   3.445   4.948   6.933  47.480

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 = "Turbidez (NTU)",
     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 = "Turbidez (NTU)",
     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(Turbidez),2)
mediana <- median(Turbidez)

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

media
## [1] 4.95
mediana
## [1] 3.445
moda
## [1] 1.977417

7.2 Indicadores de Dispersión

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

varianza
## [1] 24.11285
sd
## [1] 4.910484
cv
## [1] 99.2

7.3 Indicadores de Forma

library(e1071)

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

asimetria
## [1] 1.959997
curtosis
## [1] 6.067872

8. Tabla de Resumen

tabla_indicadores <- data.frame(
  "Variable" = "Turbidez (NTU)",
  "Rango" = paste0("[",min(Turbidez),";",max(Turbidez),"]"),
  "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 Turbidez (NTU)")
Conclusiones de la variable Turbidez (NTU)
Variable Rango X Me Mo V Sd Cv As K
Turbidez (NTU) [0;47.48] 4.95 3.45 1.977417 24.11 4.91 99.2 1.96 6.07

9. Conclusión

La variable Turbidez (NTU) fluctúa entre 0 y 47.48 NTU, y sus valores giran en torno a 4.95 NTU, con una desviación estándar de 4.91 NTU, siendo un conjunto de datos con variabilidad alta (CV = 99.2%). Los valores se distribuyen de manera asimétrica hacia valores mayores (As ≈ 1.96), indicando que hay presencia de mediciones relativamente elevadas en comparación con la media, y presentan una curtosis muy positiva (K = 6.07), evidenciando una distribución con colas pesadas y valores extremos significativos. Por lo anterior, el comportamiento de la variable Turbidez (NTU) refleja una alta dispersión de los datos, con algunos valores extremos, lo que debe considerarse en el análisis de la calidad del agua en China durante el año 2023.