Justificación de la variable A diferencia de los meses, las horas del día representan una escala temporal de alta granularidad. La “Hora de reinicio” se considera una variable cuantitativa continua (o discreta si tomamos la hora exacta como número entero). Sin embargo, al contar con 24 posibles resultados distintos, analizarla valor por valor difumina las tendencias estructurales. Por ello, se la somete a un proceso de agrupación por intervalos (clases). Al agrupar las 24 horas en bloques definidos (ej. bloques de 4 horas: [0-4), [4-8), etc.), podemos identificar fácilmente si el restablecimiento de los sistemas ocurre predominantemente en la madrugada, la mañana o la tarde, logrando un panorama probabilístico mucho más útil para la gestión operativa y de recursos técnicos.
La configuración del entorno virtual y la habilitación de módulos
analíticos son prerrequisitos del estudio. La implementación de
dplyr optimiza la depuración de datos, mientras que
knitr y kableExtra proveen el soporte
necesario para exportar los resultados tabulares bajo un formato
académico estandarizado.
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
library(rmarkdown)
library(knitr)
Primero, leemos la base de datos y aislamos únicamente el componente “Hora” (0 a 24) de la fecha en la que el sistema logró restablecerse, aplicando una limpieza rigurosa para homogeneizar los formatos de fecha y omitir los registros vacíos.
datos <- read.csv("database-_1_.csv", stringsAsFactors = FALSE, check.names = FALSE)
raw <- datos$`Restart Date/Time`
raw <- raw[raw != "" & !is.na(raw)]
En esta etapa procedemos a aislar únicamente el componente “Hora” (0 a 24). Para lograrlo, aplicamos una limpieza rigurosa mediante un parseo robusto que homogeneiza los múltiples formatos de fecha presentes en la base de datos, garantizando así la correcta extracción del valor numérico de la hora.
# Parseo robusto para estandarizar los formatos de fecha y hora
fechas <- as.POSIXct(raw, format="%m/%d/%Y %H:%M")
fechas[is.na(fechas)] <- as.POSIXct(raw[is.na(fechas)], format="%d/%m/%Y %H:%M")
fechas[is.na(fechas)] <- as.POSIXct(raw[is.na(fechas)], format="%Y-%m-%d %H:%M")
# Eliminamos valores que no se pudieron parsear correctamente antes de continuar
fechas <- fechas[!is.na(fechas)]
# Extracción separada de horas y minutos
horas_enteras <- as.numeric(format(fechas, "%H"))
minutos_enteros <- as.numeric(format(fechas, "%M"))
# 1. Conservamos la variable continua original (por si la usas en indicadores estadísticos luego)
horas_limpias <- horas_enteras + (minutos_enteros / 60)
# 2. Creamos la versión con formato "HH:MM" (texto) sin puntos decimales
horas_formateadas <- sprintf("%02d:%02d", horas_enteras, minutos_enteros)
# Asignamos la versión formateada a 'zona' para que el Conteo sea legible
zona <- horas_formateadas
En esta fase se realiza el cálculo de las frecuencias absolutas de la variable horaria extraída. Este procedimiento estadístico agrupa los registros temporales discretos para determinar la ocurrencia y el nivel de incidencia operativa en las distintas franjas del día, proporcionando valores numéricos interpretables que servirán de base directa para el análisis.
conteo_zona <- table(zona)
print(conteo_zona)
## zona
## 00:00 00:01 00:15 00:17 00:19 00:20 00:24 00:25 00:30 00:31 00:35 00:43 00:46
## 6 3 1 1 1 3 1 1 5 1 1 1 1
## 00:49 00:56 01:00 01:02 01:05 01:06 01:08 01:14 01:16 01:22 01:24 01:30 01:33
## 1 1 3 1 1 1 2 1 1 1 1 2 1
## 01:38 01:45 01:50 02:00 02:09 02:14 02:20 02:21 02:26 02:28 02:30 02:35 03:00
## 1 1 2 9 1 1 1 1 1 1 2 1 5
## 03:09 03:15 03:17 03:20 03:30 03:33 03:37 03:40 03:46 03:47 03:49 03:55 04:00
## 1 1 1 1 3 1 1 2 1 1 2 1 5
## 04:10 04:30 04:42 04:47 04:48 04:52 04:55 05:00 05:01 05:12 05:15 05:18 05:20
## 1 3 1 2 1 1 1 4 1 1 1 1 1
## 05:23 05:25 05:39 05:42 05:45 05:46 05:49 06:00 06:06 06:08 06:10 06:19 06:20
## 1 1 1 1 3 2 1 4 1 1 1 1 1
## 06:23 06:24 06:29 06:30 06:32 06:35 06:40 06:49 06:57 06:58 07:00 07:10 07:11
## 1 1 1 1 1 1 1 1 1 1 11 1 1
## 07:15 07:19 07:20 07:21 07:22 07:23 07:29 07:30 07:36 07:41 07:45 07:50 07:53
## 3 2 1 1 2 1 1 11 1 1 2 1 2
## 07:54 08:00 08:04 08:05 08:10 08:11 08:12 08:13 08:14 08:16 08:18 08:20 08:23
## 1 45 1 2 3 1 1 1 1 1 1 1 1
## 08:30 08:31 08:39 08:40 08:45 08:49 08:52 08:55 08:57 09:00 09:03 09:05 09:08
## 9 1 1 1 1 1 1 1 1 34 2 2 1
## 09:10 09:11 09:12 09:15 09:17 09:18 09:19 09:20 09:21 09:22 09:23 09:30 09:31
## 2 2 1 2 2 1 1 2 1 1 1 8 1
## 09:33 09:34 09:35 09:37 09:40 09:45 09:49 09:50 09:54 09:57 10:00 10:02 10:03
## 1 1 2 1 3 1 1 4 1 2 27 1 1
## 10:05 10:10 10:15 10:16 10:18 10:20 10:22 10:23 10:24 10:25 10:26 10:30 10:33
## 1 1 1 1 2 4 1 1 1 3 1 10 1
## 10:35 10:38 10:39 10:40 10:44 10:45 10:50 10:53 10:54 10:55 10:56 10:59 11:00
## 1 1 1 2 2 5 3 1 2 4 2 1 27
## 11:07 11:12 11:13 11:17 11:19 11:22 11:24 11:28 11:30 11:32 11:33 11:35 11:36
## 1 1 2 3 1 1 1 1 9 1 1 2 2
## 11:39 11:41 11:43 11:45 11:46 11:49 11:52 11:53 11:57 12:00 12:03 12:05 12:07
## 1 1 2 2 1 1 2 2 1 39 1 3 1
## 12:11 12:15 12:19 12:20 12:26 12:30 12:35 12:38 12:40 12:44 12:45 12:50 12:51
## 2 1 1 3 1 9 3 1 1 1 3 1 2
## 12:52 12:53 12:54 12:58 13:00 13:05 13:08 13:09 13:10 13:14 13:15 13:16 13:18
## 1 1 1 1 19 3 1 1 1 2 4 2 2
## 13:20 13:23 13:26 13:30 13:35 13:36 13:40 13:45 13:47 13:52 13:53 14:00 14:01
## 2 1 1 14 1 1 1 2 1 1 4 31 1
## 14:02 14:04 14:09 14:11 14:14 14:15 14:17 14:18 14:19 14:20 14:21 14:25 14:26
## 1 1 1 1 1 5 1 1 1 1 1 1 2
## 14:27 14:28 14:29 14:30 14:32 14:33 14:34 14:37 14:38 14:39 14:40 14:45 14:47
## 1 1 1 12 1 1 2 1 2 1 4 1 1
## 14:50 14:54 14:56 14:57 14:58 15:00 15:02 15:04 15:05 15:09 15:10 15:12 15:15
## 4 2 1 1 1 37 2 1 1 1 3 3 6
## 15:19 15:20 15:21 15:23 15:25 15:26 15:30 15:34 15:35 15:37 15:39 15:40 15:42
## 1 5 1 3 1 1 15 1 1 1 2 2 2
## 15:46 15:47 15:50 15:51 15:54 15:55 15:56 15:57 16:00 16:01 16:03 16:04 16:05
## 1 1 2 1 2 2 2 2 38 1 1 1 2
## 16:09 16:10 16:11 16:13 16:15 16:16 16:17 16:18 16:19 16:20 16:23 16:25 16:26
## 1 4 1 1 9 1 1 1 1 4 1 1 1
## 16:30 16:34 16:35 16:37 16:39 16:40 16:43 16:45 16:50 16:52 16:53 16:55 16:58
## 14 1 1 1 1 2 2 3 3 1 1 1 1
## 17:00 17:04 17:05 17:07 17:10 17:11 17:13 17:14 17:15 17:16 17:18 17:20 17:22
## 21 1 1 1 1 1 1 1 4 1 1 2 1
## 17:24 17:25 17:26 17:30 17:31 17:32 17:33 17:34 17:35 17:36 17:37 17:38 17:39
## 1 4 1 18 1 2 1 1 1 1 2 2 1
## 17:40 17:43 17:45 17:49 17:50 17:51 17:52 17:55 17:56 17:58 18:00 18:04 18:05
## 2 1 8 1 2 1 2 2 2 1 29 1 1
## 18:06 18:07 18:08 18:09 18:10 18:11 18:15 18:16 18:19 18:20 18:22 18:23 18:25
## 1 3 1 1 1 1 1 2 1 1 1 1 2
## 18:26 18:28 18:29 18:30 18:31 18:38 18:40 18:42 18:44 18:45 18:46 18:47 18:50
## 1 1 1 16 1 2 1 2 1 3 2 1 2
## 18:53 18:55 18:56 18:57 19:00 19:02 19:03 19:04 19:05 19:06 19:10 19:15 19:17
## 1 2 1 2 13 1 1 1 3 1 2 2 1
## 19:18 19:25 19:29 19:30 19:31 19:34 19:35 19:37 19:40 19:41 19:45 19:46 19:47
## 1 2 1 16 1 1 1 1 1 1 5 1 2
## 19:49 19:50 19:53 19:55 19:59 20:00 20:04 20:05 20:06 20:09 20:13 20:14 20:15
## 1 1 2 1 1 22 1 1 1 1 1 1 4
## 20:17 20:18 20:19 20:24 20:30 20:31 20:33 20:34 20:35 20:40 20:41 20:45 20:48
## 1 1 1 1 6 1 1 1 2 3 1 5 1
## 20:49 20:50 20:53 20:54 20:56 20:57 21:00 21:05 21:06 21:09 21:12 21:15 21:20
## 1 1 1 1 1 1 11 1 1 1 1 1 1
## 21:21 21:22 21:26 21:29 21:30 21:35 21:37 21:40 21:41 21:45 21:46 21:49 21:53
## 1 1 1 1 11 1 1 2 1 2 1 1 1
## 21:55 21:58 22:00 22:08 22:09 22:10 22:15 22:16 22:18 22:19 22:20 22:25 22:30
## 2 1 8 1 1 3 2 1 1 1 1 2 4
## 22:35 22:36 22:40 22:45 22:49 22:50 22:51 23:00 23:05 23:09 23:11 23:12 23:15
## 1 1 2 1 1 1 1 10 1 1 1 1 1
## 23:23 23:30 23:31 23:33 23:35 23:40 23:45 23:50 23:52 23:54 23:59
## 1 4 1 1 1 1 2 2 1 1 1
A continuación, creamos intervalos de 4 horas de amplitud. Esto dividirá el día en 6 franjas clave. También añadimos la “Marca de Clase” (punto medio del intervalo) necesaria para cálculos matemáticos.
# 1. Definir amplitud y límites numéricos
amplitud <- 4
limites <- seq(0, 24, by = amplitud)
# --- NUEVO: Dar formato de hora y minuto (HH:MM) a los límites ---
limites_formato <- sprintf("%02d:00", limites)
n <- length(limites)
# Generar etiquetas automáticamente con el nuevo formato
etiquetas <- paste0("[", limites_formato[-n], " - ", limites_formato[-1], ")")
# Forzamos a que el último intervalo tenga el corchete cerrado "]" al final
etiquetas[length(etiquetas)] <- paste0("[", limites_formato[n-1], " - 23:59]")
# 2. Agrupar la variable en intervalos usando las etiquetas formateadas
# IMPORTANTE: breaks sigue usando 'limites' (números), labels usa 'etiquetas' (texto 00:00)
horas_agrupadas <- cut(horas_limpias, breaks = limites, labels = etiquetas, right = FALSE, include.lowest = TRUE)
# 3. Creación de tabla base
tabla_base <- table(horas_agrupadas)
Intervalo <- names(tabla_base)
ni <- as.vector(tabla_base)
hi <- round(ni / sum(ni) * 100, 2)
# Ajuste por pérdida de decimales
diferencia <- 100 - sum(hi)
if(diferencia != 0){
indice_max <- which.max(ni)
hi[indice_max] <- hi[indice_max] + diferencia
}
# 4. Frecuencias Acumuladas
Ni_asc <- cumsum(ni)
Ni_dsc <- rev(cumsum(rev(ni)))
Hi_asc <- cumsum(hi)
Hi_dsc <- rev(cumsum(rev(hi)))
# 5. Marca de clase
xi <- limites[-n] + (amplitud / 2)
# 6. Construcción del Dataframe
TDFHoras <- data.frame(
"Intervalos" = Intervalo,
"MC" = xi,
"ni" = ni,
"hi (%)" = hi,
"Ni Asc" = Ni_asc,
"Ni Dsc" = Ni_dsc,
"Hi Asc" = Hi_asc,
"Hi Dsc" = Hi_dsc,
check.names = FALSE
)
paged_table(TDFHoras, options = list(rows.print = 6))
La visualización a través del histograma nos permite ver claramente en qué bloques horarios se logra restablecer el sistema. Al estar agrupado, las barras representan intervalos completos de tiempo.
library(ggplot2)
# Asegurar el orden correcto usando la Marca de Clase
TDFHoras$Intervalos <- reorder(TDFHoras$Intervalos, TDFHoras$`MC`)
p_ni <- ggplot(TDFHoras, aes(x = Intervalos, y = ni)) +
geom_col(width = 1, 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 local de reinicios por Intervalos de Hora",
x = "Franja Horaria del Día",
y = "Cantidad de Reactivaciones"
) +
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"),
axis.text.y = element_text(color = "black"),
axis.line = element_line(linewidth = 0.5, color = "black")
)
print(p_ni)
Para comprender la verdadera magnitud de las recuperaciones en cada franja horaria respecto al panorama completo, es estrictamente necesario establecer el eje vertical (Y) con el límite máximo de la población total de estudio (2795 accidentes). Al fijar esta escala global, la gráfica actúa como un termómetro absoluto: evita distorsiones y permite dimensionar de forma objetiva qué porción del universo total de fallos logra ser restablecida en cada bloque temporal.
TDFHoras$Intervalos <- reorder(TDFHoras$Intervalos, TDFHoras$`MC`)
p_ni_global <- ggplot(TDFHoras, aes(x = Intervalos, y = ni)) +
geom_col(width = 1, 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 global de reinicios por Intervalos de Hora",
x = "Franja Horaria del Día",
y = "Cantidad de Reactivaciones"
) +
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"),
axis.text.y = element_text(color = "black"),
axis.line = element_line(linewidth = 0.5, color = "black")
)
print(p_ni_global)
Con este gráfico normalizamos los datos para evaluar la probabilidad real de que un restablecimiento ocurra dentro de un bloque horario determinado a lo largo del día.
TDFHoras$Intervalos <- reorder(TDFHoras$Intervalos, TDFHoras$`MC`)
p_hi <- ggplot(TDFHoras, aes(x = Intervalos, y = `hi (%)`)) +
geom_col(width = 1, fill = "steelblue", color = "black", alpha = 0.8, linewidth = 0.5) +
scale_y_continuous(expand = expansion(mult = c(0, 0.05)),
labels = function(x) paste0(x, "%")) +
labs(title = "Gráfica No 3: Probabilidad local (%) de reinicio por Intervalo",
x = "Franja Horaria",
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"),
axis.text.y = element_text(color = "black"),
axis.line = element_line(linewidth = 0.5, color = "black")
)
print(p_hi)
Para evaluar correctamente la probabilidad en términos absolutos, es crucial establecer la escala del eje vertical de 0% a 100%. Si el gráfico se ajustara automáticamente al porcentaje máximo obtenido, la barra llenaría casi toda la gráfica, dando la falsa impresión visual de que ese bloque abarca casi la totalidad de las reparaciones. Al fijar el tope en 100%, logramos un “espectro de probabilidad completo”, permitiendo dimensionar visualmente la verdadera tasa que representa cada franja horaria respecto al día entero.
library(ggplot2)
TDFHoras$Intervalos <- reorder(TDFHoras$Intervalos, TDFHoras$`MC`)
p_hi_global <- ggplot(TDFHoras, aes(x = Intervalos, y = `hi (%)`)) +
geom_col(width = 1, 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 No 4: Probabilidad global (%) de reinicio por Intervalo",
x = "Franja Horaria",
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"),
axis.text.y = element_text(color = "black"),
axis.line = element_line(linewidth = 0.5, color = "black")
)
print(p_hi_global)
Evaluamos la dispersión horaria cruda. A diferencia de los intervalos, la caja expone dónde se comprime el 50% central de las reactivaciones a lo largo de las 24 horas del reloj.
boxplot(horas_limpias,
horizontal = TRUE,
col = "steelblue",
ylim = c(0, 24),
main = "Gráfica 5: Rango Intercuartílico de la Hora de Reinicio",
xaxt = "n")
axis(1, at = seq(0, 24, by = 2), labels = seq(0, 24, by = 2), las = 1)
grid(nx = NULL, ny = NA, col = "lightgray", lty = "dotted")
Las ojivas ilustran la suma acumulativa a medida que transcurren las horas del día, revelando la aceleración de los restablecimientos operativos en horarios laborales frente a horas nocturnas.
TDFHoras$Index <- 1:nrow(TDFHoras)
p_ojiva <- ggplot(TDFHoras) +
geom_line(aes(x = Index, y = `Ni Asc`, color = "Ascendente", linetype = "Ascendente"), linewidth = 0.8) +
geom_point(aes(x = Index, y = `Ni Asc`, color = "Ascendente"), size = 2) +
geom_line(aes(x = Index, y = `Ni Dsc`, color = "Descendente", linetype = "Descendente"), linewidth = 0.8) +
geom_point(aes(x = Index, y = `Ni Dsc`, color = "Descendente"), size = 2) +
scale_x_continuous(breaks = TDFHoras$Index, labels = TDFHoras$Intervalos) +
scale_color_manual(name = NULL,
values = c("Ascendente" = "black", "Descendente" = "steelblue")) +
scale_linetype_manual(name = NULL,
values = c("Ascendente" = "solid", "Descendente" = "solid")) +
labs(title = "Gráfica 6: Distribución acumulada de los reinicios",
x = "Franja Horaria",
y = "Cantidad Acumulada") +
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")
)
print(p_ojiva)
Determinamos el marco matemático exacto en base a la data cruda, analizando hacia qué hora apunta el “centro de gravedad” de las recuperaciones operativas.
library(e1071)
library(knitr)
# --- FUNCIÓN DE CONVERSIÓN ---
# Convierte decimales continuos al formato HH:MM de reloj
convertir_a_hhmm <- function(horas_decimales) {
horas <- floor(horas_decimales)
minutos <- round((horas_decimales - horas) * 60)
# Ajuste de seguridad por si los minutos redondean a 60
horas <- horas + floor(minutos / 60)
minutos <- minutos %% 60
sprintf("%02d:%02d", horas, minutos)
}
# --- CÁLCULOS MATEMÁTICOS (utilizando la variable continua horas_limpias) ---
# 1. Rango
ri <- min(horas_limpias) # Se conserva el cálculo interno por si se necesita
rs <- 24
# 2. Mediana
mediana <- median(horas_limpias)
# 3. Media Aritmética
media_aritmetica <- mean(horas_limpias)
# 4. Moda
t <- table(horas_limpias)
Mo <- as.numeric(names(t)[which.max(t)])
# 5. Desviación Estándar
desviacion_estandar <- sd(horas_limpias)
# 6. Coeficiente de Variabilidad
coeficiente_variabilidad <- (desviacion_estandar / media_aritmetica) * 100
# 7. Asimetría (Skewness)
As <- skewness(horas_limpias)
# 8. Curtosis
curtosis_val <- kurtosis(horas_limpias)
# --- APLICACIÓN DEL FORMATO HH:MM ---
ri_hhmm <- "00:00" # Fijado a las 00:00 horas
rs_hhmm <- "23:59" # Fijado a las 24:00 horas
media_hhmm <- convertir_a_hhmm(media_aritmetica)
mediana_hhmm <- convertir_a_hhmm(mediana)
Mo_hhmm <- convertir_a_hhmm(Mo)
# --- PREPARACIÓN DE LA TABLA ---
Variable <- "Hora de Reinicio"
S_texto <- paste(round(desviacion_estandar, 2))
Tabla_indicadores <- data.frame(
Variable,
ri_hhmm, # Mínimo (formateado)
rs_hhmm, # Máximo (formateado)
media_hhmm, # Media (formateada)
mediana_hhmm, # Mediana (formateada)
Mo_hhmm, # Moda (formateada)
S_texto, # Desviación (se mantiene decimal)
round(coeficiente_variabilidad, 2), # Cv (%) (se mantiene porcentaje)
round(As, 2), # As (se mantiene decimal de forma)
round(curtosis_val, 2) # K (se mantiene decimal de forma)
)
colnames(Tabla_indicadores) <- c("Variable","Mínimo","Máximo","Media","Me","Mo","S","Cv (%)","As","K")
# Imprimir Tabla
kable(Tabla_indicadores, format = "markdown", caption = "Tabla No. 1: Indicadores estadísticos de las horas de reinicio (Límite superior 24h).")
| Variable | Mínimo | Máximo | Media | Me | Mo | S | Cv (%) | As | K |
|---|---|---|---|---|---|---|---|---|---|
| Hora de Reinicio | 00:00 | 23:59 | 13:37 | 14:17 | 08:00 | 5.49 | 40.34 | -0.41 | -0.39 |
Buscamos comportamientos “no estándares” o atípicos con respecto a las horas habituales. Al ser el horario un factor repetitivo (0-24) es posible que no se detecten irregularidades muy alejadas estadísticamente de las colas.
stats_outliers <- boxplot.stats(horas_limpias)$out
num_outliers <- length(stats_outliers)
print(paste("Cantidad de horas atípicas:", num_outliers))
## [1] "Cantidad de horas atípicas: 0"
minimooutliers <- if(num_outliers > 0) min(stats_outliers) else "Ninguno"
maximooutliers <- if(num_outliers > 0) max(stats_outliers) else "Ninguno"
print(paste("Hora atípica mínima:", minimooutliers))
## [1] "Hora atípica mínima: Ninguno"
print(paste("Hora atípica máxima:", maximooutliers))
## [1] "Hora atípica máxima: Ninguno"
La variable continua Hora de Reinicio fluctúa entre las 00:00 y las 24:00, con valores que giran en torno a una mediana de 14:17, presentando una desviación estándar de 5.49 horas y un comportamiento general heterogéneo (CV del 40.34%). Siguiendo el análisis del ciclo operativo, se registra la presencia de 0 valores atípicos; asimismo, la distribución exhibe una asimetría negativa (-0.41) y una concentración platicúrtica (-0.39). Esto indica que las recuperaciones o reinicios del sistema no se aglomeran de forma extrema en una sola hora, sino que se distribuyen de manera aplanada durante todo el día, mostrando un ligero sesgo hacia la franja de la tarde, lo cual refleja un comportamiento operativo normal y lógico en la logística de restablecimiento de infraestructuras continuas.