Justificación de la variable
Para entender de forma sencilla por qué el “Mes del accidente” es una variable cuantitativa discreta, imaginen el año como una escalera con 12 escalones fijos, en lugar de un río que fluye sin parar. Es cuantitativa porque podemos representarla numéricamente (asignando valores del 1 al 12) para realizar cálculos matemáticos, como analizar la frecuencia de incidentes o calcular su promedio. Y es discreta porque, al registrar únicamente el mes, el dato da saltos enteros: pasamos de un mes al siguiente como unidades completas (del mes 1 al mes 2), sin tomar en cuenta las fracciones de tiempo que existen en el medio (estadísticamente no registramos un “mes 1.5”). Por lo tanto, al capturar este dato, estamos registrando un punto específico y contable dentro de una secuencia de meses enteros.
La estructuración del entorno computacional es el requerimiento
inicial del procesamiento. Incorporar librerías como dplyr
garantiza una manipulación de datos robusta, en tanto que paquetes como
knitr y kableExtra resultan indispensables
para compilar el documento con los estándares de calidad visual propios
de un informe técnico.
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
library(ggplot2)
##
## Adjuntando el paquete: 'ggplot2'
## The following object is masked from 'package:e1071':
##
## element
Todo análisis riguroso comienza con la validación de la materia prima. En esta fase, se estructuran los registros crudos de los apagados para convertirlos en un formato temporal operable (limpieza, parseo de fechas y extracción de componentes temporales) que garantice la integridad técnica del estudio.
database <- read.csv("database-_1_.csv", header = TRUE, sep = ",", dec = ".", check.names = FALSE)
raw_dates<- database$`Shutdown Date/Time`
raw_dates <- raw_dates[raw_dates != ""]
raw_dates <- na.omit(raw_dates)
fechas_obj <- as.POSIXct(raw_dates, format = "%m/%d/%Y")
amperaje <- as.numeric(fechas_obj)
amperaje <- na.omit(amperaje)
fechas_obj <- fechas_obj[!is.na(amperaje)]
El análisis temporal requiere un tratamiento meticuloso. En esta etapa, se aísla la variable referente al cierre de operaciones (Shutdown Date/Time). Debido a la alta granularidad de los registros crudos, se ejecuta un proceso de limpieza (eliminación de celdas vacías y valores nulos NA) y se estandariza el formato temporal (POSIXct). Finalmente, se extrae de manera exclusiva el mes de ocurrencia, un paso estadístico vital para aislar la temporalidad y poder evaluar la incidencia mensual de los incidentes.
# Limpieza y estructuración del formato de fecha
raw_dates <- database$`Shutdown Date/Time`
raw_dates <- raw_dates[raw_dates != ""]
raw_dates <- na.omit(raw_dates)
# Conversión a objeto de tiempo
fechas_obj <- as.POSIXct(raw_dates, format = "%m/%d/%Y")
amperaje <- as.numeric(fechas_obj)
amperaje <- na.omit(amperaje)
fechas_obj <- fechas_obj[!is.na(amperaje)]
# Extracción específica del mes (variable de interés)
zona <- as.numeric(format(fechas_obj, "%m"))
Trabajar con la variable mensual depurada permite agrupar la información de manera eficiente. El cálculo de las frecuencias absolutas contabiliza el número de paralizaciones registradas en cada mes del año. Esta tabulación es el pilar cuantitativo para identificar tendencias de estacionalidad, detectando si existen periodos anuales con mayor vulnerabilidad operativa en la red de tuberías.
conteo_zona <- table(zona)
print(conteo_zona)
## zona
## 1 2 3 4 5 6 7 8 9 10 11 12
## 123 114 115 131 106 104 113 127 127 87 113 130
Para comprender la dinámica de los cortes, es imperativo transicionar de datos temporales continuos a intervalos discretos. Esta sección consolida la agrupación cronológica mediante clases, sentando las bases matemáticas para la evaluación de densidades y probabilidades.
# Cargar librerías necesarias
library(dplyr)
library(rmarkdown)
# 1. CARGA DE DATOS
datos <- read.csv("database-_1_.csv", stringsAsFactors = FALSE)
# 2. EXTRACCIÓN Y LIMPIEZA DE LA VARIABLE (MES)
fechas <- as.POSIXct(datos$Accident.Date.Time, format="%m/%d/%Y %H:%M")
meses_limpios <- as.numeric(format(fechas, "%m"))
meses_limpios <- meses_limpios[!is.na(meses_limpios)]
# 3. CREACIÓN DE LA TABLA DE FRECUENCIAS DISCRETA
tabla_base <- table(meses_limpios)
ni <- as.vector(tabla_base)
# Esta será tu única columna para el mes (1, 2, 3... hasta 12)
Mes <- names(tabla_base)
hi <- round(ni / sum(ni) * 100, 2)
# Ajuste por pérdida de decimales para asegurar que sume 100%
diferencia <- 100 - sum(hi)
if(diferencia != 0){
indice_max <- which.max(ni)
hi[indice_max] <- hi[indice_max] + diferencia
}
# 4. CÁLCULO DE FRECUENCIAS ACUMULADAS
Ni_asc <- cumsum(ni)
Ni_dsc <- rev(cumsum(rev(ni)))
Hi_asc <- cumsum(hi)
Hi_dsc <- rev(cumsum(rev(hi)))
# 5. CONSTRUCCIÓN DEL DATAFRAME FINAL
TDFMesFin <- data.frame(
"Mes" = Mes,
"ni" = ni,
"hi (%)" = hi,
"Ni Asc" = Ni_asc,
"Ni Dsc" = Ni_dsc,
"Hi Asc" = Hi_asc,
"Hi Dsc" = Hi_dsc,
check.names = FALSE
)
# 6. MOSTRAR TABLA
paged_table(TDFMesFin, options = list(rows.print = 6))
La visualización macroscópica permite identificar el volumen total de incidencias. Este apartado despliega la distribución temporal completa, revelando visualmente las tendencias estructurales y la concentración del fenómeno a lo largo de todo el periodo de estudio.
library(ggplot2)
TDFMesFin$Mes <- factor(TDFMesFin$Mes, levels = as.character(1:12))
total_apagones <- sum(TDFMesFin$ni)
p_ni <- ggplot(TDFMesFin, aes(x = Mes, y = ni)) +
geom_col(width = 0.9, fill = "steelblue", color = "black", alpha = 0.8, linewidth = 0.5) +
scale_y_continuous(expand = expansion(mult = c(0, 0.05))) +
labs(
title = "Gráfica No 1: Distribución de los apagados locales",
x = "Mes del 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 = 0, hjust = 0.5, color = "black"),
axis.text.y = element_text(color = "black"),
axis.line = element_line(linewidth = 0.5, color = "black")
)
print(p_ni)
Al aislar ventanas temporales críticas, se incrementa la resolución del análisis. Aquí se evalúa el comportamiento volumétrico en intervalos específicos de alta relevancia operativa (ej. el mes más crítico) para contrastarlo con el histórico general.
library(ggplot2)
TDFMesFin$Mes <- factor(TDFMesFin$Mes, levels = as.character(1:12))
total_apagones <- sum(TDFMesFin$ni)
p_ni <- ggplot(TDFMesFin, aes(x = Mes, y = ni)) +
geom_col(width = 0.9, fill = "steelblue", color = "black", alpha = 0.8, linewidth = 0.5) +
scale_y_continuous(limits = c(0, 2795), expand = expansion(mult = c(0, 0.05))) +
labs(
title = "Gráfica No 2: Distribución de pagados glogables",
x = "Mes del 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 = 0, hjust = 0.5, color = "black"),
axis.text.y = element_text(color = "black"),
axis.line = element_line(linewidth = 0.5, color = "black")
)
print(p_ni)
Trascendiendo el conteo absoluto, este enfoque normaliza los datos para expresar el peso proporcional de cada intervalo. Es una herramienta crucial para entender la densidad de probabilidad de ocurrencia de un apagado en el panorama general.
library(ggplot2)
TDFMesFin$Mes <- factor(TDFMesFin$Mes, levels = as.character(1:12))
p_hi <- ggplot(TDFMesFin, aes(x = Mes, y = `hi (%)`)) +
geom_col(width = 0.9, fill = "steelblue", color = "black", alpha = 0.8, linewidth = 0.5) +
scale_y_continuous(limits = c(0, 100),
expand = expansion(mult = c(0, 0.05)),
labels = function(x) paste0(x, "%")) +
labs(title = "Gráfica 3: Porcentaje apagado global",
x = "Mes",
y = "Porcentaje") +
theme_classic() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 13),
axis.text.x = element_text(angle = 0, hjust = 0.5, color = "black"), # Ángulo 0
axis.text.y = element_text(color = "black"),
axis.line = element_line(linewidth = 0.5, color = "black")
)
print(p_hi)
Mediante el escalado probabilístico en segmentos temporales acotados, este análisis permite verificar si las dinámicas locales de los apagados obedecen al mismo modelo de probabilidad que rige la tendencia histórica.
library(ggplot2)
TDFMesFin$Mes <- factor(TDFMesFin$Mes, levels = as.character(1:12))
p_hi <- ggplot(TDFMesFin, aes(x = Mes, y = `hi (%)`)) +
geom_col(width = 0.9, fill = "steelblue", color = "black", alpha = 0.8, linewidth = 0.5) +
scale_y_continuous(labels = function(x) paste0(x, "%"),
expand = expansion(mult = c(0, 0.05))) +
labs(title = "Gráfica 4: Porcentaje apagado local",
x = "Mes",
y = "Porcentaje") +
theme_classic() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 13),
axis.text.x = element_text(angle = 0, hjust = 0.5, color = "black"), # Ángulo 0 para texto horizontal
axis.text.y = element_text(color = "black"),
axis.line = element_line(linewidth = 0.5, color = "black")
)
print(p_hi)
El estudio de la progresión acumulativa es vital para establecer umbrales temporales. Esta gráfica ilustra la suma secuencial de los eventos, evidenciando la velocidad y el ritmo con el que se acumulan los apagados en el tiempo.
# Cargar librerías necesarias
library(ggplot2)
library(scales)
# Para trazar líneas, necesitamos que el Mes sea interpretado como número (1 al 12)
TDFMesFin$Mes_num <- as.numeric(as.character(TDFMesFin$Mes))
p_ojiva_replicada <- ggplot(TDFMesFin) +
# Usamos la columna de mes numérica y la frecuencia acumulada Ascendente
geom_line(aes(x = Mes_num, y = `Ni Asc`, color = "Ascendente", linetype = "Ascendente"), linewidth = 0.8) +
geom_point(aes(x = Mes_num, y = `Ni Asc`, color = "Ascendente"), size = 2) +
# Usamos la columna de mes numérica y la frecuencia acumulada Descendente
geom_line(aes(x = Mes_num, y = `Ni Dsc`, color = "Descendente", linetype = "Descendente"), linewidth = 0.8) +
geom_point(aes(x = Mes_num, y = `Ni Dsc`, color = "Descendente"), size = 2) +
# Forzamos que en el eje X aparezcan los números exactos del 1 al 12
scale_x_continuous(breaks = 1:12) +
scale_color_manual(name = NULL,
values = c("Ascendente" = "black", "Descendente" = "blue")) +
scale_linetype_manual(name = NULL,
values = c("Ascendente" = "solid", "Descendente" = "solid")) +
labs(title = "Gráfica 5:Distribución acumulada del mes de apagado",
x = "Mes",
y = "Cantidad") +
theme_bw() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
legend.position = c(0.85, 0.85),
legend.background = element_rect(color = "black", fill = "white", linewidth = 0.5),
legend.key = element_blank(),
panel.grid.minor = element_blank(),
axis.text = element_text(color = "black"),
axis.title.y = element_text(angle = 90, vjust = 0.5)
)
print(p_ojiva_replicada)
Más allá de las frecuencias, es fundamental evaluar la variabilidad posicional de los eventos. El diagrama de caja desentraña la estacionalidad, identificando la concentración de la “hora de apagado” y su dispersión según días o meses.
boxplot(meses_limpios,
horizontal = TRUE,
col = "skyblue",
main = "Gráfica 7: Distribución de apagados por Mes",
xlab = "Mes del Año",
xaxt = "n")
axis(1, at = 1:12, labels = 1:12, las = 1)
grid(nx = NULL, ny = NA, col = "lightgray", lty = "dotted")
La cuantificación objetiva requiere robustez matemática. En este apartado se calculan los parámetros exactos de centralización, dispersión y forma para caracterizar analíticamente el perfil temporal de las interrupciones.
library(e1071)
library(knitr)
# Asumimos que el vector 'meses_limpios' ya está cargado de los pasos anteriores
# 1. Rango (Mínimo y Máximo)
ri <- min(meses_limpios)
rs <- max(meses_limpios)
# 2. Mediana
mediana <- median(meses_limpios)
# 3. Media Aritmética
media_aritmetica <- mean(meses_limpios)
# 4. Moda
t <- table(meses_limpios)
Mo <- as.numeric(names(t)[which.max(t)])
# 5. Desviación Estándar
# Al ser meses, la desviación se expresa directamente en "meses"
desviacion_estandar <- sd(meses_limpios)
# 6. Coeficiente de Variabilidad
coeficiente_variabilidad <- (desviacion_estandar / media_aritmetica) * 100
# 7. Asimetría (Skewness)
As <- skewness(meses_limpios)
# 8. Curtosis
curtosis_val <- kurtosis(meses_limpios)
# --- PREPARACIÓN DE LA TABLA ---
Variable <- "Mes apagado"
S_texto <- paste(round(desviacion_estandar))
Tabla_indicadores <- data.frame(
Variable,
ri, # Mínimo
rs, # Máximo
round(media_aritmetica), # Media
mediana, # Mediana
Mo, # Moda
S_texto, # Desviación
round(coeficiente_variabilidad),
round(As, 2),
round(curtosis_val, 2)
)
colnames(Tabla_indicadores) <- c("Variable","Mínimo","Máximo","x","Me","Mo","S","Cv (%)","As","K")
# Imprimir Tabla
kable(Tabla_indicadores, format = "markdown", caption = "Tabla No. 2: Indicadores estadísticos de la variable Mes del Accidente.")
| Variable | Mínimo | Máximo | x | Me | Mo | S | Cv (%) | As | K |
|---|---|---|---|---|---|---|---|---|---|
| Mes apagado | 1 | 12 | 6 | 6 | 1 | 3 | 56 | 0.08 | -1.22 |
Esta sección se enfoca en los ‘Cisnes Negros’ del dataset: eventos de baja frecuencia pero impacto catastrófico. Identificar los valores atípicos permite aislar aquellos fallos críticos de seguridad donde la evacuación superó los rangos normales, siendo esta la información más valiosa para el diseño de planes de contingencia y gestión de crisis.
# Usamos boxplot.stats sobre nuestro vector numérico de meses
stats_outliers <- boxplot.stats(meses_limpios)$out
# Contar los valores atípicos
num_outliers <- length(stats_outliers)
print(paste("Cantidad de meses atípicos:", num_outliers))
## [1] "Cantidad de meses atípicos: 0"
# Obtener Mínimo y Máximo Outlier (si existen)
# Usamos 'if' para evitar errores si num_outliers es 0
minimooutliers <- if(num_outliers > 0) min(stats_outliers) else NA
maximooutliers <- if(num_outliers > 0) max(stats_outliers) else NA
# Al ser meses enteros, ya no convertimos a fecha.
# Solo pasamos el valor o imprimimos "Ninguno"
minimooutliers_mes <- if(!is.na(minimooutliers)) minimooutliers else "Ninguno"
maximooutliers_mes <- if(!is.na(maximooutliers)) maximooutliers else "Ninguno"
print(paste("Mes atípico mínimo:", minimooutliers_mes))
## [1] "Mes atípico mínimo: Ninguno"
print(paste("Mes atípico máximo:", maximooutliers_mes))
## [1] "Mes atípico máximo: Ninguno"
La variable discreta Mes de Apagado fluctúa entre 1 y 12, con valores que giran en torno a una mediana de 6, presentando una desviación estándar de 3 y un comportamiento marcadamente heterogéneo (CV del 56%). Dada la naturaleza cíclica del calendario anual, se registra la presencia de 0 valores atípicos; asimismo, la distribución exhibe una asimetría prácticamente nula (0.08, fuertemente simétrica) y una concentración platicúrtica (-1.22). Esto indica que los incidentes no se aglomeran de forma aguda en una temporada o estación específica, sino que ocurren de manera dispersa y constante a lo largo de todo el año, lo cual refleja un comportamiento operativo normal y esperado en infraestructuras que mantienen un riesgo latente continuo