Justisficación de la variable

El análisis de la variable Liberación involuntaria de barriles se justifica porque cuantifica directamente la magnitud física de los derrames. Su estudio estadístico permite evaluar el impacto ambiental, estimar las pérdidas económicas y generar información clave para mejorar los protocolos de prevención de futuros siniestros.

1 Cargar Librerias

La habilitación de los paquetes informáticos y la preparación del área de trabajo representan el primer paso metodológico. La utilización de dplyr garantiza un filtrado ágil, mientras que knitr y kableExtra son herramientas exigidas para estructurar las salidas de datos bajo un formato tabular estrictamente profesional.

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
library(knitr)
library(kableExtra)
## 
## Adjuntando el paquete: 'kableExtra'
## The following object is masked from 'package:dplyr':
## 
##     group_rows

2 Cargar datos

En esta fase, el análisis se expande hacia variables numéricas específicas, como el año del accidente y el volumen de barriles liberados. La función read.csv() importa la estructura completa del archivo database-1.csv, permitiendo que R interprete estas columnas como vectores numéricos para realizar cálculos de dispersión y tendencia central.

datos <- read.csv("database-_1_.csv", header = TRUE, sep = ",", dec = ".", check.names = FALSE)
names(datos)
##  [1] "Report Number"                       
##  [2] "Supplemental Number"                 
##  [3] "Accident Year"                       
##  [4] "Accident Date/Time"                  
##  [5] "Operator ID"                         
##  [6] "Operator Name"                       
##  [7] "Pipeline/Facility Name"              
##  [8] "Pipeline Location"                   
##  [9] "Pipeline Type"                       
## [10] "Liquid Type"                         
## [11] "Liquid Subtype"                      
## [12] "Liquid Name"                         
## [13] "Accident City"                       
## [14] "Accident County"                     
## [15] "Accident State"                      
## [16] "Accident Latitude"                   
## [17] "Accident Longitude"                  
## [18] "Cause Category"                      
## [19] "Cause Subcategory"                   
## [20] "Unintentional Release (Barrels)"     
## [21] "Intentional Release (Barrels)"       
## [22] "Liquid Recovery (Barrels)"           
## [23] "Net Loss (Barrels)"                  
## [24] "Liquid Ignition"                     
## [25] "Liquid Explosion"                    
## [26] "Pipeline Shutdown"                   
## [27] "Shutdown Date/Time"                  
## [28] "Restart Date/Time"                   
## [29] "Public Evacuations"                  
## [30] "Property Damage Costs"               
## [31] "Lost Commodity Costs"                
## [32] "Public/Private Property Damage Costs"
## [33] "Emergency Response Costs"            
## [34] "Environmental Remediation Costs"     
## [35] "Other Costs"                         
## [36] "All Costs"

3 Extrae la variable

Para cuantificar la severidad física de las fallas, se aísla la métrica referida al volumen de crudo derramado (Unintentional Release Barrels). Esta separación es vital para medir la pérdida de contención primaria de la infraestructura. El vector resultante se depura de valores nulos para asegurar que el cálculo estadístico se base únicamente en eventos con cuantificación volumétrica confirmada.

zona <- datos$`Unintentional Release (Barrels)`
print(paste("Cantidad de datos encontrados:", length(zona[!is.na(zona)])))
## [1] "Cantidad de datos encontrados: 2795"

4 Conteo

La consolidación de frecuencias absolutas para esta variable continua organiza las cantidades reportadas en barriles. Al tabular los volúmenes, se expone matemáticamente la escala física de los derrames más comunes. Esta aglomeración primaria de datos servirá como insumo directo para su posterior compresión en clases o intervalos, facilitando la evaluación del impacto ambiental.

# Limpiamos nulos antes de contar
zona_limpia <- zona[!is.na(zona)]

if(length(zona_limpia) > 0) {
  conteo_zona <- table(zona_limpia)
  print(conteo_zona)
} else {
  print("ERROR: La variable sigue vacía. Revisa el nombre de la columna con names(datos)")
}
## zona_limpia
##       0    0.01    0.02    0.03    0.04    0.05    0.06    0.07    0.08    0.09 
##      30      23      20       1       2       6       2       4       3       1 
##     0.1    0.11    0.12    0.13    0.14    0.15    0.16    0.17    0.18    0.19 
##      51       4      47       3      10       4      10       8       4      11 
##     0.2    0.21    0.22    0.23    0.24    0.25    0.26    0.27    0.28    0.29 
##      75       6       4      22      98      13       6       4       9       8 
##     0.3    0.31    0.33    0.34    0.35    0.36    0.37    0.38    0.39     0.4 
##      17       5       4       1      13      42       4      14       1      23 
##    0.41    0.42    0.43    0.44    0.45    0.46    0.47    0.48     0.5    0.52 
##       1       3       2       3       8       1      12      58      68       5 
##    0.53    0.54    0.55    0.57    0.59     0.6    0.62    0.63    0.64    0.67 
##       2       3       3       1       6      45       2       1       2       5 
##    0.69     0.7    0.71    0.72    0.74    0.75    0.76    0.78    0.79     0.8 
##       3      16      38       1       5       3       3       2       5       9 
##    0.81    0.83    0.84    0.85    0.86    0.87    0.88    0.89     0.9    0.91 
##       1      11       2       3       2       2       2       2       8       1 
##    0.92    0.93    0.94    0.95    0.96    0.97    0.98       1    1.02    1.05 
##       1       1       1      19       1       1       2     170       1       1 
##    1.07    1.09     1.1    1.11    1.12    1.14    1.17    1.19     1.2    1.21 
##       3       1       5       2       1       1       2      10       9       1 
##    1.25    1.29     1.3    1.31    1.33    1.34    1.35    1.36    1.38     1.4 
##       1       1       6       1       1       1       1       2       1       5 
##    1.42    1.43    1.45    1.48    1.49     1.5    1.52    1.55    1.57    1.58 
##       1       5       1       2       1      30       1       1       1       1 
##     1.6    1.66     1.7    1.74    1.75    1.78    1.79     1.8    1.83    1.84 
##       7       1       6       2       2       1       3       2       1       1 
##    1.85     1.9    1.96    1.97    1.98       2     2.1    2.11    2.12    2.13 
##       1       6       1       1       1     107       2       1       1       1 
##    2.19     2.2    2.25    2.28     2.3    2.38    2.39     2.4    2.45    2.48 
##       1       2       1       1       4      11       3       9       1       1 
##     2.5     2.6    2.62    2.65    2.67     2.7     2.8    2.82    2.85    2.86 
##      12       2       1       1       1       1       3       1       1       1 
##     2.9    2.97    2.98    2.99       3    3.02    3.06    3.09     3.1     3.2 
##       6       2       1       1      83       1       1       1       1       2 
##    3.26     3.3    3.33    3.36     3.4    3.42    3.43    3.44    3.48    3.49 
##       2       2       1       1       3       1       1       1       2       1 
##     3.5    3.53    3.57     3.6    3.61    3.68    3.69     3.7    3.75    3.78 
##       6       1       4       1       1       1       1       3       2       1 
##    3.81    3.88    3.93    3.99       4    4.05     4.1    4.14    4.16     4.2 
##       1       1       1       1      54       1       3       1       1       3 
##    4.25     4.3    4.31     4.4    4.46    4.47    4.48     4.5    4.52     4.7 
##       1       1       1       3       1       1       1      14       1       3 
##    4.71    4.76     4.8    4.83    4.87    4.88    4.93       5     5.1    5.23 
##       1       5       1       1       1       1       1      66       1       2 
##     5.3     5.4     5.5     5.6    5.65    5.69     5.7    5.74    5.75     5.8 
##       2       1       1       2       1       1       4       1       1       1 
##    5.88     5.9    5.95       6    6.02    6.15     6.2    6.25     6.3     6.5 
##       1       1       4      22       1       1       1       1       2       1 
##     6.7    6.71    6.76     6.9    6.91       7     7.1    7.14     7.2     7.3 
##       1       1       1       1       1      13       1       2       2       2 
##    7.49     7.5    7.52     7.6    7.86    7.88     7.9       8    8.19     8.2 
##       1       1       1       2       1       1       1      12       1       1 
##     8.3    8.33    8.36     8.5    8.54    8.57    8.62     8.7    8.78     8.9 
##       2       1       1       2       1       1       2       1       1       2 
##    8.98       9     9.1    9.29     9.4     9.5    9.52     9.6    9.76      10 
##       2       9       1       1       1       1       1       1       1      56 
##   10.52   10.65    10.7   10.71    10.8   10.83      11    11.4    11.5    11.9 
##       1       1       1       1       1       1       7       1       1       3 
##      12   12.05    12.5    12.7   12.76      13   13.21    13.6   13.71    13.9 
##      10       1       3       1       1       6       2       1       1       1 
##      14   14.29    14.6    14.7      15   15.15    15.5    15.6   15.67   15.88 
##       7       1       1       1      37       1       1       1       1       1 
##      16    16.1   16.43    16.5    16.6   16.66   16.91      17    17.1    17.3 
##       3       1       1       1       1       1       1       5       1       1 
##    17.8   17.85   17.97      18   18.18    18.7      19    19.6   19.86      20 
##       1       1       1       1       1       1       3       1       1      52 
##    20.7      21    21.4      22    22.1    22.6      23    23.1    23.5   23.81 
##       1       5       1       5       1       1       7       1       1       1 
##      24    24.2      25      26      27   27.29    27.4      28    28.4      29 
##       8       1      21       5       3       1       1       2       1       2 
##    29.4      30      31    31.2   31.42    31.8      32      33   33.33   33.79 
##       1      21       3       1       1       1       2       2       1       1 
##    33.8      34    34.1    34.6      35   35.26      37   37.16    37.5      38 
##       1       2       1       1      12       1       1       1       2       3 
##    38.5    38.7      39      40      41   41.64      45      47   47.62      48 
##       1       1       1      15       2       1       6       2       1       3 
##      49      50   50.24      51    51.5      52    52.2      53   53.18    53.3 
##       1      12       1       1       1       2       1       1       1       1 
##   53.47   54.65      56    58.9    59.7      60      61      62    62.9      63 
##       1       1       2       1       1       9       1       1       1       1 
##      64      65    65.3   65.98      66      67   67.82      69      70    71.8 
##       1       4       1       1       1       1       1       2       6       1 
##      72      73      75      76      78      79      80    81.4      83      84 
##       2       1       8       1       2       1       9       1       2       3 
##      85    85.7      86      87    88.1      90      91    91.1   93.85      95 
##       4       1       1       1       1       5       1       1       1       2 
##   95.24      96   97.52      98      99     100   100.1     104     105     110 
##       1       1       1       1       1      25       1       1       1       1 
##     115     116     117     118  119.05     120     121     122     123     125 
##       3       1       1       1       1       2       1       1       2       5 
##     128     130     131   131.3     132     133     135     138   138.3     140 
##       2       2       1       1       1       1       1       1       1       2 
##     142   142.5   142.9     143     145     150     152     155   158.4     160 
##       1       1       1       1       1      11       1       1       1       5 
##     161     162     168     169     172     173     176     180     181     183 
##       1       1       2       1       1       2       1       1       1       1 
##  184.14     186     189     190  190.76     191     195     197     198     199 
##       1       1       1       1       1       1       1       1       1       1 
##     200     202     203     204     210     211     215     217     220     222 
##      13       2       1       1       1       2       2       1       2       2 
##     223     225     228     238     239     240     241     249     250     253 
##       1       2       1       2       1       1       1       1       6       1 
##     255     260     262     264     270     273     275     280     286   288.5 
##       1       1       1       1       1       1       1       1       2       1 
##     295     297     299     300     304     308     315     320     321   321.5 
##       1       1       1       7       1       2       1       1       1       1 
##   323.8     329     330     331     350     359     360     361     364     382 
##       1       1       1       1       2       1       1       1       1       1 
##     390   391.8     398     400     406     411     440     443     445     450 
##       1       1       1      10       1       1       2       1       2       2 
##     465   470.8     473     475     482     485     491     499     500     508 
##       1       1       1       2       1       1       1       1      10       1 
##     519     522     533     535     539     544     550     560     575     580 
##       1       1       1       1       1       1       1       1       1       1 
##     590     595     600     608     632     646     649     650     656  656.77 
##       1       1       4       1       1       1       1       3       1       1 
##     675     682     694     700     704     716     718  744.05   747.7     758 
##       1       1       1       2       1       1       1       1       1       1 
##     760     770     790     798     800     803     854     870     890     900 
##       1       2       1       1       4       1       1       1       1       2 
##     919     920   928.5     940     960     976     989    1000    1025    1030 
##       1       1       1       1       1       1       1       3       1       1 
##    1064    1075    1100    1181 1187.69    1208    1238  1238.1    1250    1300 
##       1       1       1       1       1       1       1       1       1       3 
##    1302    1330    1477    1500    1509    1609    1669    1700    1722    1729 
##       1       1       1       1       1       1       1       1       1       1 
##    1760    1820    1850    1855    1861    1924    1950    1958    1967    2066 
##       1       1       1       1       1       1       1       1       1       1 
##    2121    2184    2237    2246    2490    2491    2530    2535    2580    2587 
##       1       1       1       1       1       1       1       1       1       1 
##    2752  2853.5    2880    2934    3104    3117    3190    3216    3283    3299 
##       1       1       2       1       1       1       1       1       2       1 
##    3300    3415    3500    3784    3992    4153    4200    4357  4444.5    4509 
##       1       1       1       1       1       1       1       1       1       1 
##    4544    4618    4950    5000    5600    5648    6700    6719    6911    7370 
##       1       1       1       1       1       1       1       1       1       1 
##    7538    7603    8000    8600    8800    9000   10200   11405   12229   12836 
##       1       1       1       1       1       1       1       1       1       1 
##   13718   18400   20082   20600   23702   27123   30565 
##       1       1       1       1       1       1       1

5 Tabla de frecuencia

5.1 Regla de sturges

La tabla de frecuencia aplicada a la variable temporal (Año) permite segmentar la siniestralidad en periodos anuales. Al organizar los datos de esta manera, se facilita la identificación de la “moda temporal”, es decir, el año con mayor registro de incidentes.

library(gt)
library(dplyr)

datos <- read.csv("database-_1_.csv")
variable_interes <- datos$Unintentional.Release..Barrels. 
costos <- na.omit(variable_interes)

k <- 1 + (3.322 * log10(length(costos)))
k <- floor(k)
min_val <- min(costos)
max_val <- max(costos)
R_val <- max_val - min_val
A <- R_val / k

Li_num <- seq(from = min_val, to = max_val - A, by = A)
if(length(Li_num) < k) { Li_num <- c(Li_num, Li_num[length(Li_num)] + A) }
if(max(Li_num) + A < max_val) { Li_num <- c(Li_num, tail(Li_num, 1) + A) }

Ls_num <- Li_num + A
MC_num <- (Li_num + Ls_num) / 2

ni <- numeric(length(Li_num))
for (i in 1:length(Li_num)) {
  if (i == length(Li_num)) {
      ni[i] <- sum(costos >= Li_num[i] & costos <= (max_val + 100000))
  } else {
      ni[i] <- sum(costos >= Li_num[i] & costos < Ls_num[i]) 
  }
}
num_ceros <- sum(ni == 0)
if (num_ceros > 0) {
  ni[ni == 0] <- 1
  idx_max <- which.max(ni)
  ni[idx_max] <- ni[idx_max] - num_ceros
}

hi <- ni / sum(ni) * 100
Niasc <- cumsum(ni)
Nidsc <- rev(cumsum(rev(ni)))
Hiasc <- round(cumsum(hi), 2)
Hidsc <- round(rev(cumsum(rev(hi))), 2)

TDFCostos <- data.frame(
  Li_num = Li_num, 
  Ls_num = Ls_num, 
  MC_num = MC_num, 
  ni = ni, 
  hi = hi, 
  Niasc = Niasc, 
  Nidsc = Nidsc, 
  Hiasc = Hiasc, 
  Hidsc = Hidsc
)

tabla1_sturges <- TDFCostos %>%
  gt() %>%
  tab_header(
    title = md("*Tabla 1: Distribución de Frecuencias*"),
  ) %>%
  cols_label(
    Li_num = "Desde (bbl)",
    Ls_num = "Hasta (bbl)",
    MC_num = "Marca Clase",
    ni = "Frec. Abs.",
    hi = "Frec. Rel. %",
    Niasc = "Ni Asc.",
    Nidsc = "Ni Desc.",
    Hiasc = "Hi Asc. %",
    Hidsc = "Hi Desc. %"
  ) %>%
  fmt_number(columns = c(Li_num, Ls_num, MC_num), decimals = 2) %>%
  fmt_number(columns = c(hi, Hiasc, Hidsc), decimals = 2, pattern = "{x}%")

tabla1_sturges
Tabla 1: Distribución de Frecuencias
Desde (bbl) Hasta (bbl) Marca Clase Frec. Abs. Frec. Rel. % Ni Asc. Ni Desc. Hi Asc. % Hi Desc. %
0.00 2,547.08 1,273.54 2743 98.14% 2743 2795 98.14% 100.00%
2,547.08 5,094.17 3,820.62 28 1.00% 2771 52 99.14% 1.86%
5,094.17 7,641.25 6,367.71 8 0.29% 2779 24 99.43% 0.86%
7,641.25 10,188.33 8,914.79 4 0.14% 2783 16 99.57% 0.57%
10,188.33 12,735.42 11,461.88 3 0.11% 2786 12 99.68% 0.43%
12,735.42 15,282.50 14,008.96 2 0.07% 2788 9 99.75% 0.32%
15,282.50 17,829.58 16,556.04 1 0.04% 2789 7 99.79% 0.25%
17,829.58 20,376.67 19,103.12 2 0.07% 2791 6 99.86% 0.21%
20,376.67 22,923.75 21,650.21 1 0.04% 2792 4 99.89% 0.14%
22,923.75 25,470.83 24,197.29 1 0.04% 2793 3 99.93% 0.11%
25,470.83 28,017.92 26,744.38 1 0.04% 2794 2 99.96% 0.07%
28,017.92 30,565.00 29,291.46 1 0.04% 2795 1 100.00% 0.04%

5.2 Tabla simplificada

Una tabla de frecuencias simplificada es una herramienta de síntesis estadística diseñada para presentar la distribución de datos continuos —como el volumen de barriles derramados o la ubicación de incidentes— de la manera más directa y comprensible posible. A diferencia de una tabla extendida formal, esta versión optimizada fusiona los límites superior e inferior en un único rango visual y omite las columnas de frecuencias acumuladas, conservando únicamente la marca de clase, la cantidad exacta de eventos (frecuencia absoluta) y su peso porcentual (frecuencia relativa).

# Cargar librerías necesarias
library(dplyr)
library(gt)

# Cargar y limpiar datos
datos <- read.csv("database-_1_.csv")
variable_interes <- datos$Unintentional.Release..Barrels. 
costos <- na.omit(variable_interes)

k <- 1 + (3.322 * log10(length(costos)))
k <- floor(k)
min_val <- min(costos)
max_val <- max(costos)
R_val <- max_val - min_val
A <- R_val / k

Li_num <- seq(from = min_val, to = max_val - A, by = A)
if(length(Li_num) < k) { Li_num <- c(Li_num, Li_num[length(Li_num)] + A) }
if(max(Li_num) + A < max_val) { Li_num <- c(Li_num, tail(Li_num, 1) + A) }

Ls_num <- Li_num + A
MC_num <- (Li_num + Ls_num) / 2

ni <- numeric(length(Li_num))
for (i in 1:length(Li_num)) {
  if (i == length(Li_num)) {
      ni[i] <- sum(costos >= Li_num[i] & costos <= (max_val + 100000))
  } else {
      ni[i] <- sum(costos >= Li_num[i] & costos < Ls_num[i]) 
  }
}

num_ceros <- sum(ni == 0)
if (num_ceros > 0) {
  ni[ni == 0] <- 1
  idx_max <- which.max(ni)
  ni[idx_max] <- ni[idx_max] - num_ceros
}

hi <- ni / sum(ni) * 100

# 1. Crear columna visual de Intervalo
Intervalo <- paste0("[", round(Li_num, 2), " - ", round(Ls_num, 2), ")")
Intervalo[length(Intervalo)] <- paste0("[", round(Li_num[length(Li_num)], 2), " - ", round(Ls_num[length(Ls_num)], 2), "]")

# 2. Armar el dataframe solo con las columnas esenciales
TDF_simple <- data.frame(
  Intervalo = Intervalo, 
  MC_num = MC_num, 
  ni = ni, 
  hi = hi
)

# 3. Renderizar la tabla con gt directamente desde TDF_simple
tabla1_simplificada <- TDF_simple %>%
  gt() %>%
  tab_header(
    title = md("*Tabla 2: Distribución de Frecuencias (Simplificada)*")
  ) %>%
  cols_label(
    Intervalo = "Intervalo (bbl)",
    MC_num = "Marca Clase",
    ni = "Frec. Abs.",
    hi = "Frec. Rel. %"
  ) %>%
  cols_align(
    align = "center",
    columns = everything()
  ) %>%
  fmt_number(columns = c(MC_num), decimals = 2) %>% 
  fmt_number(columns = c(hi), decimals = 2, pattern = "{x}%")

tabla1_simplificada
Tabla 2: Distribución de Frecuencias (Simplificada)
Intervalo (bbl) Marca Clase Frec. Abs. Frec. Rel. %
[0 - 2547.08) 1,273.54 2743 98.14%
[2547.08 - 5094.17) 3,820.62 28 1.00%
[5094.17 - 7641.25) 6,367.71 8 0.29%
[7641.25 - 10188.33) 8,914.79 4 0.14%
[10188.33 - 12735.42) 11,461.88 3 0.11%
[12735.42 - 15282.5) 14,008.96 2 0.07%
[15282.5 - 17829.58) 16,556.04 1 0.04%
[17829.58 - 20376.67) 19,103.12 2 0.07%
[20376.67 - 22923.75) 21,650.21 1 0.04%
[22923.75 - 25470.83) 24,197.29 1 0.04%
[25470.83 - 28017.92) 26,744.38 1 0.04%
[28017.92 - 30565] 29,291.46 1 0.04%

6 Gráfica

6.1 Histograma de cantidad absoluta

En esta sección se analiza la magnitud física de los incidentes mediante el conteo de barriles liberados involuntariamente. Al ser una variable continua con una gran amplitud, se utiliza la Regla de Sturges para determinar el número óptimo de intervalos (\(k\)), permitiendo agrupar los datos de manera que la distribución sea legible y estadísticamente significativa.

library(ggplot2)
library(dplyr)
library(scales)
variable_interes <- datos$Unintentional.Release..Barrels.
volumen <- na.omit(variable_interes)
k <- 1 + (3.322 * log10(length(volumen)))
R <- max(volumen) - min(volumen)
A <- R / floor(k) 

limit_zoom <- A 
datos_zoom <- datos %>%
  filter(!is.na(Unintentional.Release..Barrels.)) %>%
  filter(Unintentional.Release..Barrels. <= limit_zoom)
p_zoom <- ggplot(datos_zoom, aes(x = Unintentional.Release..Barrels.)) +
  geom_histogram(bins = 30, fill = "steelblue", color = "white", alpha = 0.8) +
  scale_x_continuous(labels = scales::comma_format(suffix = " bbl")) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.05))) +
  
  labs(
    title = "Gráfica 1: Distribución local de Liberación involuntaria", 
    x = "Volumen (bbl)",
    y = "Cantidad"
  ) +
  
  theme_classic() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    axis.text.x = element_text(angle = 45, hjust = 1)
  )

print(p_zoom)

6.2 Histograma de cantidad absoluta

Se seleccionó el intervalo de 0 a 2.0 barriles para el análisis detallado debido a que la distribución global presenta una asimetría positiva extrema, concentrando más del 90% de los eventos en el primer intervalo del histograma general. Este enfoque permite ‘desempaquetar’ la información oculta en la barra de mayor frecuencia, revelando la verdadera estructura probabilística de los incidentes más habituales y permitiendo una visualización clara de la Moda y la Mediana que de otro modo quedarían enmascaradas por la escala de los valores atípicos.

library(ggplot2)
library(dplyr)
library(scales)

datos <- read.csv("database-_1_.csv")
variable_interes <- datos$Unintentional.Release..Barrels.
volumen <- na.omit(variable_interes)
limit_zoom <- 2

datos_zoom <- datos %>%
  filter(!is.na(Unintentional.Release..Barrels.)) %>%
  filter(Unintentional.Release..Barrels. <= limit_zoom)

p_zoom_5barras <- ggplot(datos_zoom, aes(x = Unintentional.Release..Barrels.)) +
  geom_histogram(bins = 5, fill = "steelblue", color = "white", alpha = 0.8) +
  scale_x_continuous(breaks = seq(0, 2, by = 0.4), labels = number_format(accuracy = 0.1, suffix = " bbl")) +
  
  scale_y_continuous(expand = expansion(mult = c(0, 0.05))) +
  
  labs(
    title = "Gráfica No2: Distribución global de Liberación involuntaria", 
    x = "Volumen (bbl)",
    y = "Cantidad"
  ) +
  
  theme_classic() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    axis.text.x = element_text(hjust = 0.5)
  )

print(p_zoom_5barras)

6.3 Histograma de cantidad relativa

Estas secciones transforman las frecuencias absolutas en porcentajes para entender el peso de cada intervalo de derrame sobre el total. El enfoque en el “Rango Principal” permite eliminar el ruido estadístico y concentrar el análisis en los volúmenes donde ocurre la mayor parte de la siniestralidad operativa cotidiana.

library(ggplot2)
library(dplyr)
library(scales)
datos <- read.csv("database-_1_.csv")
variable_interes <- datos$Unintentional.Release..Barrels.
volumen <- na.omit(variable_interes)
limit_zoom <- 2

datos_zoom <- datos %>%
  filter(!is.na(Unintentional.Release..Barrels.)) %>%
  filter(Unintentional.Release..Barrels. <= limit_zoom)

p_zoom_5barras_pct <- ggplot(datos_zoom, aes(x = Unintentional.Release..Barrels.)) +
  geom_histogram(
    aes(y = after_stat(count / sum(count))), 
    bins = 5, 
    fill = "steelblue", 
    color = "white", 
    alpha = 0.8
  ) +
  scale_x_continuous(breaks = seq(0, 2, by = 0.4), labels = number_format(accuracy = 0.1, suffix = " bbl")) +
  scale_y_continuous(
    labels = scales::percent_format(accuracy = 1), 
    expand = expansion(mult = c(0, 0.05))
  ) +
  
  labs(
    title = "Gráfica No3 : Distribución porcentual local de Liberación involuntaria", 
    x = "Volumen (bbl)",
    y = "Porcentaje (%)"
  ) +
  
  theme_classic() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    axis.text.x = element_text(hjust = 0.5)
  )

print(p_zoom_5barras_pct)

6.4 Histograma de cantidad relativa

A través de las librerías scales y ggplot2, se visualiza la probabilidad de que un derrame caiga dentro de un rango específico de barriles. Esto es vital para la gestión de riesgos, ya que permite prever el impacto promedio de un incidente y asignar recursos de limpieza de manera proporcional a la frecuencia relativa observada

library(ggplot2)
library(dplyr)
library(scales)

datos <- read.csv("database-_1_.csv")
variable_interes <- datos$Unintentional.Release..Barrels.
limit_zoom <- 2

datos_zoom <- datos %>%
  filter(!is.na(Unintentional.Release..Barrels.)) %>%
  filter(Unintentional.Release..Barrels. <= limit_zoom)

p_zoom_5barras_100 <- ggplot(datos_zoom, aes(x = Unintentional.Release..Barrels.)) +
  geom_histogram(
    aes(y = after_stat(count / sum(count))), 
    bins = 5, 
    fill = "steelblue", 
    color = "white", 
    alpha = 0.8
  ) +
  scale_x_continuous(breaks = seq(0, 2, by = 0.4), labels = number_format(accuracy = 0.1, suffix = " bbl")) +
  scale_y_continuous(
    labels = scales::percent_format(accuracy = 1),
    limits = c(0, 1), 
    expand = expansion(mult = c(0, 0.05))
  ) +
  
  labs(
    title = "Gráfica No4 : Distribución porcentual global de Liberación involuntaria", 
    x = "Volumen (bbl)",
    y = "Porcentaje (%)"
  ) +
  
  theme_classic() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    axis.text.x = element_text(hjust = 0.5)
  )

print(p_zoom_5barras_100)

6.5 Ojivas convinadas

La ojiva combinada representa la suma acumulativa de los barriles derramados a través de los diferentes rangos. Es una herramienta de diagnóstico poderosa para identificar el “punto de quiebre” donde la acumulación de pequeños incidentes iguala o supera el impacto de los grandes eventos.

library(ggplot2)
library(dplyr)
library(scales)
datos <- read.csv("database-_1_.csv")
variable_interes <- datos$Unintentional.Release..Barrels.
volumen <- na.omit(variable_interes)
datos_local <- volumen[volumen <= 2]
k_local <- 6
min_val <- 0
max_val <- 2
R_local <- max_val - min_val
A_local <- R_local / k_local 
Li_num <- seq(min_val, max_val - A_local, length.out = k_local)
Ls_num <- Li_num + A_local
ni_local <- numeric(k_local)
for(i in 1:k_local){
  if(i == k_local){
    ni_local[i] <- sum(datos_local >= Li_num[i] & datos_local <= max_val)
  } else {
    ni_local[i] <- sum(datos_local >= Li_num[i] & datos_local < Ls_num[i])
  }
}

Niasc <- cumsum(ni_local)
Nidsc <- rev(cumsum(rev(ni_local)))
datos_asc <- data.frame(
  x = c(min_val, Ls_num),  
  y = c(0, Niasc),         
  Tipo = "Ascendente"
)

datos_dsc <- data.frame(
  x = c(Li_num, max_val),  
  y = c(Nidsc, 0),         
  Tipo = "Descendente"
)

datos_ojivas_plot <- rbind(datos_asc, datos_dsc)
p_ojiva_cruzada_solida <- ggplot(datos_ojivas_plot, aes(x = x, y = y, color = Tipo, linetype = Tipo)) +
  geom_line(linewidth = 0.8) +
  geom_point(size = 2) +
  
  scale_x_continuous(
    labels = scales::number_format(accuracy = 0.01, suffix = " bbl"),
    breaks = scales::pretty_breaks(n = 6)
  ) +
  scale_color_manual(values = c("Ascendente" = "black", "Descendente" = "blue")) +
  scale_linetype_manual(values = c("Ascendente" = "solid", "Descendente" = "solid")) +
  
  labs(
    title = "Gráfica 5: Distribución Acumulada Comparativa de Liberación involuntaria",
    x = "Volumen (bbl)",
    y = "Cantidad Acumulada",
    color = NULL,
    linetype = NULL
  ) +
  
  theme_bw() + 
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
    legend.position = c(0.85, 0.5),
    legend.background = element_rect(color = "black", fill = "white"),
    axis.text = element_text(color = "black")
  )

print(p_ojiva_cruzada_solida)

Esta gráfica presenta las Ojivas de Frecuencia Acumulada para la variable de Volumen (medido en barriles), mostrando cómo se distribuyen los datos a lo largo del rango de 0 a 2 bbl. La línea negra (Ascendente) indica la cantidad de observaciones que están por debajo de un volumen determinado (acumulación “menor que”), mientras que la línea azul (Descendente) muestra cuántas observaciones restan por encima de ese mismo valor (acumulación “mayor que”). El punto donde ambas curvas se cruzan es visualmente importante porque representa la mediana aproximada del conjunto de datos, dividiendo la muestra en dos partes iguales.

6.6 Diagrama de cajas

El diagrama de cajas es una de las herramientas más potentes de la estadística descriptiva para visualizar la distribución de los datos a través de sus cuartiles. A diferencia de las gráficas de barras, el boxplot permite observar no solo la frecuencia, sino también la variabilidad, el grado de asimetría y, fundamentalmente, la presencia de valores que se alejan del comportamiento normal del grupo.

library(ggplot2)
library(dplyr)
datos <- read.csv("database-_1_.csv")
variable_interes <- datos$Unintentional.Release..Barrels.
volumen <- na.omit(variable_interes)
variable_box <- volumen[volumen <= 2] # Filtro Local
par(mar = c(5, 2, 4, 2)) 
b <- boxplot(variable_box, 
        horizontal = TRUE, 
        col = "skyblue", 
        border = "gray30",         
        medcol = "red",            
        boxwex = 0.6,              
        outline = FALSE,           
        main = "Gráfica 6: Distribución de Volumen de Liberación involuntaria",
        xlab = "Volumen (bbl)",
        xaxt = "n",  
        yaxt = "n",  
        frame = FALSE 
)

limite_visible <- b$stats[5] 
puntos_eje <- pretty(c(0, limite_visible))             
axis(1, at = puntos_eje, labels = format(puntos_eje, nsmall = 2), col = "gray30", col.axis = "gray30")
grid(nx = NULL, ny = NA, col = "lightgray", lty = "dotted", lwd = 1)

Esta gráfica nos permite ver rápidamente dónde se concentran la mayoría de los datos y qué tan dispersos están. La caja azul representa el núcleo de la información (el 50% central de los casos), indicando que la mayoría de los volúmenes habituales oscilan entre 0.25 y 1.00 bbl.La línea roja dentro de la caja marca la mediana (aprox. 0.50 bbl), que es el punto de equilibrio exacto: la mitad de los registros son menores a esa cifra y la otra mitad mayores. Además, al ver que la línea punteada de la derecha es más larga que la de la izquierda, podemos concluir que existe una mayor dispersión en los volúmenes altos; es decir, los datos se ‘estiran’ más hacia los 2 barriles que hacia el 0.

7 Tabla estadística

Sirve como línea base para comparar si el volumen de derrames local es superior o inferior al promedio general del sistema.

library(e1071)
## Warning: package 'e1071' was built under R version 4.5.3
## 
## Adjuntando el paquete: 'e1071'
## The following object is masked from 'package:ggplot2':
## 
##     element
library(knitr)
datos <- read.csv("database-_1_.csv")
variable_analisis <- na.omit(datos$Unintentional.Release..Barrels.)
n <- length(variable_analisis)
k_global <- floor(1 + 3.322 * log10(n))
R <- max(variable_analisis) - min(variable_analisis)
A_global <- R / k_global
Li <- seq(min(variable_analisis), max(variable_analisis) - A_global, length.out = k_global)
if(max(Li) + A_global < max(variable_analisis)) { 
   Li <- c(Li, tail(Li, 1) + A_global) 
   k_global <- k_global + 1
}
Ls <- Li + A_global
MC <- (Li + Ls) / 2

ni <- numeric(length(MC))
for(i in 1:length(MC)){
  if(i == length(MC)) ni[i] <- sum(variable_analisis >= Li[i] & variable_analisis <= (max(variable_analisis) + 0.001))
  else ni[i] <- sum(variable_analisis >= Li[i] & variable_analisis < Ls[i])
}
media_agrupada <- sum(MC * ni) / sum(ni)
desviacion_estandar <- sd(variable_analisis)
error_estandar <- desviacion_estandar / sqrt(n)
margen_error <- 1.96 * error_estandar
ic_inferior <- media_agrupada - margen_error
ic_superior <- media_agrupada + margen_error
texto_media_intervalo <- paste0("[", format(round(ic_inferior, 2), big.mark=","), " - ", format(round(ic_superior, 2), big.mark=","), "]")
ri <- min(variable_analisis)
rs <- max(variable_analisis)
mediana <- median(variable_analisis)
t <- table(variable_analisis)
Mo <- as.numeric(names(t)[which.max(t)])
cv <- (desviacion_estandar / media_agrupada) * 100
As <- skewness(variable_analisis)
K <- kurtosis(variable_analisis)
Tabla_global <- data.frame(
  "Liberación involuntaria",
  paste(format(ri, nsmall=2), "bbl"),
  paste(format(rs, big.mark=","), "bbl"),
  texto_media_intervalo, 
  paste(format(round(mediana, 2), big.mark=","), "bbl"),
  paste(format(round(Mo, 2), big.mark=","), "bbl"),
  paste(format(round(desviacion_estandar, 2), big.mark=","), "bbl"),
  paste(round(cv, 2), "%"),
  round(As, 2),
  round(K, 2)
)

colnames(Tabla_global) <- c("Variable","Min","Max","Media (IC 95%)","Mediana","Moda","Desv. S","CV","As","K")
kable(Tabla_global, format = "markdown", caption = "Tabla 2: Indicadores Globales (con Intervalo de Confianza para la Media).")
Tabla 2: Indicadores Globales (con Intervalo de Confianza para la Media).
Variable Min Max Media (IC 95%) Mediana Moda Desv. S CV As K
Liberación involuntaria 0.00 bbl 30,565 bbl [1,341.27 - 1,442.75] 2 bbl 1 bbl 1,368.67 bbl 98.32 % 13.61 227.81

7.1 Valores Atípicos

Dada la naturaleza de la industria, el volumen de derrames suele presentar valores extremadamente altos que distorsionan los promedios. Esta sección utiliza diagramas de cajas para aislar estos eventos catastróficos.

variable_global <- na.omit(datos$Unintentional.Release..Barrels.)
stats_outliers_global <- boxplot.stats(variable_global)$out
num_outliers_global <- length(stats_outliers_global)
minimooutliers_global <- if(num_outliers_global > 0) min(stats_outliers_global) else NA
maximooutliers_global <- if(num_outliers_global > 0) max(stats_outliers_global) else NA

cat("\n--- Análisis de Outliers ---\n")
## 
## --- Análisis de Outliers ---
cat("Número de valores atípicos:", num_outliers_global, "\n")
## Número de valores atípicos: 497
cat("Mínimo Outlier:", if(!is.na(minimooutliers_global)) paste(format(minimooutliers_global, big.mark=","), "bbl") else "Ninguno", "\n")
## Mínimo Outlier: 50 bbl
cat("Máximo Outlier:", if(!is.na(maximooutliers_global)) paste(format(maximooutliers_global, big.mark=","), "bbl") else "Ninguno", "\n")
## Máximo Outlier: 30,565 bbl

8 Conclusión

La variable continua Liberación Involuntaria fluctúa entre 0.00 y 30,565 bbl, con valores que giran en torno a una mediana de 2 bbl, presentando una desviación estándar de 1,368.67 bbl y un comportamiento marcadamente heterogéneo (CV del 98.32%). Se identifican 497 valores atípicos que se presentan a partir de los 50 bbl; asimismo, la distribución muestra una asimetría fuertemente positiva (13.61) y una concentración leptocúrtica (227.81), lo cual indica que la gran mayoría de los incidentes registran volúmenes de derrame muy bajos, representando un comportamiento general beneficioso para el entorno y el control de la infraestructura petrolera, a pesar de la ocurrencia de eventos catastróficos puntuales de gran magnitud.