1 Cargar Libreria

La carga de librerias es muy importante para las gráficas

library(knitr)
library(kableExtra)
library(dplyr)
## 
## Adjuntando el paquete: 'dplyr'
## The following object is masked from 'package:kableExtra':
## 
##     group_rows
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)

2 Cargar datos

Se inicia el proceso mediante la importación del conjunto de datos principal (database-1.csv), asegurando la integridad de la información y la correcta asignación de variables clave, como las categorías de las causas que originan los derrames.

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

Esta etapa es fundamental para establecer la base del estudio, permitiendo la limpieza de registros inconsistentes y la verificación del tamaño muestral necesario para garantizar la validez de las conclusiones posteriores.

zona <- datos$`Cause Category`

4 Conteo

En esta fase se realiza el cálculo de las frecuencias absolutas de la variable extraída. Este procedimiento estadístico agrupa los registros para determinar la ocurrencia y el nivel de incidencia de cada tipo de falla (como corrosión, errores operativos o fallos de equipo). Esto permite consolidar los datos crudos en valores numéricos interpretables que servirán de base para el análisis estructurado.

conteo_zona <- table(zona)
print(conteo_zona)
## zona
##            ALL OTHER CAUSES                   CORROSION 
##                         118                         592 
##           EXCAVATION DAMAGE         INCORRECT OPERATION 
##                          97                         378 
## MATERIAL/WELD/EQUIP FAILURE        NATURAL FORCE DAMAGE 
##                        1435                         118 
##  OTHER OUTSIDE FORCE DAMAGE 
##                          57

5 Tabla de Frecuencia

A continuación, se presenta el procesamiento de datos para la variable Cause.Category. Se detalla el código utilizado en R para la importación del archivo CSV y la posterior generación de la tabla de frecuencias, con el fin de analizar la incidencia de cada categoría.

library(dplyr)
library(knitr)
library(kableExtra)

orden_categorias <- c("Corrosión", "Falla del Equipo", "Operación Incorrecta", 
                      "Daño por Excavación",  "Causas menores", "Fuerzas Naturales", "Fuerzas Externas")

TDF_causa <- datos %>%
  mutate(Cause.Category = case_when(
    `Cause Category` == "CORROSION" ~ "Corrosión",
    `Cause Category` == "MATERIAL/WELD/EQUIP FAILURE" ~ "Falla del Equipo",
    `Cause Category` == "INCORRECT OPERATION" ~ "Operación Incorrecta",
    `Cause Category` == "EXCAVATION DAMAGE" ~ "Daño por Excavación",
    `Cause Category` == "NATURAL FORCE DAMAGE" ~ "Fuerzas Naturales",
    `Cause Category` == "OTHER OUTSIDE FORCE DAMAGE" ~ "Fuerzas Externas",
    `Cause Category` == "ALL OTHER CAUSES" ~ "Causas menores",
    TRUE ~ as.character(`Cause Category`) 
  )) %>%
  # 2. Convertimos el texto a Factor usando tu orden
  mutate(Cause.Category = factor(Cause.Category, levels = orden_categorias)) %>%
  count(Cause.Category, name = "ni") %>%        
  arrange(Cause.Category) 

# Cálculos de frecuencias relativas exactas
TDF_causa$hi_exacto <- (TDF_causa$ni / sum(TDF_causa$ni)) * 100
TDF_causa$DECIMAL_exacto <- TDF_causa$hi_exacto / 100 

# Redondeo
TDF_causa$hi <- round(TDF_causa$hi_exacto, 2)
TDF_causa$DECIMAL <- round(TDF_causa$DECIMAL_exacto, 3) 

# Ajuste de diferencias por redondeo al valor máximo
dif_hi <- 100 - sum(TDF_causa$hi)
dif_dec <- 1 - sum(TDF_causa$DECIMAL)

idx_max <- which.max(TDF_causa$ni)
TDF_causa$hi[idx_max] <- TDF_causa$hi[idx_max] + dif_hi
TDF_causa$DECIMAL[idx_max] <- TDF_causa$DECIMAL[idx_max] + dif_dec

# Creación de la fila de Total
Sumatoria <- data.frame(
  Cause.Category = "Total",
  ni = sum(TDF_causa$ni),
  hi = sum(TDF_causa$hi),
  DECIMAL = sum(TDF_causa$DECIMAL)
)

# Unión de la tabla y formateo de nombres
TDF_final <- rbind(TDF_causa[, c("Cause.Category", "ni", "hi", "DECIMAL")], Sumatoria)
colnames(TDF_final) <- c("Categoría de causa", "ni", "hi (%)", "fi") 

# Renderizado de la tabla con kableExtra
titulo_formal <- "CUADRO N°1 <br/> Distribución de frecuencias de accidentes según la categoría de causa en Estados Unidos, [2010 - 2016]"

kable(TDF_final, 
      align = 'cccc', # Corregido a 4 columnas 
      caption = titulo_formal, escape = FALSE,
      digits = c(0, 0, 2, 3)) %>% 
  kable_styling(full_width = FALSE, position = "center", 
                bootstrap_options = c("striped", "hover", "condensed", "bordered")) %>%
  add_header_above(c(" " = 2, "Frecuencia relativa" = 2), bold = TRUE, background = "#D5D8DC") %>%
  row_spec(0, bold = TRUE) %>%
  row_spec(nrow(TDF_final), bold = TRUE, background = "#f2f2f2")
CUADRO N°1
Distribución de frecuencias de accidentes según la categoría de causa en Estados Unidos, [2010 - 2016]
Frecuencia relativa
Categoría de causa ni hi (%) fi
Corrosión 592 21.18 0.212
Falla del Equipo 1435 51.35 0.514
Operación Incorrecta 378 13.52 0.135
Daño por Excavación 97 3.47 0.035
Causas menores 118 4.22 0.042
Fuerzas Naturales 118 4.22 0.042
Fuerzas Externas 57 2.04 0.020
Total 2795 100.00 1.000

6 Gráficas

6.1 Cantidad absoluta de accidentes por categoría de causa

Se presenta un histograma de frecuencias para la variable de categorías de causas. La distribución es notablemente asimétrica a la derecha, concentrando la mayor parte de la siniestralidad en problemas técnicos y de materiales (Equipo y Corrosión). Esta visualización permite identificar rápidamente las áreas críticas que requieren mayor atención o mantenimiento preventivo para reducir el número total de accidentes.

library(ggplot2)
library(dplyr)

orden_final <- c("Corrosión", "Falla del Equipo", "Operación Incorrecta", "Daño por Excavación","Causas menores","Fuerzas Naturales", "Fuerzas Externas")

datos_causa <- datos %>%

  mutate(Cause.Category = `Cause Category`) %>%
  mutate(Cause.Category = case_when(
    Cause.Category == "CORROSION" ~ "Corrosión",
    Cause.Category == "MATERIAL/WELD/EQUIP FAILURE" ~ "Falla del Equipo",
    Cause.Category == "EXCAVATION DAMAGE" ~ "Daño por Excavación",
    Cause.Category == "INCORRECT OPERATION" ~ "Operación Incorrecta",
    Cause.Category == "NATURAL FORCE DAMAGE" ~ "Fuerzas Naturales",
    Cause.Category == "OTHER OUTSIDE FORCE DAMAGE" ~ "Fuerzas Externas",
    Cause.Category == "ALL OTHER CAUSES" ~ "Causas menores",
    TRUE ~ as.character(Cause.Category)
  )) %>%
  count(Cause.Category, name = "ni") %>%
  mutate(Cause.Category = factor(Cause.Category, levels = orden_final))

ggplot(datos_causa, aes(x = Cause.Category, y = ni)) +
  geom_bar(stat = "identity", fill = "skyblue", width = 0.7) +
  scale_y_continuous(limits = c(0, 2795), breaks = c(0, 1000, 2000, 2795)) +
  labs(
    title = "Gráfica 1: Distribución general de categoría de causa",
    x = "Causa del Accidente",
    y = "Cantidad"
  ) +
  theme_classic() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 10, color = "black"),
    plot.title = element_text(face = "bold", hjust = 0.5)
  )

6.2 Cantidad absoluta de accidentes por categoría de causa

Se observa que la tendencia local refleja fielmente el comportamiento del sistema general, manteniendo la jerarquía de las causas de manera proporcional.Los daños por excavación, causas menores, fuerzas naturales y fuerzas externas presentan los valores más bajos, manteniéndose todas por debajo de los 250 incidentes en la escala local.

library(ggplot2)
library(dplyr)

orden_final <- c("Corrosión", "Falla del Equipo", "Operación Incorrecta", "Daño por Excavación","Causas menores","Fuerzas Naturales", "Fuerzas Externas")

datos_causa <- datos %>%

  mutate(Cause.Category = `Cause Category`) %>%
  mutate(Cause.Category = case_when(
    Cause.Category == "CORROSION" ~ "Corrosión",
    Cause.Category == "MATERIAL/WELD/EQUIP FAILURE" ~ "Falla del Equipo",
    Cause.Category == "EXCAVATION DAMAGE" ~ "Daño por Excavación",
    Cause.Category == "INCORRECT OPERATION" ~ "Operación Incorrecta",
    Cause.Category == "NATURAL FORCE DAMAGE" ~ "Fuerzas Naturales",
    Cause.Category == "OTHER OUTSIDE FORCE DAMAGE" ~ "Fuerzas Externas",
    Cause.Category == "ALL OTHER CAUSES" ~ "Causas menores",
    TRUE ~ as.character(Cause.Category)
  )) %>%
  count(Cause.Category, name = "ni") %>%
  mutate(Cause.Category = factor(Cause.Category, levels = orden_final))

ggplot(datos_causa, aes(x = Cause.Category, y = ni)) +
  geom_bar(stat = "identity", fill = "skyblue", width = 0.7) +
  scale_y_continuous(limits = c(0, 1435), breaks = c(0, 500, 1000, 1435)) +
  labs(
    title = "Gráfica 2: Distribución local de categoría de causa",
    x = "Causa del Accidente",
    y = "Cantidad"
  ) +
  theme_classic() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 10, color = "black"),
    plot.title = element_text(face = "bold", hjust = 0.5)
  )

6.3 Cantidad Relativa de accidentes por categoría de causa

La presente gráfica permite visualizar el impacto porcentual de cada categoría sobre el total de incidentes registrados a nivel local. A diferencia de las gráficas de frecuencia absoluta, este análisis facilita la identificación de las prioridades estratégicas mediante una escala relativa.

library(dplyr)
library(ggplot2)

orden_final <- c("Corrosión", "Falla del Equipo", "Operación Incorrecta", 
                 "Daño por Excavación", "Causas menores", "Fuerzas Naturales", 
                 "Fuerzas Externas")

datos_causa <- datos %>%

  mutate(Cause.Category = `Cause Category`) %>%
  mutate(Cause.Category = case_when(
    Cause.Category == "CORROSION" ~ "Corrosión",
    Cause.Category == "MATERIAL/WELD/EQUIP FAILURE" ~ "Falla del Equipo",
    Cause.Category == "EXCAVATION DAMAGE" ~ "Daño por Excavación",
    Cause.Category == "INCORRECT OPERATION" ~ "Operación Incorrecta",
    Cause.Category == "NATURAL FORCE DAMAGE" ~ "Fuerzas Naturales",
    Cause.Category == "OTHER OUTSIDE FORCE DAMAGE" ~ "Fuerzas Externas",
    Cause.Category == "ALL OTHER CAUSES" ~ "Causas menores",
    TRUE ~ as.character(Cause.Category)
  )) %>%
  count(Cause.Category, name = "ni") %>%
  mutate(hi = (ni / sum(ni)) * 100) %>%
  mutate(Cause.Category = factor(Cause.Category, levels = orden_final))

ggplot(datos_causa, aes(x = Cause.Category, y = hi)) +
  geom_bar(stat = "identity", fill = "skyblue", width = 0.7) +
  scale_y_continuous(limits = c(0, 60), breaks = seq(0, 60, by = 10)) +
  labs(
    title = "Gráfica 3: Distribución relativa local de categoría de Causa",
    x = "Causa del Accidente",
    y = "Porcentaje (%)"
  ) +
  theme_classic() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 10, color = "black"),
    plot.title = element_text(face = "bold", hjust = 0.5)
  )

6.4 Cantidad Relativa de accidentes por categoría de causa

La similitud visual entre ambas gráficas confirma que la muestra local es un reflejo fiel del comportamiento global. Esto valida que cualquier estrategia de mitigación de riesgos diseñada para el total de la base de datos será altamente efectiva si se aplica localmente.

library(dplyr)
library(ggplot2)

orden_final <- c("Corrosión", "Falla del Equipo", "Operación Incorrecta", 
                 "Daño por Excavación", "Causas menores", "Fuerzas Naturales", 
                 "Fuerzas Externas")

datos_causa <- datos %>%
  mutate(Cause.Category = `Cause Category`) %>%
  mutate(Cause.Category = case_when(
    Cause.Category == "CORROSION" ~ "Corrosión",
    Cause.Category == "MATERIAL/WELD/EQUIP FAILURE" ~ "Falla del Equipo",
    Cause.Category == "EXCAVATION DAMAGE" ~ "Daño por Excavación",
    Cause.Category == "INCORRECT OPERATION" ~ "Operación Incorrecta",
    Cause.Category == "NATURAL FORCE DAMAGE" ~ "Fuerzas Naturales",
    Cause.Category == "OTHER OUTSIDE FORCE DAMAGE" ~ "Fuerzas Externas",
    Cause.Category == "ALL OTHER CAUSES" ~ "Causas menores",
    TRUE ~ as.character(Cause.Category)
  )) %>%
  count(Cause.Category, name = "ni") %>%
  mutate(hi = (ni / sum(ni)) * 100) %>%
  mutate(Cause.Category = factor(Cause.Category, levels = orden_final))

ggplot(datos_causa, aes(x = Cause.Category, y = hi)) +
  geom_bar(stat = "identity", fill = "skyblue", width = 0.7) +
  scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, by = 20)) +
  labs(
    title = "Gráfica 4: Distribución relativa general de categoría de Causa",
    x = "Causa del Accidente",
    y = "Porcentaje (%)"
  ) +
  theme_classic() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 10, color = "black"),
    plot.title = element_text(face = "bold", hjust = 0.5)
  )

6.5 Diagrama Circular

El diagrama circular ofrece una visión integral de la participación de cada causa en el total de accidentes registrados. Esta representación permite identificar de manera inmediata qué proporción del problema ocupa cada categoría.

library(dplyr)
library(ggplot2)

datos_pastel <- datos %>%

  mutate(Cause.Category = `Cause Category`) %>%
  mutate(Cause.Category = case_when(
    Cause.Category == "CORROSION" ~ "Corrosión",
    Cause.Category == "MATERIAL/WELD/EQUIP FAILURE" ~ "Falla del Equipo",
    Cause.Category == "EXCAVATION DAMAGE" ~ "Daño por Excavación",
    Cause.Category == "INCORRECT OPERATION" ~ "Operación Incorrecta",
    Cause.Category == "NATURAL FORCE DAMAGE" ~ "Fuerzas Naturales",
    Cause.Category == "OTHER OUTSIDE FORCE DAMAGE" ~ "Fuerzas Externas",
    Cause.Category == "ALL OTHER CAUSES" ~ "Causas menores",
    TRUE ~ as.character(Cause.Category)
  )) %>%
  count(Cause.Category, name = "ni") %>%
  mutate(prop = ni / sum(ni) * 100) %>%
  arrange(desc(Cause.Category)) %>%
  mutate(ypos = cumsum(prop) - 0.5 * prop)

ggplot(datos_pastel, aes(x = "", y = prop, fill = Cause.Category)) +
  geom_bar(stat = "identity", width = 1, color = "white") +
  coord_polar("y", start = 0) +
  theme_void() + 
  geom_text(aes(label = paste0(round(prop, 1), "%")), 
            position = position_stack(vjust = 0.5), 
            color = "black", size = 3) +
  labs(
    title = "Diagrama Circular: Causas de Accidentes",
    fill = "Causa del Accidente"
  ) +
  scale_fill_brewer(palette = "Blues") +
  theme(
    legend.position = "right", # Posición a la derecha
    legend.title = element_text(face = "bold"),
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14)
  )

7 Indicadores Estadíticos

Este indicador funciona como una conclusión técnica directa. Al señalar a la “Falla del Equipo” como el factor predominante, el reporte proporciona una base sólida para la toma de decisiones, sugiriendo que las acciones correctivas y de inversión deben enfocarse prioritariamente en la integridad y mantenimiento de los componentes físicos.

# Cargar la librería knitr (solo es necesario una vez en todo el documento)
library(knitr)

# Tu código de limpieza y cálculo
datos_espanol <- datos %>%
  mutate(Cause.Category = `Cause Category`) %>%
  mutate(Cause.Category = case_when(
    Cause.Category == "CORROSION" ~ "Corrosión",
    Cause.Category == "MATERIAL/WELD/EQUIP FAILURE" ~ "Falla del Equipo",
    Cause.Category == "EXCAVATION DAMAGE" ~ "Daño por Excavación",
    Cause.Category == "INCORRECT OPERATION" ~ "Operación Incorrecta",
    Cause.Category == "NATURAL FORCE DAMAGE" ~ "Fuerzas Naturales",
    Cause.Category == "OTHER OUTSIDE FORCE DAMAGE" ~ "Fuerzas Externas",
    Cause.Category == "ALL OTHER CAUSES" ~ "Causas menores",
    TRUE ~ as.character(Cause.Category)
  ))

tabla_causas <- table(na.omit(datos_espanol$Cause.Category))

causa_top <- names(tabla_causas)[which.max(tabla_causas)]
cantidad_top <- max(tabla_causas)
total_eventos <- sum(tabla_causas)
porcentaje_top <- round((cantidad_top / total_eventos) * 100, 2)

# 1. Crear el Data Frame con la estructura de la imagen
tabla_indicadores_causas <- data.frame(
  Variable = "Categoría de Causa", 
  Media = "N/A",
  Mediana = "N/A",
  Moda = causa_top 
)

# 2. Generar la tabla con formato para el reporte
kable(tabla_indicadores_causas, 
      caption = "Tabla 7: Indicadores Estadísticos de la Categoría de Causa", 
      align = c("l", "c", "c", "c"))
Tabla 7: Indicadores Estadísticos de la Categoría de Causa
Variable Media Mediana Moda
Categoría de Causa N/A N/A Falla del Equipo

8 Conclusión

La variable cualitativa nominal Categoría de causa tiene como valor más frecuente el estado ‘Falla del Equipo’ (moda), abarcando el 51.34% de los registros de Categoría de causa.