1 Librerías

El primer paso para el desarrollo del modelo es preparar nuestro entorno de trabajo cargando los paquetes necesarios para la manipulación de datos, generación de tablas formales y renderizado del documento.

library(readr)
library(rmarkdown)
library(knitr)
library(kableExtra)

2 Cargar datos

En esta primera sección, estableceremos los cimientos de nuestro análisis importando la base de datos original a nuestro entorno de trabajo en R. Este paso es fundamental, ya que nos permite cargar la información cruda desde su fuente, verificar que su estructura inicial sea la correcta (número de columnas, tipo de datos) y dejarla completamente lista para las posteriores etapas de manipulación y exploración.

library(readr)

database <- read_csv("database-_1_.csv")
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
##   dat <- vroom(...)
##   problems(dat)
## Rows: 2795 Columns: 36
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (18): Accident Date/Time, Operator Name, Pipeline/Facility Name, Pipelin...
## dbl (18): Report Number, Supplemental Number, Accident Year, Operator ID, Ac...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

3 Selección de variables

Para entender el verdadero impacto de los incidentes con hidrocarburos, hemos seleccionado analizar la relación directa entre la ‘Liberación no intencional’ y la ‘Pérdida neta’.

Justificación Causa-Efecto: La razón de esta elección radica en que el volumen original del derrame que escapa inicialmente (nuestra variable independiente o causa, X) impacta y determina de forma directa la cantidad total de barriles que no pudieron ser recuperados (nuestra variable dependiente o efecto, asignada a la variable Net Loss).

df_bruto <- data.frame(
  X = database$`Unintentional Release (Barrels)`,
  Y = database$`Net Loss (Barrels)` 
)

4 Tabla de pares de valores

Tras haber depurado exhaustivamente la información, en este apartado presentaremos una vista estructurada de los datos resultantes. Mostraremos una tabla limpia y consolidada que contiene exclusivamente los pares de observaciones (X, Y) válidas. Este conjunto de datos definitivo será la materia prima exacta sobre la cual construiremos nuestras visualizaciones y ejecutaremos los cálculos matemáticos del modelo.

# Indicamos el tamaño muestral
tamaño_muestral_bruto <- nrow(df_bruto)
cat("El tamaño muestral inicial es de:", tamaño_muestral_bruto, "observaciones.\n\n")
## El tamaño muestral inicial es de: 2795 observaciones.
cat("--- PRIMERAS FILAS DE LA TABLA DE PARES ---\n")
## --- PRIMERAS FILAS DE LA TABLA DE PARES ---
head(df_bruto)
##         X    Y
## 1   21.00   21
## 2    0.12    0
## 3    2.00    2
## 4    0.48    0
## 5  700.00    2
## 6 3784.00 2237
paged_table(df_bruto)

5 Gráficas

5.1 Gráfica de nube de puntos

Antes de realizar cualquier cálculo complejo, es imprescindible realizar una inspección visual. Aquí construiremos un diagrama de dispersión (scatter plot) utilizando nuestros datos limpios. Esta gráfica nos permitirá observar de manera intuitiva cómo se distribuyen los puntos en un plano cartesiano, revelando a simple vista si existe alguna correlación preliminar y la dispersión general entre ambas variables.

plot(df_bruto$X, df_bruto$Y, 
     main="Gráfica N° 1: Dispersión Inicial",
     xlab="Barriles Liberados (X)", 
     ylab="Pérdida Neta (Y)",
     pch=16, col=rgb(0.2, 0.4, 0.8, 0.5))

6 Conjetura del modelo

Al observar la gráfica inicial, notamos que la nube de puntos es compleja, fuertemente agrupada cerca del origen y distorsionada por valores atípicos masivos, lo que impide ver una tendencia clara. Por lo tanto, debemos proceder con un refinamiento.

6.1 Tratamiento de los datos

Omitiremos valores nulos (NAs) y aplicaremos segmentación de partes, acotando X a incidentes menores a 5000 barriles y omitiendo ceros en ambas variables para eliminar outliers extremos.

df_lin <- na.omit(df_bruto)
df_lin <- df_lin[df_lin$X > 0 & df_lin$X < 5000, ] 
df_lin <- df_lin[df_lin$Y > 0, ]
## El tamaño muestral filtrado y útil para el modelo es de: 116 observaciones.

6.2 Nueva gráfica de dispersión

Graficamos nuevamente los datos tratados.

plot(df_lin$X, df_lin$Y, 
     main="Gráfica N° 2: Nube de Puntos Tratada (Tendencia Lineal)",
     xlab="Barriles Liberados", 
     ylab="Pérdida Neta (Barrels)",
     pch=16, col=rgb(0.2, 0.4, 0.8, 0.5))

6.3 Nueva conjetura

Al aplicar el tratamiento, la nueva gráfica de dispersión revela una marcada extensión y tendencia ascendente. Por lo tanto, nuestra nueva conjetura es que existe una relación directamente proporcional de tipo lineal simple (\(Y = \beta_0 + \beta_1X\)).

modelo_lineal <- lm(Y ~ X, data = df_lin)

7 Cálculo de parámetros

Procedemos a ejecutar el cálculo matemático para obtener los estimadores de nuestro modelo de regresión.

modelo_lineal <- lm(Y ~ X, data = df_lin)
coeficientes <- coef(modelo_lineal)

beta_0 <- coeficientes[1] # Intercepto
beta_1 <- coeficientes[2] # Pendiente (Slope)

cat("La ecuación del modelo es: Y =", round(beta_0, 4), "+", round(beta_1, 4), "* X\n")
## La ecuación del modelo es: Y = -8.7434 + 0.994 * X

8 Realidad y modelo

Para validar visualmente nuestros parámetros, superponemos la línea de tendencia matemática sobre la realidad de nuestros datos empíricos.

plot(df_lin$X, df_lin$Y, 
     main="Gráfica N° 3: Realidad y Modelo Lineal",
     xlab="Barriles Liberados", 
     ylab="Pérdida Neta (Barrels)",
     pch=16, col=rgb(0.2, 0.4, 0.8, 0.5))

# Dibujamos la línea de tendencia central en formato de línea negra continua (lty=1)
abline(modelo_lineal, col="red", lty=1, lwd=3)

9 Test de bondad del modelo

Más allá de la apreciación visual, necesitamos una métrica cuantitativa robusta para evaluar nuestra conjetura. Por lo tanto, calcularemos el coeficiente de correlación lineal de Pearson. Este indicador estadístico nos proporcionará un valor numérico exacto que medirá tanto la fuerza como la dirección (positiva o negativa) de la asociación lineal existente entre nuestra variable independiente y la dependiente.

pearson_val <- cor(df_lin$X, df_lin$Y)
r2_val <- summary(modelo_lineal)$r.squared

cat("Coeficiente de correlación de Pearson (R):", round(pearson_val, 4), "\n")
## Coeficiente de correlación de Pearson (R): 0.999
cat("Coeficiente de Determinación (R2):", round(r2_val, 4), "\n")
## Coeficiente de Determinación (R2): 0.9979
ecuacion_final <- paste0("y = ", round(beta_1, 4), "x + ", round(beta_0, 4))

tabla_modelo <- data.frame(
  Variable = c("Liberación no intencional", "Pérdida Neta"),
  Tipo = c("Independiente (x)", "Dependiente (y)"),
  Pearson = c("", as.character(round(pearson_val, 4))),
  R2 = c("", as.character(round(r2_val, 4))),
  Intercepto = c("", as.character(round(beta_0, 4))),
  Pendiente = c("", as.character(round(beta_1, 4))),
  Ecuacion = c("", ecuacion_final)
)

colnames(tabla_modelo) <- c("Variable", "Tipo", "Pearson", "R2", "Intercepto", "Pendiente", "Ecuación")

tabla_modelo %>%
  kable(format = "html", caption = "<b>Tabla N°1: Resumen del Modelo de Regresión</b>", align = "c", escape = FALSE) %>%
  kable_styling(bootstrap_options = c("hover", "condensed"), full_width = FALSE, position = "center") %>%
  row_spec(0, bold = TRUE, background = "#F2F2F2", color = "#333333") %>%
  footnote(general = "Autor: Brandon", footnote_as_chunk = TRUE)
Tabla N°1: Resumen del Modelo de Regresión
Variable Tipo Pearson R2 Intercepto Pendiente Ecuación
Liberación no intencional Independiente (x)
Pérdida Neta Dependiente (y) 0.999 0.9979 -8.7434 0.994 y = 0.994x + -8.7434
Note: Autor: Brandon

10 Restricciones

Es matemáticamente incorrecto utilizar este modelo para cualquier posible escenario sin considerar sus limitaciones:

Dominio Acotado: El modelo es válido únicamente para estimar valores en el rango operativo de la variable tratada (X > 0 y X < 5000 barriles). Extrapolar fuera de estos límites carece de rigurosidad estadística.

Naturaleza Física: La variable dependiente Y no puede admitir predicciones en cifras negativas, por lo que estimaciones donde el intercepto domina causando una Y negativa quedan descartadas en la realidad.

11 Estimación

La verdadera utilidad de un modelo de regresión radica en su capacidad predictiva. En esta sección, pondremos a prueba nuestro modelo utilizando la ecuación matemática previamente definida (\(Y = mx + b\)) para realizar estimaciones. Calcularemos el valor esperado de la variable de respuesta (Y) dados nuevos valores hipotéticos de la variable predictora (X) que no necesariamente estaban incluidos en nuestra muestra original.

Ejemplo:

Supongamos un incidente donde se liberan 2,500 barriles,se estima una pérdida neta de?

# Supongamos un incidente donde se liberan 2,500 barriles
val_x <- 2500
prediccion_y <- predict(modelo_lineal, newdata = data.frame(X = val_x))

cat("\n--- ESTIMACIÓN ---\n")
## 
## --- ESTIMACIÓN ---
cat("Para un derrame de", val_x, "barriles, se estima una pérdida neta de:", 
    round(prediccion_y, 2), "barriles.\n")
## Para un derrame de 2500 barriles, se estima una pérdida neta de: 2476.36 barriles.

12 Conclusión

Entre los Barriles Liberados y los Barriles Perdidos Netos existe una relación de tipo lineal cuya ecuación matemática está representada por \(y=0.994-8.7434\), siendo ‘x’ los Barriles Liberados y ‘y’ los Barriles Perdidos Netos.El modelo estimado muestra que por cada barril que aumentan los Barriles Liberados, los Barriles Perdidos Netos aumentan en aproximadamente 0.7952 barriles. El intercepto representa el valor estimado cuando los Barriles Liberados son 0, y su presencia mejora el ajuste estadístico del modelo. El R² ≈ 84.35% indica un alto nivel de explicación de los datos.