La preparación del entorno computacional y la habilitación de
paquetes específicos son esenciales para la sistematización del trabajo.
El uso de dplyr asegura un procesamiento ordenado de la
matriz, mientras que knitr y kableExtra son
requeridos para estructurar las métricas con el rigor y la calidad
visual que demanda un reporte de ingeniería.
library(htmltools)
library(gt)
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(e1071)
## Warning: package 'e1071' was built under R version 4.5.3
El primer paso crítico en cualquier análisis de datos es la importación correcta de la fuente de información. En esta sección, se utiliza la función read.csv() para cargar el archivo de datos externo al entorno de trabajo de R. Este proceso transforma los datos crudos en un “data frame”, permitiendo que el software reconozca las columnas y filas para su posterior manipulación.
database <- read.csv("database-_1_.csv", header = TRUE, sep = ",", dec = ".", check.names = FALSE)
raw_years <- database$`Accident Year`
raw_years <- raw_years[raw_years != ""]
raw_years <- na.omit(raw_years)
years_obj <- floor(as.numeric(as.character(raw_years)))
## Warning: NAs introducidos por coerción
years_num <- as.numeric(years_obj)
years_num <- na.omit(years_num)
years_obj <- years_obj[!is.na(years_num)]
valid_indices <- years_num > 1900 & years_num <= 2025
years_num <- years_num[valid_indices]
years_obj <- years_obj[valid_indices]
Para la evaluación cronológica de la infraestructura, se aísla la variable cuantitativa discreta correspondiente al año del accidente (Accident Year). Esta extracción metodológica es clave para analizar la dimensión temporal de los derrames, permitiendo trabajar estrictamente con los valores enteros que representan cada periodo anual.
zona <- database$`Accident Year`
Tratándose de datos numéricos discretos de carácter temporal, el cálculo de frecuencias absolutas agrupa la totalidad de los incidentes ocurridos en cada periodo. Esta tabulación matemática revela la evolución histórica de la accidentalidad en la red, entregando una base cuantitativa directa para identificar si las fallas tienen una tendencia al alza o a la baja a lo largo del tiempo.
# 1. Convertimos la variable 'zona' a formato numérico
zona_numerica <- as.numeric(as.character(zona))
## Warning: NAs introducidos por coerción
# 2. Ahora sí aplicamos la función trunc() y creamos la tabla
conteo_zona <- table(trunc(zona_numerica))
# 3. Imprimimos el resultado
print(conteo_zona)
##
## 2010 2011 2012 2013 2014 2015 2016
## 350 345 366 401 454 576 301
Una vez cargados los datos, el siguiente paso es la organización mediante tablas de frecuencia. Esta técnica estadística agrupa la información de una variable específica (como el año o la causa del accidente) para contar cuántas veces ocurre cada evento.
#tabla de frecuencia
datos <- read.csv("database-_1_.csv", stringsAsFactors = FALSE)
anios_limpios <- floor(as.numeric(datos$Accident.Year))
## Warning: NAs introducidos por coerción
anios_limpios <- anios_limpios[!is.na(anios_limpios)]
tabla_base <- table(anios_limpios)
ni <- as.vector(tabla_base)
Magnitud <- names(tabla_base)
hi <- round(ni/sum(ni)*100, 2)
Ni_asc <- cumsum(ni)
Ni_dsc <- rev(cumsum(rev(ni)))
Hi_asc <- cumsum(hi)
Hi_dsc <- rev(cumsum(rev(hi)))
TDFMagnitudFin <- data.frame(Magnitud, ni, hi, Ni_asc, Ni_dsc, Hi_asc, Hi_dsc)
library(knitr)
kable(TDFMagnitudFin,
caption = "Tabla de Frecuencia de accidentes del año",
align = "c",
col.names = c("Año", "ni", "hi (%)", "Ni Asc", "Ni Dsc", "Hi Asc", "Hi Dsc"))
| Año | ni | hi (%) | Ni Asc | Ni Dsc | Hi Asc | Hi Dsc |
|---|---|---|---|---|---|---|
| 2010 | 350 | 12.53 | 350 | 2793 | 12.53 | 99.99 |
| 2011 | 345 | 12.35 | 695 | 2443 | 24.88 | 87.46 |
| 2012 | 366 | 13.10 | 1061 | 2098 | 37.98 | 75.11 |
| 2013 | 401 | 14.36 | 1462 | 1732 | 52.34 | 62.01 |
| 2014 | 454 | 16.25 | 1916 | 1331 | 68.59 | 47.65 |
| 2015 | 576 | 20.62 | 2492 | 877 | 89.21 | 31.40 |
| 2016 | 301 | 10.78 | 2793 | 301 | 99.99 | 10.78 |
Tras observar el comportamiento general, este apartado se enfoca en el análisis de una zona o segmento específico (distribución local). Esta comparación es vital para determinar si las tendencias de la región estudiada se mantienen alineadas con los promedios globales o si presentan anomalías particulares que requieran una intervención diferenciada.
library(ggplot2)
##
## Adjuntando el paquete: 'ggplot2'
## The following object is masked from 'package:e1071':
##
## element
TDFMagnitudFin$Magnitud <- as.numeric(as.character(TDFMagnitudFin$Magnitud))
p_global <- ggplot(TDFMagnitudFin, aes(x = Magnitud, weight = ni)) +
geom_bar(bins = 7, fill = "steelblue", color = "black", alpha = 0.8) +
scale_x_continuous(breaks = seq(min(TDFMagnitudFin$Magnitud), max(TDFMagnitudFin$Magnitud), by = 1)) +
scale_y_continuous(expand = expansion(mult = c(0, 0.1))) +
labs(title = "Gráfica No 1: Cantidad absoluta global de Accidentes Anuales",
x = "Año",
y = "Cantidad") +
theme_classic() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 13),
plot.subtitle = element_text(hjust = 0.5, color = "gray40"),
axis.text.x = element_text(angle = 45, hjust = 1, color = "black"),
axis.text.y = element_text(color = "black"),
axis.line = element_line(linewidth = 0.5, color = "black")
)
## Warning in geom_bar(bins = 7, fill = "steelblue", color = "black", alpha =
## 0.8): Ignoring unknown parameters: `bins`
print(p_global)
El histograma de distribución de accidentes por intervalos de tiempo muestra la frecuencia de eventos ocurridos anualmente. Esta visualización es clave para detectar patrones cíclicos o años atípicos en los que la cantidad de accidentes se desvió significativamente del promedio histórico.
library(ggplot2)
TDFMagnitudFin$Magnitud <- as.numeric(as.character(TDFMagnitudFin$Magnitud))
max_ni <- max(TDFMagnitudFin$ni)
p_ni_local <- ggplot(TDFMagnitudFin, aes(x = Magnitud, weight = ni)) +
geom_bar(binwidth = 1, fill = "steelblue", color = "black", alpha = 0.8) +
scale_x_continuous(breaks = TDFMagnitudFin$Magnitud) +
scale_y_continuous(limits = c(0, max_ni * 1.05),
expand = expansion(mult = c(0, 0))) +
labs(title = "Gráfica No 2: Cantidad absoluta local de Accidentes Anuales",
x = "Año",
y = "Cantidad") +
theme_classic() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 13),
plot.subtitle = element_text(hjust = 0.5, color = "gray40"),
axis.text.x = element_text(angle = 45, hjust = 1, color = "black"),
axis.text.y = element_text(color = "black"),
axis.line = element_line(linewidth = 0.5, color = "black")
)
## Warning in geom_bar(binwidth = 1, fill = "steelblue", color = "black", alpha =
## 0.8): Ignoring unknown parameters: `binwidth`
print(p_ni_local)
Para validar la representatividad de la muestra local, se analiza aquí la incidencia porcentual a nivel global. Este enfoque permite normalizar los datos y comparar la participación de cada categoría de causa frente al universo total de accidentes registrados en el dataset.
library(ggplot2)
TDFMagnitudFin$Magnitud <- as.numeric(as.character(TDFMagnitudFin$Magnitud))
total_hi <- sum(TDFMagnitudFin$hi)
p_hi_global <- ggplot(TDFMagnitudFin, aes(x = Magnitud, weight = hi)) +
geom_bar(binwidth = 1, fill = "steelblue", color = "black", alpha = 0.8) +
scale_x_continuous(breaks = TDFMagnitudFin$Magnitud) +
scale_y_continuous(limits = c(0, max(TDFMagnitudFin$hi) * 1.2),
expand = expansion(mult = c(0, 0))) +
labs(title = "Gráfica No 3: Cantidad relativa global de Accidentes Anuales",
x = "Año",
y = "Porcentaje (%)") +
theme_classic() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
plot.subtitle = element_text(hjust = 0.5, color = "gray40"),
axis.text.x = element_text(angle = 45, hjust = 1, color = "black"),
axis.text.y = element_text(color = "black"),
axis.line = element_line(linewidth = 0.5, color = "black")
)
## Warning in geom_bar(binwidth = 1, fill = "steelblue", color = "black", alpha =
## 0.8): Ignoring unknown parameters: `binwidth`
print(p_hi_global)
Más allá de los números totales, es fundamental entender el peso porcentual de cada causa. En esta sección se transforman las frecuencias absolutas en valores relativos, facilitando la interpretación de la probabilidad de ocurrencia de cada tipo de accidente dentro del entorno local.
# Histogram_localhi_updated
library(ggplot2)
TDFMagnitudFin$Magnitud <- as.numeric(as.character(TDFMagnitudFin$Magnitud))
max_hi <- max(TDFMagnitudFin$hi)
p_hi_local <- ggplot(TDFMagnitudFin, aes(x = Magnitud, weight = hi)) +
geom_bar(binwidth = 1, fill = "steelblue", color = "black", alpha = 0.8) +
scale_x_continuous(breaks = TDFMagnitudFin$Magnitud) +
scale_y_continuous(limits = c(0, max_hi * 1.1),
expand = expansion(mult = c(0, 0))) +
labs(title = "Gráfica No 4: Cantidad relativa local de Accidentes Anuales",
x = "Año",
y = "Porcentaje (%)") +
theme_classic() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 13),
plot.subtitle = element_text(hjust = 0.5, color = "gray40"),
axis.text.x = element_text(angle = 45, hjust = 1, color = "black"),
axis.text.y = element_text(color = "black"),
axis.line = element_line(linewidth = 0.5, color = "black")
)
## Warning in geom_bar(binwidth = 1, fill = "steelblue", color = "black", alpha =
## 0.8): Ignoring unknown parameters: `binwidth`
print(p_hi_local)
La ojiva es una representación gráfica que permite observar cómo se acumulan los accidentes a medida que sumamos cada categoría de causa en el entorno local. A diferencia de las gráficas de barras tradicionales, la ojiva se enfoca en el crecimiento porcentual acumulado, facilitando la identificación del punto en el que se alcanza la mayoría de la siniestralidad.
library(ggplot2)
total_n <- max(TDFMagnitudFin$Ni_asc)
p_ojiva_ni <- ggplot(TDFMagnitudFin, aes(x = Magnitud)) +
geom_line(aes(y = Ni_asc, color = "Ni Ascendente"), linewidth = 1) +
geom_point(aes(y = Ni_asc, color = "Ni Ascendente"), size = 2.5) +
geom_line(aes(y = Ni_dsc, color = "Ni Descendente"), linewidth = 1) +
geom_point(aes(y = Ni_dsc, color = "Ni Descendente"), size = 2.5) +
scale_color_manual(name = "Tipo de Acumulado",
values = c("Ni Ascendente" = "steelblue",
"Ni Descendente" = "firebrick")) +
scale_x_continuous(breaks = TDFMagnitudFin$Magnitud) +
scale_y_continuous(limits = c(0, total_n * 1.05), # Un 5% extra arriba
expand = expansion(mult = c(0, 0))) +
labs(title = "Gráfica No 5: Comportamiento de la cantidad Acumulada de Accidentes.",
x = "Año",
y = "Cantidad Acumulada") +
theme_classic() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
plot.subtitle = element_text(hjust = 0.5, color = "gray40"),
axis.text.x = element_text(angle = 45, hjust = 1, color = "black"),
legend.position = "bottom", # Leyenda en la parte inferior
axis.line = element_line(linewidth = 0.5, color = "black")
)
print(p_ojiva_ni)
La Gráfica No. 5 muestra la acumulación absoluta de accidentes (\(N_i\)), donde la curva azul asciende progresivamente hasta alcanzar un total cercano a los 2800 eventos en 2016, mientras la roja desciende desde esa misma cifra. El cruce de ambas líneas, ocurrido poco después de 2013 y alrededor de los 1400 casos, marca visualmente la mediana, indicando el punto donde se registró la mitad del total de siniestros.
El diagrama de cajas es una herramienta estadística que resume la distribución de una variable numérica a través de sus cuartiles. En este reporte, se utiliza para analizar la variabilidad de los accidentes, permitiendo identificar visualmente la mediana, el rango intercuartílico y la presencia de valores extremos que se alejan del comportamiento normal de los datos.
library(ggplot2)
par(mar = c(5, 2, 4, 2))
boxplot(anios_limpios,
horizontal = TRUE,
col = "skyblue",
main = "Gráfica 7: Distribución de Años (Boxplot)",
xlab = "Año",
xaxt = "n",
outline = TRUE,
pch = 19,
outcol = "red")
axis(1,
at = sort(unique(anios_limpios)),
labels = sort(unique(anios_limpios)),
las = 2,
cex.axis = 0.8)
grid(nx = NULL, ny = NA, col = "lightgray", lty = "dotted")
Esta gráfica de caja muestra la distribución temporal de un conjunto de datos que abarca desde el año 2010 hasta el 2016. Se observa que el 50% central de la información (la caja azul) está concentrado entre los años 2012 y 2015, con una mediana situada exactamente en 2013 que divide la muestra en dos partes iguales. La longitud desigual de las secciones de la caja sugiere que los datos están más dispersos en los años recientes (entre 2013 y 2015) en comparación con el periodo inicial, indicando una variabilidad ligeramente mayor hacia el final del rango temporal analizado.
Más allá de las representaciones visuales, el rigor de una investigación de datos reside en sus indicadores numéricos. En esta sección se presentan las medidas de tendencia central y descriptivas calculadas directamente desde el dataset mediante R. El objetivo es proporcionar una conclusión objetiva que elimine cualquier ambigüedad interpretativa sobre los riesgos analizados.
library(e1071)
# 1. Rango (Mínimo y Máximo)
ri <- min(anios_limpios, na.rm = TRUE)
rs <- max(anios_limpios, na.rm = TRUE)
# 2. Mediana
mediana <- median(anios_limpios, na.rm = TRUE)
# 3. Media Aritmética
media_aritmetica <- mean(anios_limpios, na.rm = TRUE)
# 4. Moda (Calculada como el valor más frecuente)
t <- table(anios_limpios)
Mo <- as.numeric(names(t)[which.max(t)])
# 5. Desviación Estándar
# Aquí es directo, el resultado es en "años"
desviacion_estandar <- sd(anios_limpios, na.rm = TRUE)
# 6. Coeficiente de Variabilidad
coeficiente_variabilidad <- (desviacion_estandar / media_aritmetica) * 100
# 7. Asimetría (Skewness)
As <- skewness(anios_limpios, na.rm = TRUE)
# 8. Curtosis
curtosis_val <- kurtosis(anios_limpios, na.rm = TRUE)
Más allá de las representaciones gráficas, la tabla de indicadores proporciona los valores exactos que rigen el comportamiento de los datos. Esta sección presenta un resumen tabular donde se identifican las métricas clave de la variable analizada, permitiendo una lectura rápida y precisa de la realidad estadística del proyecto.
library(knitr)
# Preparamos los textos para la tabla
Variable <- "Año del accidente"
Tabla_indicadores <- data.frame(
Variable,
ri, # Mínimo
rs, # Máximo
round(media_aritmetica), # Media
mediana, # Mediana
Mo, # Moda
round(desviacion_estandar), # S (Desviación)
round(coeficiente_variabilidad, 2),
round(As, 2),
round(curtosis_val, 2)
)
colnames(Tabla_indicadores) <- c("Variable","Mínimo","Máximo","x","Me","Mo","S (años)","Cv (%)","As","K")
# Imprimir Tabla
kable(Tabla_indicadores, format = "markdown", align = "c",
caption = "Tabla No. 1: Indicadores estadísticos de la variable Accident Year.")
| Variable | Mínimo | Máximo | x | Me | Mo | S (años) | Cv (%) | As | K |
|---|---|---|---|---|---|---|---|---|---|
| Año del accidente | 2010 | 2016 | 2013 | 2013 | 2015 | 2 | 0.1 | -0.19 | -1.18 |
En estadística, un valor atípico es una observación que se distancia significativamente del resto de los datos. Identificar estos puntos en el reporte es crucial, ya que pueden representar errores de registro o, más importante aún, eventos extraordinarios que requieren una investigación profunda por su alto impacto o naturaleza inusual.
# Usamos boxplot.stats sobre los años
stats_outliers <- boxplot.stats(anios_limpios)$out
# Contar los valores atípicos
num_outliers <- length(stats_outliers)
print(paste("Número de outliers:", num_outliers))
## [1] "Número de outliers: 0"
# Obtener Mínimo y Máximo Outlier (si existen)
minimooutliers <- if(num_outliers > 0) min(stats_outliers) else NA
maximooutliers <- if(num_outliers > 0) max(stats_outliers) else NA
# Imprimir resultados
if(num_outliers > 0){
print(paste("Outlier más bajo:", minimooutliers))
print(paste("Outlier más alto:", maximooutliers))
} else {
print("No existen valores atípicos.")
}
## [1] "No existen valores atípicos."
La variable discreta Año del Accidente fluctúa entre 2010 y 2016, con valores que giran en torno a una mediana de 2013, presentando una desviación estándar de 2 y un comportamiento marcadamente homogéneo (CV del 0.1%). Dada la naturaleza histórica del registro de siniestros, se registra la presencia de 0 valores atípicos; asimismo, la distribución exhibe una ligera asimetría negativa (-0.19, prácticamente simétrica) y una concentración platicúrtica (-1.18). Esto indica que los incidentes no se aglomeran de forma aguda en un año específico, sino que ocurren de manera dispersa y constante a lo largo de todo el periodo analizado, lo cual refleja un comportamiento operativo normal y esperado en infraestructuras que mantienen un riesgo latente continuo que no ha mostrado tendencias de reducción.