1. Librerías

# -------------------------
# Cargar librerías
# -------------------------
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

2.Leer datos

# -------------------------
# Cargar datos
# -------------------------

datos <- read.csv("waterPollution.csv",
                  sep = ",",
                  stringsAsFactors = FALSE)

3. Selección y separación de la variable

# ================================
# SELECCIÓN Y SEPARACIÓN
# ================================

datos$resultMeanValue <- as.numeric(gsub("-", NA, datos$resultMeanValue))

fosforo <- datos %>%  
  filter(observedPropertyDeterminandCode == "CAS_7723-14-0") %>%
  select(waterBodyIdentifier, phenomenonTimeReferenceYear, X_val = resultMeanValue)

nitratos <- datos %>%  
  filter(observedPropertyDeterminandCode == "CAS_14797-55-8") %>%
  select(waterBodyIdentifier, phenomenonTimeReferenceYear, Y_val = resultMeanValue)

datos_pareados <- inner_join(fosforo, nitratos, by = c("waterBodyIdentifier", "phenomenonTimeReferenceYear"))
## Warning in inner_join(fosforo, nitratos, by = c("waterBodyIdentifier", "phenomenonTimeReferenceYear")): Detected an unexpected many-to-many relationship between `x` and `y`.
## ℹ Row 28 of `x` matches multiple rows in `y`.
## ℹ Row 64 of `y` matches multiple rows in `x`.
## ℹ If a many-to-many relationship is expected, set `relationship =
##   "many-to-many"` to silence this warning.
datos_pareados <- datos_pareados[complete.cases(datos_pareados$X_val, datos_pareados$Y_val), ]

4. IQR para valores atípicos

# ------------------------------------------------------------------------------
# 4. IQR PARA ATÍPICOS
# ------------------------------------------------------------------------------
if (nrow(datos_pareados) > 10) {
  
  # IQR para Fósforo (X)
  Q1_X <- quantile(datos_pareados$X_val, 0.25)
  Q3_X <- quantile(datos_pareados$X_val, 0.75)
  IQR_X <- Q3_X - Q1_X
  
  # IQR para Nitratos (Y)
  Q1_Y <- quantile(datos_pareados$Y_val, 0.25)
  Q3_Y <- quantile(datos_pareados$Y_val, 0.75)
  IQR_Y <- Q3_Y - Q1_Y
  
  # Aplicar filtro
  datos_filtrados <- datos_pareados[
    datos_pareados$X_val >= (Q1_X - 1.5 * IQR_X) & datos_pareados$X_val <= (Q3_X + 1.5 * IQR_X) &
      datos_pareados$Y_val >= (Q1_Y - 1.5 * IQR_Y) & datos_pareados$Y_val <= (Q3_Y + 1.5 * IQR_Y),
  ]
  
  if(nrow(datos_filtrados) == 0) datos_filtrados <- datos_pareados
  
} else {
  stop("No hay suficientes muestras emparejadas en el mismo año/lugar para estos compuestos.")
}

# Asignación final de variables limpias
x <- datos_filtrados$X_val
y <- datos_filtrados$Y_val

# Tabla de Pares de Valores (TVP)
TVP <- data.frame(Fosforo = x, Nitratos = y)

5.Diagrama de Dispersión

# ------------------------------------------------------------------------------
# 5. GRÁFICA No1: DIAGRAMA DE DISPERSIÓN 
# ------------------------------------------------------------------------------
plot(x, y,
     main = "Gráfica No1: Relación entre Fósforo Total y Nitratos en Cuerpos 
     de Agua de Europa",
     xlab = "Fósforo Total (mg/L)",      
     ylab = "Nitratos (mg/L)",     
     col = rgb(91, 192, 222, maxColorValue = 255, alpha = 60), 
     pch = 16,                               
     cex = 0.8,                               
     xlim = c(0, max(x) * 1.05),      
     ylim = c(0, max(y) * 1.05))

6. Conjetura

# ------------------------------------------------------------------------------
# 6. CONJETURA
# ------------------------------------------------------------------------------
# La distribución de los puntos sugiere una relación positiva entre ambos nutrientes. 
# A medida que los niveles de Fósforo Total aumentan en los cuerpos de agua, los niveles de Nitratos 
# también tienden a incrementarse, debido a que comparten fuentes comunes de contaminación antropogénica 
# (como escorrentía agrícola, fertilizantes y aguas residuales urbanas). 
# Esta tendencia justifica el ajuste de un modelo de regresión lineal para evaluar la coexistencia 
# y el comportamiento conjunto de ambos contaminantes en los ecosistemas acuáticos europeos.

7 Cálculo de parámetros del modelo

# ------------------------------------------------------------------------------
# 6. CÁLCULO DE PARÁMETROS DEL MODELO LINEAL
# ------------------------------------------------------------------------------
regresionlineal <- lm(y ~ x)

# Extraer coeficientes automáticamente
intercepto <- coef(regresionlineal)[1]
pendiente  <- coef(regresionlineal)[2]

print(paste("Intercepto (beta_0):", round(intercepto, 4)))
## [1] "Intercepto (beta_0): 5.2799"
print(paste("Pendiente (beta_1):", round(pendiente, 4)))
## [1] "Pendiente (beta_1): 85.0372"

8. Regresión Lineal modelo y realidad

# ------------------------------------------------------------------------------
# 7. GRÁFICA No2: REGRESIÓN LINEAL 
# ------------------------------------------------------------------------------
plot(x, y,
     main = "Gráfica No2: Regresión lineal entre Fósforo Total y Nitratos 
     en Cuerpos de Agua de Europa",
     xlab = "Fósforo Total (mg/L)",                  
     ylab = "Nitratos (mg/L)",                       
     col = rgb(91, 192, 222, maxColorValue = 255, alpha = 60), 
     pch = 16,                                       
     cex = 0.8,                                      
     cex.main = 1,                                  
     cex.lab = 1,                                   
     cex.axis = 0.9,
     xlim = c(0, max(x) * 1.05),   
     ylim = c(0, max(y) * 1.05),
     xaxs = "i",           
     yaxs = "i")                                        

abline(regresionlineal, col = "red", lwd = 2)

9. Test de bondad

# ================
# TEST DE BONDAD 
# ================

# Coeficiente de correlación de Pearson (r)
r_valor <- cor(x, y)
r_porcentaje <- r_valor * 100

# Coeficiente de determinación (R²) basado en el modelo ajustado
r2_porcentaje <- summary(regresionlineal)$r.squared * 100

print(paste("Coeficiente de correlación (r %):", round(r_porcentaje, 2), "%"))
## [1] "Coeficiente de correlación (r %): 47.12 %"
print(paste("Coeficiente de determinación (R² %):", round(r2_porcentaje, 2), "%"))
## [1] "Coeficiente de determinación (R² %): 22.2 %"

10. Restricciones

# ------------------------------------------------------------------------------
# 10. RESTRICCIONES 
# ------------------------------------------------------------------------------
# Dominio [x]: D= {R+^0} (Fósforo Total >= 0)
# Dominio [y]: D= {R+^0} (Nitratos >= 0)

# ¿Existe algún valor en dominio de x que sustituido en el modelo matemático genere un valor en y fuera de su dominio?

# Al igual que con el material particulado, las concentraciones de nutrientes en ecosistemas acuáticos no pueden ser negativas. Físicamente, un valor de Fósforo (x = 0) debería idealmente dar valores de  Nitratos (y) mayores o iguales a cero. Si el intercepto (beta_0) del modelo matemático resulta ser ligeramente negativo debido al ajuste estadístico, teóricamente existirían valores muy bajos de x que darían un resultado de y negativo (fuera de su dominio físico). En la práctica, el modelo se restringe y valida únicamente para el rango de concentraciones reales observadas en los cuerpos de agua europeos.

11. Aplicación del modelo

# ------------------------------------------------------------------------------
# 11. APLICACIONES DEL MODELO 
# ------------------------------------------------------------------------------
# Evaluación para un valor esperado de Fósforo Total = 0.5 mg/L
Fosforo_evaluar <- 0.5
Nitratos_esperado <- intercepto + (pendiente * Fosforo_evaluar)

print(paste("Nitratos esperados (mg/L) para Fósforo =", Fosforo_evaluar, ":", round(Nitratos_esperado, 4)))
## [1] "Nitratos esperados (mg/L) para Fósforo = 0.5 : 47.7985"

12. Conclusión

En el estudio de la contaminación del agua en Europa se observa una relación lineal positiva entre la concentración de Fósforo Total y los niveles de Nitratos. El modelo matemático se describe mediante la ecuación y = 5.28x + 85.037. El modelo explica aproximadamente el 22.2% de la variabilidad de los nitratos, lo que indica una asociación moderada entre ambas variables. El porcentaje restante de la variabilidad 77.8% puede atribuirse a otros factores físicos, químicos y biológicos que no fueron considerados, como las corrientes hídricas, la temperatura del agua, el oxígeno disuelto o la presencia de otros vertidos contaminantes. Las restricciones se aplican para todo el dominio natural de la variable: x ≥ 0, y ≥ 0, siendo el modelo más confiable dentro del rango observado de los datos en los ecosistemas acuáticos europeos.