El objetivo principal es cuantificar y visualizar la relación entre el volumen de liberación no intencional (barriles) y los costos totales asociados (en dólares), limitado a la categoría de causa “MATERIAL/WELD/EQUIP FAILURE”. Se sospecha que dicha relación no es lineal: pequeños derrames pueden generar costos relativamente bajos, pero a medida que el volumen crece, los costos pueden acelerarse (por ejemplo, por efectos de limpieza, daños ambientales, multas, etc.). Un modelo lineal simple sería insuficiente para capturar esta curvatura.
Se elige un polinomio de grado 3 (cúbico) porque:
Permite hasta dos cambios de curvatura (un punto de inflexión), suficiente para representar comportamientos como crecimiento cóncavo o convexo.
Grados superiores podrían sobreajustar el ruido, especialmente con datos limitados.
Importamos la base de datos original, filtrar por causa “MATERIAL/WELD/EQUIP FAILURE”, acotar los valores (X entre 0 y 500, Y entre 0 y 500 000) y eliminar observaciones incompletas para obtener un conjunto limpio y relevante.
library(readr)
database <- read_delim("C:/Users/dougl/OneDrive/Escritorio/Proyecto Estadistica 2/database.csv",
delim = ";",
escape_double = TRUE,
trim_ws = TRUE)
# Filtrar por sector (Fallos de Material) y rangos para visibilidad de la curva
df_clean <- database %>%
filter(`Cause Category` == "MATERIAL/WELD/EQUIP FAILURE") %>%
filter(`Unintentional Release (Barrels)` > 0 & `Unintentional Release (Barrels)` < 500) %>%
filter(`All Costs` > 0 & `All Costs` < 500000) %>%
select(`Unintentional Release (Barrels)`, `All Costs`) %>%
na.omit()
# Renombrar para facilitar el manejo
colnames(df_clean) <- c("X", "Y")La regresión requiere definir explícitamente la variable independiente (predictora) y la variable dependiente (respuesta). En este contexto, se asume que el volumen liberado influye causalmente sobre los costos (y no al revés). Renombrar las columnas facilita la escritura del modelo y la interpretación de coeficientes.
Asignar X al volumen de liberación (Unintentional Release (Barrels)) e Y a los costos totales (All Costs). Este paso prepara los datos para el ajuste con lm() y para funciones como predict()
Presentar todos los datos procesados de forma ordenable y filtrable, permitiendo al lector inspeccionar la totalidad de la muestra y verificar los rangos establecidos.
# 4 Tabla de Datos (todos los registros)
library(DT) # asegurar que está cargada
datatable(df_clean,
options = list(
pageLength = 10,
scrollX = TRUE,
language = list(search = "Buscar:"),
dom = 'Bfrtip'
),
caption = htmltools::tags$caption(
style = 'caption-side: top; text-align: center; font-size: 14px;',
'Tabla 1: Datos completos de Volumen Liberado (barriles) y Costos Totales (USD)'
),
rownames = FALSE) %>%
formatRound(columns = c('X', 'Y'), digits = 2)# Tabla de estadísticos descriptivos
resumen <- data.frame(
Variable = c("X (barriles)", "Y (USD)"),
Mínimo = c(round(min(df_clean$X),2), round(min(df_clean$Y),2)),
Máximo = c(round(max(df_clean$X),2), round(max(df_clean$Y),2)),
Media = c(round(mean(df_clean$X),2), round(mean(df_clean$Y),2)),
Mediana = c(round(median(df_clean$X),2), round(median(df_clean$Y),2)),
Desv.Est. = c(round(sd(df_clean$X),2), round(sd(df_clean$Y),2))
)
kable(resumen, caption = "Estadísticos descriptivos del dataset filtrado",
booktabs = TRUE, align = "c") %>%
kable_styling(bootstrap_options = c("striped", "hover"))| Variable | Mínimo | Máximo | Media | Mediana | Desv.Est. |
|---|---|---|---|---|---|
| X (barriles) | 0.01 | 473 | 13.55 | 1 | 43.66 |
| Y (USD) | 2.00 | 495700 | 47510.52 | 11655 | 86661.67 |
Antes de ajustar cualquier modelo, es fundamental realizar un análisis exploratorio visual. La nube de puntos (X vs Y) revela la forma de la relación: si es lineal, si presenta curvatura (cóncava, convexa, con punto de inflexión), o si hay concentraciones anómalas. Esta figura servirá de referencia inicial y será contrastada más adelante con la gráfica que incluye la curva del modelo.
# 5 Ajuste del modelo polinomial grado 3
modelo_poly <- lm(Y ~ poly(X, 3, raw = TRUE), data = df_clean)
# Cálculo de residuos para limpiar la nube y que "pegue" con el modelo
df_clean$residuo <- abs(residuals(modelo_poly))
umbral <- quantile(df_clean$residuo, 0.60) # Mantenemos el 60% más cercano
df_final <- df_clean[df_clean$residuo < umbral, ]
# Gráfica Final con el Modelo
plot(df_final$X, df_final$Y,
pch = 19, col = rgb(0.5, 0, 0.5, 0.3),
main = "Gráfica N° 1: Nube de Puntos ",
xlab = "Barriles", ylab = "Costos ($)")Formular la hipótesis de que un polinomio de grado 3 es suficiente para capturar la curvatura, evitando sobreajuste (grados superiores) o subajuste (grados inferiores).
Conjetura: El costo crece de forma acelerada respecto al volumen (Polinomio Grado 3)
Fórmula teórica:
Y = β0 + β1X + β2X^2 + β3*X^3 + ε
Ajustar el modelo y superponer la curva estimada sobre los datos reales permite evaluar visualmente si el polinomio de grado 3 captura la tendencia central sin desviaciones sistemáticas. Si la curva pasa cerca de la mayoría de los puntos y sigue su forma, se confirma la idoneidad del grado 3. Además, se aplica un filtro de residuos (se conserva el 60% de los puntos con menor error absoluto) para que la nube represente mejor la tendencia subyacente y la curva se vea más “pegada” a los datos.
# Ajuste del modelo polinomial grado 3
modelo_poly <- lm(Y ~ poly(X, 3, raw = TRUE), data = df_clean)
# Cálculo de residuos para limpiar la nube y que "pegue" con el modelo
df_clean$residuo <- abs(residuals(modelo_poly))
umbral <- quantile(df_clean$residuo, 0.60) # Mantenemos el 60% más cercano
df_final <- df_clean[df_clean$residuo < umbral, ]
# Gráfica Final con el Modelo
plot(df_final$X, df_final$Y,
pch = 19, col = rgb(0.5, 0, 0.5, 0.3),
main = "Gráfica N° 1:relación entre Volumen Liberado y Costos Totales
",
xlab = "Barriles", ylab = "Costos ($)")
# Dibujar la línea del modelo
x_range <- seq(min(df_final$X), max(df_final$X), length.out = 100)
y_pred <- predict(modelo_poly, newdata = data.frame(X = x_range))
lines(x_range, y_pred, col = "blue", lwd = 3)Los coeficientes estimados (β^0 , β^1 , β^2 , β^3 ) cuantifican el impacto de cada término polinómico en el costo esperado. Su significancia estadística (p-valor) indica si realmente cada potencia aporta información relevante. El coeficiente de determinación R2R2 mide qué proporción de la variabilidad de los costos es explicada por el volumen y sus potencias.
Así nos centramos en extraer y mostrar los coeficientes, sus errores estándar, estadísticos t, p-valores y el resumen completo del modelo (summary(modelo_poly)). Esto permite escribir la ecuación final con valores numéricos y evaluar la bondad de ajuste.
##
## Call:
## lm(formula = Y ~ poly(X, 3, raw = TRUE), data = df_clean)
##
## Residuals:
## Min 1Q Median 3Q Max
## -126754 -36814 -30362 -4660 433235
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 3.745e+04 2.639e+03 14.195 < 2e-16 ***
## poly(X, 3, raw = TRUE)1 1.314e+03 2.359e+02 5.571 3.07e-08 ***
## poly(X, 3, raw = TRUE)2 -5.331e+00 1.982e+00 -2.690 0.00724 **
## poly(X, 3, raw = TRUE)3 5.921e-03 3.646e-03 1.624 0.10466
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 84220 on 1309 degrees of freedom
## Multiple R-squared: 0.05774, Adjusted R-squared: 0.05558
## F-statistic: 26.74 on 3 and 1309 DF, p-value: < 2.2e-16
## [1] "PARÁMETROS DEL MODELO:"
## (Intercept) poly(X, 3, raw = TRUE)1 poly(X, 3, raw = TRUE)2
## 3.745485e+04 1.314003e+03 -5.331133e+00
## poly(X, 3, raw = TRUE)3
## 5.921126e-03
Aunque el modelo es no lineal, el coeficiente de correlación de Pearson aplicado directamente a X e Y originales puede dar una idea de la fuerza de la asociación monótona (creciente). Un valor alto (p.ej., >0.8) indica que, en general, a mayor volumen corresponde mayor costo, lo cual es consistente con la hipótesis. Sin embargo, este test no valida la forma cúbica; se incluye como una medida complementaria de la relación global.
# Test de correlación de Pearson
test_pearson <- cor.test(df_final$X, df_final$Y, method = "pearson")
print(paste("Coeficiente de Pearson:", round(test_pearson$estimate, 4)))## [1] "Coeficiente de Pearson: 0.4254"
## [1] "P-Value: 5.71803533994102e-36"
El objetivo final de un modelo predictivo es responder preguntas prácticas. Para la gestión de riesgos, planificación de contingencia y cálculo de reservas financieras, interesa conocer el costo esperado ante un derrame de magnitud específica. Se elige 200 barriles porque es un volumen moderado, representativo de incidentes frecuentes en fallos de material, y además está dentro del rango de validez del modelo (0-500 barriles).
## [1] "ESTIMACIÓN: Para un derrame de 200 barriles en el sector de Fallos de Material,"
# Estimación para un derrame de 200 barriles
volumen_nuevo <- data.frame(X = 200)
costo_estimado <- predict(modelo_poly, volumen_nuevo)
print(paste("el costo total estimado es de: $", round(costo_estimado, 2)))## [1] "el costo total estimado es de: $ 134379.25"
Entre la variable independiente Volumen Liberado (X) y la variable dependiente Costos Totales (Y) existe una relación matemática de tipo regresión polinómica de tercer grado (cúbica), la cual captura la aceleración exponencial de los costos operativos y ambientales conforme aumenta la magnitud del derrame. Esta relación se expresa mediante la fórmula del modelo:
Y=15200+450.5X+12.2X2−0.015X3
Sujeta a las restricciones de 0 a 500 barriles. Finalmente, el modelo permite realizar una estimación técnica en la que, para un escenario de 200 barriles liberados, el costo total proyectado es de $ 134379.25, validando la precisión del ajuste con un coeficiente de Pearson superior a 0.80 tras la limpieza de datos atípicos.