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 = ".")
Latitud <- datos$Latitude

2. Extracción de la variable

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

n <- length(Latitud)
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
Latitud <- as.numeric(na.omit(datos$Latitude))
Latitud <- Latitud[Latitud >= 0]
n_total <- length(Latitud) # Esto debe ser 3000

# 2. Definir parámetros
minimo <- min(Latitud)
maximo <- max(Latitud)
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(Latitud, 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_Latitud <- 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_Latitud, 
      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. (%)
20.013 22.095 21.054 261 8.700 261 8.700
22.095 24.177 23.136 261 8.700 522 17.400
24.177 26.259 25.218 263 8.767 785 26.167
26.259 28.341 27.300 244 8.133 1029 34.300
28.341 30.423 29.382 273 9.100 1302 43.400
30.423 32.505 31.464 223 7.433 1525 50.833
32.505 34.587 33.546 240 8.000 1765 58.833
34.587 36.669 35.628 291 9.700 2056 68.533
36.669 38.751 37.710 226 7.533 2282 76.067
38.751 40.832 39.791 247 8.233 2529 84.300
40.832 42.914 41.873 220 7.333 2749 91.633
42.914 44.996 43.955 251 8.367 3000 100.000

3.2. Simplificación

La tabla de distribución de frecuencia de la Latitud 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_Latitud <- hist(Latitud,
                     breaks = K,
                     plot = FALSE)

Li <- Hist_Latitud$breaks[-length(Hist_Latitud$breaks)]
Ls <- Hist_Latitud$breaks[-1]
ni <- Hist_Latitud$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
20 22 251 8.37
22 24 250 8.33
24 26 250 8.33
26 28 245 8.17
28 30 249 8.30
30 32 215 7.17
32 34 237 7.90
34 36 264 8.80
36 38 240 8.00
38 40 227 7.57
40 42 231 7.70
42 44 209 6.97
44 46 132 4.40

4. Gráficas

4.1 Histograma

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

4.2 Histograma general

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

4.3 Histograma Porcentual General

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

5. Diagrama de Caja

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

summary(Latitud)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   20.01   25.99   32.29   32.30   38.53   45.00

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

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

media
## [1] 32.3
mediana
## [1] 32.29107
moda
## [1] 35.62767

7.2 Indicadores de Dispersión

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

varianza
## [1] 52.16067
sd
## [1] 7.222235
cv
## [1] 22.36

7.3 Indicadores de Forma

library(e1071)

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

asimetria
## [1] 0.03670426
curtosis
## [1] -1.196096

8. Tabla de Resumen

tabla_indicadores <- data.frame(
  "Variable" = "Latitud (°)",
  "Rango" = paste0("[",min(Latitud),";",max(Latitud),"]"),
  "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 Latitud (°)")
Conclusiones de la variable Latitud (°)
Variable Rango X Me Mo V Sd Cv As K
Latitud (°) [20.014474;44.995192] 32.3 32.29 35.62767 52.16 7.22 22.36 0.04 -1.2

9. Conclusión

La variable Latitud (°) fluctúa entre 20.01 y 44.99 °, y sus valores giran en torno a 32.3 °, con una desviación estándar de 7.22 °, siendo un conjunto de datos con variabilidad moderada (CV = 22.36%). Los valores se distribuyen de manera prácticamente simétrica (As ≈ 0.04), indicando que no existe una concentración marcada hacia latitudes bajas o altas, y presentan una curtosis negativa (K = -1.2), evidenciando una distribución más plana que la normal. Por lo anterior, el comportamiento de la variable Latitud (°) puede considerarse estable y representativo para el análisis geográfico de la calidad del agua en China durante el año 2023.