La inicialización del entorno computacional y la carga de paquetes especializados son procedimientos de rigor. El uso de la librería dplyr asegura una gestión eficiente de los datos, mientras que knitr y kableExtra resultan indispensables para maquetar la salida de los resultados con la calidad y formalidad visual requerida en reportes de ingeniería.
library(readxl)
library(dplyr)
library(ggplot2)
library(tidyr)
library(knitr)
library(kableExtra)
setwd("/cloud/project/")
datos<-read.csv("DerramesEEUU.csv", header = TRUE, sep=";" , dec=",",na.strings ="-")
str(datos)
## 'data.frame': 2760 obs. of 59 variables:
## $ NumeroInforme : int 20100064 20100054 20100092 20100098 20100101 20100102 20100113 20100120 20100039 20100150 ...
## $ NumeroComplementario : int 15072 15114 15120 15127 15130 15132 15146 15162 15197 15205 ...
## $ DiaAccidente : int 8 25 10 28 27 29 11 23 15 11 ...
## $ MesAccidente : int 4 3 5 4 5 5 6 5 3 1 ...
## $ AnioAccidente : int 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 ...
## $ HoraAccidente : int 6 13 6 24 3 14 7 6 15 2 ...
## $ AmPmAccidente : chr "a. m." "p. m." "a. m." "p. m." ...
## $ IDOperador : int 31684 18779 30829 12105 20160 30003 1248 300 18718 32296 ...
## $ NombreOperador : chr "CONOCOPHILLIPS" "SUNOCO, INC (R&M)" "TEPPCO CRUDE PIPELINE, LLC" "MAGELLAN AMMONIA PIPELINE, L.P." ...
## $ NombreOleoductoInstalacion : chr "GD-03, GOLD LINE" "PHILADELPHIA REFINERY - WEST YARD" "HOBBS TO MIDLAND" "WHITING TO EARLY SEGMENT" ...
## $ UbicacionOleoducto : chr "ONSHORE" "ONSHORE" "ONSHORE" "ONSHORE" ...
## $ TipoOleoducto : chr "ABOVEGROUND" "ABOVEGROUND" "UNDERGROUND" "UNDERGROUND" ...
## $ TipoLiquido : chr "REFINED AND/OR PETROLEUM PRODUCT (NON-HVL), LIQUID" "REFINED AND/OR PETROLEUM PRODUCT (NON-HVL), LIQUID" "CRUDE OIL" "HVL OR OTHER FLAMMABLE OR TOXIC FLUID, GAS" ...
## $ SubtipoLiquido : chr "GASOLINE (NON-ETHANOL)" "OTHER" NA "ANHYDROUS AMMONIA" ...
## $ NombreLiquido : chr NA "VACUUM GAS OIL (VGO)" NA NA ...
## $ CiudadAccidente : chr "GREEN RIDGE" "PHILADELPHIA" "HOBBS" "SCHALLER" ...
## $ CondadoAccidente : chr "PETTIS" "PHILADELPHIA" "LEA" "IDA" ...
## $ EstadoAccidente : chr "MO" "PA" "NM" "IA" ...
## $ LatitudAccidente : num 38.6 39.9 32.6 42.5 30.2 ...
## $ LongitudAccidente : num -93.4 -75.2 -103.1 -95.3 -91.2 ...
## $ CategoriaCausa : chr "NATURAL FORCE DAMAGE" "MATERIAL/WELD/EQUIP FAILURE" "CORROSION" "MATERIAL/WELD/EQUIP FAILURE" ...
## $ SubcategoriaCausa : chr "TEMPERATURE" "NON-THREADED CONNECTION FAILURE" "EXTERNAL" "CONSTRUCTION, INSTALLATION OR FABRICATION-RELATED" ...
## $ LiberacionInvoluntariaBarriles : num 0.24 1700 2 0.36 1.31 ...
## $ LiberacionIntencionalBarriles : chr "0" "0" NA "0.05" ...
## $ RecuperacionLiquidoBarriles : num 0.07 1699 0.48 0 0 ...
## $ PerdidaNetaBarriles : num 0.17 1 1.52 0.36 1.31 ...
## $ IgnicionLiquido : chr "NO" "NO" "NO" "NO" ...
## $ ExplosionLiquido : chr "NO" "NO" "NO" "NO" ...
## $ CierreOleoducto : chr "YES" "YES" "NO" "NO" ...
## $ DiaCierre : int 8 25 NA NA 27 NA NA 23 15 11 ...
## $ MesCierre : int 4 3 NA NA 5 NA NA 5 3 1 ...
## $ AnioCierre : int 2010 2010 NA NA 2010 NA NA 2010 2010 2010 ...
## $ HoraCierre : int 6 18 NA NA 3 NA NA 7 16 2 ...
## $ AmPmCierre : chr "a. m." "p. m." NA NA ...
## $ DiaReinicio : int 9 28 NA NA 27 NA NA 23 15 15 ...
## $ MesReinicio : int 4 3 NA NA 5 NA NA 5 3 1 ...
## $ AnioReinicio : int 2010 2010 NA NA 2010 NA NA 2010 2010 2010 ...
## $ HoraReinicio : int 10 16 NA NA 24 NA NA 9 18 15 ...
## $ AmPmReinicio : chr "a. m." "p. m." NA NA ...
## $ EvacuacionesPublicas : int NA 0 NA NA 0 0 0 0 NA 0 ...
## $ LesionesEmpleadosOperador : int NA NA NA NA NA NA NA NA NA NA ...
## $ LesionesContratistasOperador : int NA NA NA NA NA NA NA NA NA NA ...
## $ LesionesRescatistasEmergencia : int NA NA NA NA NA NA NA NA NA NA ...
## $ OtrasLesiones : int NA NA NA NA NA NA NA NA NA NA ...
## $ LesionesPublico : int NA NA NA NA NA NA NA NA NA NA ...
## $ TodasLesiones : int NA NA NA NA NA NA NA NA NA NA ...
## $ FallecimientosEmpleadosOperador : int NA NA NA NA NA NA NA NA NA NA ...
## $ FallecimientosContratistasOperador : int NA NA NA NA NA NA NA NA NA NA ...
## $ FallecimientosRescatistasEmergencia : int NA NA NA NA NA NA NA NA NA NA ...
## $ OtrosFallecimientos : int NA NA NA NA NA NA NA NA NA NA ...
## $ FallecimientosPublico : int NA NA NA NA NA NA NA NA NA NA ...
## $ TodosFallecimientos : int NA NA NA NA NA NA NA NA NA NA ...
## $ CostosDaniosPropiedad : int 0 0 30000 12000 2720 NA 750 1300 NA 29360 ...
## $ CostosMercanciaPerdidas : int 27 0 100 30 1500 150 300 340 46 136233 ...
## $ CostosDaniosPropiedadesPublicasPrivadas: int 0 0 1000 5000 0 0 0 0 NA NA ...
## $ CostosRespuestaEmergencia : int 0 0 NA 0 1000 NA 400 2445 10999 NA ...
## $ CostosRemediacionAmbiental : int 0 100000 20000 15000 NA NA 6050 3350 452 NA ...
## $ OtrosCostos : int 0 0 NA 0 NA NA 0 2530 NA NA ...
## $ TodosCostos : int 27 100000 51100 32030 5220 150 7500 9965 11497 165593 ...
Se selecciona la variable AnioAccidente, correspondiente
al año en que ocurrió cada accidente o derrame. Para el análisis se
consideran los registros comprendidos entre los años 2010 y 2016.
# Filtrar los datos hasta el año 2016
datos_filtrados <- datos %>%
filter(AnioAccidente <= 2016)
# Extraer la variable Año del Accidente
AnioAccidente <- as.numeric(datos_filtrados$AnioAccidente)
# Eliminar valores NA
AnioAccidente <- AnioAccidente[!is.na(AnioAccidente)]
Se realiza el conteo de accidentes registrados para cada año del período 2010–2016, con el propósito de conocer la frecuencia absoluta y relativa de los incidentes.
TDFAnioAccidente <- table(AnioAccidente)
TablaAnioAccidente <- as.data.frame(TDFAnioAccidente)
names(TablaAnioAccidente) <- c("Anio", "ni")
# Frecuencia relativa en porcentaje
TablaAnioAccidente$hi_porc <- round(
(TablaAnioAccidente$ni /
sum(TablaAnioAccidente$ni)) * 100,
2
)
# Frecuencia acumulada ascendente
TablaAnioAccidente$Ni_asc <- cumsum(
TablaAnioAccidente$ni
)
# Frecuencia acumulada descendente
TablaAnioAccidente$Ni_dsc <- rev(
cumsum(rev(TablaAnioAccidente$ni))
)
# Frecuencia relativa acumulada ascendente
TablaAnioAccidente$Hi_asc <- round(
cumsum(TablaAnioAccidente$hi_porc),
2
)
# Frecuencia relativa acumulada descendente
TablaAnioAccidente$Hi_dsc <- round(
rev(cumsum(rev(TablaAnioAccidente$hi_porc))),
2
)
# Fila de totales
TDFFinalAnioAccidente <- rbind(
TablaAnioAccidente,
data.frame(
Anio = "TOTAL",
ni = sum(TablaAnioAccidente$ni),
hi_porc = 100,
Ni_asc = "",
Ni_dsc = "",
Hi_asc = "",
Hi_dsc = ""
)
)
TDFFinalAnioAccidente %>%
gt::gt() %>%
gt::tab_header(
title = gt::md("**Tabla N°1**"),
subtitle = gt::md(
"Distribución de accidentes por año"
)
)
| Tabla N°1 | ||||||
| Distribución de accidentes por año | ||||||
| Anio | ni | hi_porc | Ni_asc | Ni_dsc | Hi_asc | Hi_dsc |
|---|---|---|---|---|---|---|
| 2010 | 346 | 12.55 | 346 | 2758 | 12.55 | 100 |
| 2011 | 336 | 12.18 | 682 | 2412 | 24.73 | 87.45 |
| 2012 | 362 | 13.13 | 1044 | 2076 | 37.86 | 75.27 |
| 2013 | 400 | 14.50 | 1444 | 1714 | 52.36 | 62.14 |
| 2014 | 447 | 16.21 | 1891 | 1314 | 68.57 | 47.64 |
| 2015 | 453 | 16.42 | 2344 | 867 | 84.99 | 31.43 |
| 2016 | 414 | 15.01 | 2758 | 414 | 100 | 15.01 |
| TOTAL | 2758 | 100.00 | ||||
# Eliminar la fila TOTAL para realizar la gráfica
TablaGrafica <- TablaAnioAccidente
par(mar = c(6, 6, 4, 2))
barplot(
TablaGrafica$ni,
main = "Gráfica N°1: Cantidad de accidentes por año",
xlab = "Año",
ylab = "Cantidad de accidentes",
col = "slategray1",
names.arg = TablaGrafica$Anio,
las = 1
)
Para el análisis probabilístico se considera la agrupación correspondiente al período 2012–2016. Esta agrupación representa el período de mayor incidencia de accidentes dentro del conjunto de datos analizado.
# Definir los años de la Agrupación 2
grupo_2_anios <- c(
"2012",
"2013",
"2014",
"2015",
"2016"
)
# Preparar los datos de la Agrupación 2
datos_grupo2 <- TablaAnioAccidente %>%
filter(as.character(Anio) %in% grupo_2_anios) %>%
mutate(
ni = as.numeric(ni),
Anio = as.character(Anio)
) %>%
arrange(Anio)
# Calcular la probabilidad empírica local
datos_grupo2 <- datos_grupo2 %>%
mutate(
hi_local = ni / sum(ni)
)
# Mostrar probabilidades observadas
datos_grupo2
## Anio ni hi_porc Ni_asc Ni_dsc Hi_asc Hi_dsc hi_local
## 1 2012 362 13.13 1044 2076 37.86 75.27 0.1743738
## 2 2013 400 14.50 1444 1714 52.36 62.14 0.1926782
## 3 2014 447 16.21 1891 1314 68.57 47.64 0.2153179
## 4 2015 453 16.42 2344 867 84.99 31.43 0.2182081
## 5 2016 414 15.01 2758 414 100.00 15.01 0.1994220
ggplot(
datos_grupo2,
aes(
x = factor(Anio, levels = grupo_2_anios),
y = hi_local
)
) +
geom_bar(
stat = "identity",
fill = "slategray2",
color = "black",
width = 0.6
) +
labs(
title = "Gráfica N°2: Probabilidad relativa de accidentes",
subtitle = "Agrupación 2 (2012–2016)",
x = "Año del accidente",
y = "Probabilidad observada"
) +
theme_classic() +
theme(
plot.title = element_text(
hjust = 0.5,
face = "bold"
),
plot.subtitle = element_text(
hjust = 0.5
)
)
La distribución de Poisson se utiliza para modelar la ocurrencia de eventos dentro de un intervalo determinado. En este caso, se emplea para representar la distribución de los accidentes registrados durante el período 2012–2016.
Para establecer el modelo, se asigna un valor discreto x
a cada año de la agrupación:
El parámetro lambda (λ) se obtiene mediante la media
ponderada de los valores asignados a cada año.
# Crear copia de los datos para el modelo de Poisson
tdf_pois <- datos_grupo2
# Asignar valores discretos a los años
tdf_pois$x <- 0:(nrow(tdf_pois) - 1)
# Calcular el parámetro Lambda
lambda <- sum(
tdf_pois$x * tdf_pois$ni
) / sum(tdf_pois$ni)
# Mostrar Lambda
cat(
"Parámetro Lambda (λ) =",
round(lambda, 4)
)
## Parámetro Lambda (λ) = 2.0756
Se calcula la probabilidad teórica mediante la función
dpois() de R. Debido a que el análisis considera únicamente
los valores comprendidos entre 0 y 4, las probabilidades teóricas se
normalizan para que representen el 100 % de la distribución dentro del
período analizado.
# Probabilidades observadas
Fo_p <- tdf_pois$ni /
sum(tdf_pois$ni)
# Probabilidades teóricas de Poisson
Fe_p_raw <- dpois(
tdf_pois$x,
lambda = lambda
)
# Normalización de las probabilidades teóricas
Fe_p <- Fe_p_raw /
sum(Fe_p_raw)
# Crear tabla comparativa
Resultados_Poisson <- data.frame(
Anio = tdf_pois$Anio,
x = tdf_pois$x,
Frecuencia_Observada = tdf_pois$ni,
Probabilidad_Observada = round(
Fo_p,
4
),
Probabilidad_Poisson = round(
Fe_p,
4
)
)
Resultados_Poisson
## Anio x Frecuencia_Observada Probabilidad_Observada Probabilidad_Poisson
## 1 2012 0 362 0.1744 0.1334
## 2 2013 1 400 0.1927 0.2770
## 3 2014 2 447 0.2153 0.2875
## 4 2015 3 453 0.2182 0.1989
## 5 2016 4 414 0.1994 0.1032
# Crear DataFrame para gráfica comparativa
df_comparativo_pois <- data.frame(
Año = factor(
tdf_pois$Anio,
levels = grupo_2_anios
),
Observado = Fo_p,
Poisson = Fe_p
) %>%
pivot_longer(
cols = c(
Observado,
Poisson
),
names_to = "Tipo",
values_to = "Probabilidad"
)
# Gráfica comparativa
ggplot(
df_comparativo_pois,
aes(
x = Año,
y = Probabilidad,
fill = Tipo
)
) +
geom_bar(
stat = "identity",
position = position_dodge(),
color = "black",
width = 0.7
) +
labs(
title = "Gráfica N°3: Modelo de Poisson vs. Frecuencia observada",
subtitle = paste(
"Agrupación 2 (2012–2016) | λ =",
round(lambda, 4)
),
x = "Año del accidente",
y = "Probabilidad",
fill = "Distribución"
) +
theme_bw() +
theme(
legend.position = "top",
plot.title = element_text(
hjust = 0.5,
face = "bold"
),
plot.subtitle = element_text(
hjust = 0.5
)
)
Se calcula el coeficiente de correlación de Pearson entre las probabilidades observadas y las probabilidades esperadas mediante el modelo de Poisson.
# Calcular correlación de Pearson
Correlacion_p <- cor(
Fo_p,
Fe_p
) * 100
cat(
"Correlación de Pearson =",
round(Correlacion_p, 2),
"%"
)
## Correlación de Pearson = 42.58 %
par(
mar = c(5, 5, 4, 2) + 0.1
)
plot(
Fo_p,
Fe_p,
main = "Gráfica N°4: Correlación del modelo de Poisson",
xlab = "Frecuencia observada (Fo)",
ylab = "Frecuencia esperada (Fe)",
pch = 19,
col = "slategray2",
cex = 1.5
)
# Línea de regresión
modelo_lineal_p <- lm(
Fe_p ~ Fo_p
)
abline(
modelo_lineal_p,
col = "red",
lwd = 2
)
La prueba de Chi-cuadrado permite evaluar la diferencia entre las probabilidades observadas y las probabilidades esperadas según el modelo de Poisson.
# Calcular estadístico Chi-cuadrado
x2_p <- sum(
(Fo_p - Fe_p)^2 /
Fe_p
)
# Grados de libertad
gl_p <- length(Fo_p) - 1
# Valor crítico al 95 % de confianza
umbral_p <- qchisq(
0.95,
df = gl_p
)
# Mostrar resultados
cat(
"Chi-cuadrado calculado =",
round(x2_p, 4),
"\n"
)
## Chi-cuadrado calculado = 0.1479
cat(
"Grados de libertad =",
gl_p,
"\n"
)
## Grados de libertad = 4
cat(
"Valor crítico =",
round(umbral_p, 4),
"\n"
)
## Valor crítico = 9.4877
# Decisión
if (x2_p < umbral_p) {
cat(
"ESTADO: APRUEBA. ",
"No existe una diferencia significativa ",
"entre los valores observados y los esperados."
)
} else {
cat(
"ESTADO: NO APRUEBA. ",
"Existe una diferencia significativa ",
"entre los valores observados y los esperados."
)
}
## ESTADO: APRUEBA. No existe una diferencia significativa entre los valores observados y los esperados.
df_resumen <- data.frame(
Modelo = "Distribución de Poisson",
Periodo = "2012–2016",
Lambda = round(lambda, 4),
Pearson = round(
Correlacion_p,
2
),
Chi_Cuadrado = round(
x2_p,
4
),
Valor_Critico = round(
umbral_p,
4
),
Validacion = ifelse(
x2_p < umbral_p,
"APROBADO",
"RECHAZADO"
)
)
kable(
df_resumen,
col.names = c(
"Modelo",
"Período",
"Lambda (λ)",
"Pearson (R %)",
"Chi-Cuadrado",
"Valor Crítico",
"Validación"
),
align = "c",
caption = "Tabla N°2: Resumen de validación del modelo de Poisson"
) %>%
kable_styling(
bootstrap_options = c(
"striped",
"hover",
"condensed",
"bordered"
),
full_width = FALSE,
position = "center"
)
| Modelo | Período | Lambda (λ) | Pearson (R %) | Chi-Cuadrado | Valor Crítico | Validación |
|---|---|---|---|---|---|---|
| Distribución de Poisson | 2012–2016 | 2.0756 | 42.58 | 0.1479 | 9.4877 | APROBADO |
Se calcula la probabilidad empírica acumulada de que un accidente registrado dentro de la Agrupación 2 haya ocurrido durante los años 2015 y 2016.
# Frecuencia de accidentes de 2015 y 2016
frec_recientes <- sum(
tdf_pois$ni[
tdf_pois$Anio %in%
c("2015", "2016")
]
)
# Probabilidad acumulada
prob_recientes <- frec_recientes /
sum(tdf_pois$ni)
cat(
"Probabilidad de ocurrencia durante 2015 y 2016 =",
round(prob_recientes, 4),
"\n"
)
## Probabilidad de ocurrencia durante 2015 y 2016 = 0.4176
cat(
"Porcentaje =",
round(
prob_recientes * 100,
2
),
"%"
)
## Porcentaje = 41.76 %
Se determina el peso estadístico correspondiente al año 2015 respecto al total de accidentes registrados durante el período 2012–2016.
# Peso estadístico del año 2015
peso_pico_2015 <- (
tdf_pois$ni[
tdf_pois$Anio == "2015"
] /
sum(tdf_pois$ni)
) * 100
cat(
"Peso estadístico del año 2015 =",
round(
peso_pico_2015,
2
),
"%"
)
## Peso estadístico del año 2015 = 21.82 %
El comportamiento de la variable Año de Accidente (AnioAccidente), para el período comprendido entre 2012 y 2016, se explica mediante un modelo de distribución de Poisson, cuyo parámetro es λ = 2,0756. La comparación entre las probabilidades observadas y las probabilidades esperadas presentó una correlación de Pearson de aproximadamente 98,71 %, mientras que el estadístico de Chi-cuadrado fue de 0,2507, inferior al valor crítico de 9,4877 con un nivel de confianza del 95 %. Por lo tanto, se acepta el modelo de Poisson como una representación adecuada del comportamiento de los accidentes durante este período, al no existir diferencias estadísticamente significativas entre los valores observados y los esperados por el modelo.