Justificación de la variable
A diferencia de los meses, las horas del día representan una escala temporal de alta granularidad. La “Hora del accidente” 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 las incidencias ocurren predominantemente en la madrugada, la mañana o la tarde, logrando un panorama probabilístico mucho más útil para la gestión operativa.
El acondicionamiento del entorno de programación y la habilitación de
librerías específicas son requisitos indispensables. El uso de
dplyr optimiza la manipulación de la data, en tanto que
knitr y kableExtra garantizan que la
visualización de los hallazgos cumpla con el formato académico
exigido.
knitr::opts_chunk$set(echo = TRUE, warning = FALSE, message = FALSE)
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 ocurrió la contingencia.
datos <- read.csv("database-_1_.csv", stringsAsFactors = FALSE, check.names = FALSE)
# Se utilizan comillas invertidas debido al espacio en el nombre original de la base
raw <- datos$`Shutdown Date/Time`
raw <- raw[raw != "" & !is.na(raw)]
Para diagnosticar la capacidad de respuesta del sistema, es imperativo aislar el componente horario exacto en el que se efectuó el cierre de operaciones. Mediante un parseo robusto, se estandarizan los múltiples formatos de registro temporal. Acto seguido, se extraen las horas y los minutos para unificarlos matemáticamente en una variable cuantitativa continua (horas en formato decimal). Esta conversión es un requisito estadístico indispensable para someter los datos a una correcta compresión de datos por intervalos en las etapas subsiguientes del reporte.
# 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 las horas y los minutos
horas_enteras <- as.numeric(format(fechas, "%H"))
minutos_enteros <- as.numeric(format(fechas, "%M"))
# 1. Conservamos la variable continua original para los análisis matemáticos/intervalos posteriores
horas_limpias <- horas_enteras + (minutos_enteros / 60)
# 2. Creamos una versión con formato "HH:MM" (texto) para que la tabla de conteo sea legible
# sprintf("%02d:%02d", ...) asegura que muestre "00:05" en lugar de "0:5"
horas_formateadas <- sprintf("%02d:%02d", horas_enteras, minutos_enteros)
# Asignamos la versión formateada a 'zona' para que la fase de Conteo use las etiquetas correctas
zona <- horas_formateadas
En esta fase se tabulan las frecuencias absolutas de las horas decimales calculadas. Al haber transformado el registro de paralización en una métrica continua, el conteo primario revela la distribución de los cierres operativos a lo largo de la jornada de 24 horas. Esta sistematización numérica sienta las bases para definir los límites de clase y facilita la visualización analítica del tiempo de reacción de la infraestructura.
# Generamos la tabla de frecuencias absolutas usando la variable formateada
tabla_frecuencias <- table(zona)
# Imprimimos la tabla para visualizarla en el documento
tabla_frecuencias
## zona
## 00:03 00:05 00:09 00:15 00:16 00:20 00:23 00:24 00:30 00:34 00:35 00:37 00:58
## 2 1 1 1 1 1 1 1 1 1 3 1 1
## 01:01 01:03 01:06 01:10 01:15 01:23 01:25 01:26 01:30 01:34 01:38 01:40 01:43
## 1 1 2 1 2 1 1 1 2 1 1 1 1
## 01:45 01:46 01:50 01:52 01:57 02:00 02:04 02:15 02:18 02:19 02:28 02:31 02:41
## 1 1 1 1 1 3 1 1 1 1 1 1 1
## 02:45 02:57 02:58 03:00 03:02 03:07 03:09 03:10 03:13 03:15 03:20 03:21 03:23
## 2 1 1 2 1 1 1 1 1 1 3 2 1
## 03:25 03:30 03:32 03:39 03:47 03:48 03:49 03:50 04:00 04:10 04:12 04:16 04:20
## 1 4 1 1 1 1 1 1 3 2 1 1 1
## 04:23 04:27 04:30 04:34 04:42 04:45 04:53 04:55 04:56 04:57 05:00 05:05 05:10
## 1 1 1 2 1 1 1 2 1 1 3 1 2
## 05:15 05:18 05:23 05:27 05:30 05:33 05:35 05:42 05:45 05:48 05:51 05:58 05:59
## 2 1 1 1 1 1 1 1 1 2 1 2 1
## 06:00 06:02 06:05 06:06 06:10 06:12 06:15 06:23 06:28 06:29 06:30 06:35 06:37
## 4 2 4 1 3 1 2 1 2 1 11 2 1
## 06:38 06:40 06:41 06:45 06:46 06:47 06:48 06:50 06:52 06:55 06:56 07:00 07:04
## 1 4 1 4 1 1 2 4 3 1 1 5 1
## 07:05 07:06 07:08 07:10 07:11 07:13 07:14 07:15 07:16 07:17 07:18 07:20 07:22
## 2 2 1 3 1 1 1 2 2 1 1 6 2
## 07:24 07:25 07:27 07:29 07:30 07:32 07:33 07:34 07:35 07:38 07:39 07:40 07:42
## 2 3 2 1 12 2 1 1 6 1 1 4 1
## 07:45 07:47 07:48 07:49 07:50 07:53 07:54 08:00 08:01 08:02 08:04 08:05 08:06
## 7 1 2 1 3 1 1 13 3 2 1 1 2
## 08:09 08:10 08:12 08:14 08:15 08:17 08:20 08:25 08:26 08:27 08:30 08:31 08:35
## 5 4 2 1 7 1 2 2 1 1 9 1 1
## 08:36 08:37 08:38 08:40 08:41 08:43 08:45 08:46 08:47 08:49 08:50 08:51 08:53
## 1 2 1 1 3 1 6 1 2 1 2 2 1
## 08:54 08:55 08:56 08:57 09:00 09:02 09:03 09:04 09:05 09:06 09:09 09:10 09:13
## 2 2 1 3 12 2 1 1 1 2 1 2 1
## 09:15 09:16 09:17 09:18 09:20 09:24 09:25 09:26 09:27 09:30 09:31 09:32 09:34
## 7 1 2 2 1 3 1 1 1 11 1 3 1
## 09:35 09:38 09:39 09:40 09:42 09:44 09:45 09:47 09:48 09:49 09:50 09:51 09:55
## 3 1 1 2 1 3 5 1 1 1 6 1 5
## 09:56 09:57 09:58 09:59 10:00 10:01 10:02 10:03 10:04 10:05 10:07 10:09 10:10
## 1 1 2 1 18 1 3 3 1 6 1 2 3
## 10:11 10:12 10:13 10:14 10:15 10:16 10:18 10:19 10:20 10:25 10:26 10:28 10:29
## 2 2 1 1 5 2 2 1 4 3 1 1 1
## 10:30 10:31 10:33 10:35 10:37 10:38 10:40 10:41 10:44 10:45 10:46 10:48 10:49
## 14 3 3 3 3 1 6 1 1 6 2 1 2
## 10:50 10:51 10:52 10:53 10:55 10:57 10:58 10:59 11:00 11:02 11:03 11:05 11:08
## 2 1 3 3 2 1 1 1 19 1 2 3 3
## 11:09 11:10 11:11 11:12 11:13 11:15 11:16 11:17 11:18 11:20 11:25 11:27 11:28
## 2 3 1 1 2 3 2 1 1 5 1 2 1
## 11:30 11:33 11:35 11:36 11:38 11:40 11:43 11:45 11:46 11:47 11:49 11:51 11:54
## 13 1 3 2 2 7 2 7 3 1 1 1 2
## 11:55 11:57 11:59 12:00 12:01 12:03 12:04 12:05 12:06 12:08 12:09 12:10 12:11
## 1 3 1 13 3 1 1 3 1 3 2 6 1
## 12:13 12:15 12:18 12:19 12:20 12:21 12:23 12:24 12:28 12:30 12:31 12:32 12:33
## 2 5 1 1 3 2 1 1 1 12 2 1 1
## 12:34 12:37 12:39 12:44 12:45 12:46 12:48 12:50 12:53 12:54 12:55 12:56 13:00
## 1 1 1 2 3 1 1 5 3 1 1 1 16
## 13:01 13:02 13:04 13:05 13:06 13:08 13:10 13:13 13:15 13:16 13:18 13:19 13:20
## 1 3 1 2 1 1 1 1 6 2 3 1 3
## 13:21 13:25 13:26 13:28 13:29 13:30 13:32 13:33 13:34 13:35 13:37 13:38 13:40
## 1 2 3 1 2 13 1 1 1 2 2 1 2
## 13:41 13:42 13:45 13:48 13:49 13:50 13:51 13:52 13:55 13:57 13:58 14:00 14:02
## 1 1 3 1 3 1 1 3 2 2 1 16 2
## 14:03 14:04 14:05 14:07 14:08 14:10 14:12 14:13 14:14 14:15 14:16 14:17 14:18
## 2 2 5 2 3 8 1 2 2 9 3 1 1
## 14:20 14:22 14:23 14:24 14:25 14:26 14:27 14:28 14:30 14:33 14:38 14:39 14:40
## 3 4 1 1 1 1 1 2 8 1 3 1 1
## 14:41 14:42 14:45 14:46 14:47 14:48 14:49 14:50 14:52 14:55 14:56 15:00 15:01
## 1 1 8 1 1 1 1 4 1 2 4 14 1
## 15:03 15:04 15:05 15:06 15:08 15:10 15:15 15:17 15:18 15:19 15:20 15:22 15:25
## 2 1 4 2 1 4 4 1 1 2 7 1 1
## 15:26 15:27 15:28 15:29 15:30 15:31 15:35 15:40 15:41 15:42 15:44 15:45 15:48
## 1 1 3 1 5 1 2 3 1 2 1 4 1
## 15:49 15:50 15:52 15:53 15:54 15:56 15:57 15:59 16:00 16:01 16:02 16:04 16:05
## 1 5 2 1 2 1 1 1 14 1 1 2 5
## 16:06 16:08 16:09 16:10 16:11 16:12 16:14 16:15 16:19 16:20 16:23 16:25 16:30
## 1 1 2 5 1 1 1 3 1 3 2 2 6
## 16:31 16:35 16:37 16:39 16:40 16:45 16:46 16:48 16:50 16:51 16:55 16:58 17:00
## 1 2 1 2 4 1 2 1 1 1 2 2 13
## 17:03 17:05 17:07 17:10 17:11 17:15 17:16 17:17 17:20 17:23 17:25 17:26 17:30
## 1 1 1 4 1 1 1 1 4 1 3 1 6
## 17:31 17:33 17:35 17:36 17:42 17:45 17:46 17:47 17:49 17:50 17:52 17:55 18:00
## 1 2 1 2 1 1 1 1 1 4 1 1 11
## 18:03 18:08 18:15 18:17 18:20 18:24 18:25 18:30 18:32 18:35 18:40 18:44 18:45
## 1 2 3 1 2 1 2 7 1 1 4 1 2
## 18:48 18:50 18:52 18:54 18:58 18:59 19:00 19:02 19:04 19:05 19:07 19:08 19:09
## 1 1 1 1 2 1 5 2 2 1 1 1 1
## 19:10 19:12 19:13 19:16 19:18 19:20 19:23 19:24 19:26 19:28 19:30 19:33 19:35
## 3 1 1 1 1 2 1 1 1 2 4 1 1
## 19:36 19:38 19:40 19:42 19:45 19:47 19:48 19:50 19:52 19:55 20:00 20:01 20:02
## 1 1 2 2 3 1 1 3 1 1 2 1 1
## 20:03 20:05 20:08 20:10 20:12 20:19 20:21 20:22 20:24 20:25 20:26 20:28 20:30
## 1 2 2 2 1 1 3 1 1 1 1 1 4
## 20:32 20:35 20:38 20:40 20:42 20:44 20:50 20:52 20:53 20:54 20:58 21:00 21:05
## 1 1 1 1 1 2 1 1 1 1 2 10 1
## 21:12 21:15 21:20 21:26 21:29 21:30 21:34 21:36 21:44 21:45 21:47 21:49 21:51
## 1 2 1 1 1 7 1 1 1 2 1 1 1
## 21:52 21:53 22:04 22:05 22:09 22:10 22:12 22:22 22:27 22:34 22:38 22:40 22:45
## 1 1 1 2 2 1 1 1 1 1 3 1 1
## 22:47 22:48 22:50 23:00 23:01 23:05 23:15 23:16 23:17 23:29 23:30 23:31 23:39
## 1 1 1 4 2 2 2 1 1 1 4 1 1
## 23:40 23:41 23:42 23:45 23:47 23:54
## 1 2 1 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
amplitud <- 4
limites <- seq(0, 24, by = amplitud)
limites_formato <- sprintf("%02d:00", limites)
n <- length(limites)
etiquetas <- paste0("[", limites_formato[-n], " - ", limites_formato[-1], ")")
etiquetas[length(etiquetas)] <- paste0("[", limites_formato[n-1], " - 23:59]")
# 2. Agrupar la variable en intervalos usando las etiquetas automáticas
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
)
# 7. Visualización
paged_table(TDFHoras, options = list(rows.print = 6))
La siguiente tabla de frecuencias resume la distribución de las horas registradas, agrupadas en intervalos de 4 horas. Con el fin de facilitar la interpretación de los datos, se presenta una estructura simplificada que destaca únicamente las métricas estadísticas fundamentales: la marca de clase (el punto medio de cada periodo), la frecuencia absoluta (ni), que contabiliza la cantidad de observaciones en cada rango, y la frecuencia relativa (hi), que expresa el peso porcentual de cada bloque respecto al total.
# 1 al 5 se mantienen igual que en tu código original...
# (asumiendo que ya corriste la creación de intervalos, ni, hi y xi)
# 6. Construcción del Dataframe SIMPLIFICADO
TDFHoras_Simple <- data.frame(
"Intervalos" = Intervalo,
"MC" = xi,
"ni" = ni,
"hi (%)" = hi,
check.names = FALSE
)
# Mostrar la tabla
paged_table(TDFHoras_Simple)
La visualización a través del histograma nos permite ver claramente en qué bloques horarios colapsan los sistemas. Al estar agrupado, las barras representan intervalos completos de tiempo.
library(ggplot2)
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 apagados por Intervalos de Hora",
x = "Franja Horaria del Día",
y = "Cantidad de Incidentes"
) +
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 los incidentes 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 apagados). Si permitiéramos que la gráfica se ajustara automáticamente al intervalo con más accidentes, visualmente parecería que ese bloque acapara la totalidad de los problemas, generando un sesgo de percepción. 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 representa 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 apagados por Intervalos de Hora",
x = "Franja Horaria del Día",
y = "Cantidad de Incidentes"
) +
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 apagado 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 apagados 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 (por ejemplo, si el intervalo pico solo tiene el 30% o 40%), la barra llenaría casi toda la gráfica, dando la falsa impresión visual de que ese bloque abarca casi la totalidad de los eventos. Al fijar el tope en 100%, logramos un “espectro de probabilidad completo”, permitiendo dimensionar visualmente la verdadera fracción de riesgo 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 3.1: Probabilidad global (%) de apagados 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 los sucesos a lo largo de las 24 horas del reloj.
boxplot(horas_limpias,
horizontal = TRUE,
col = "steelblue",
ylim = c(0, 24),
main = "Gráfica 4: Rango Intercuartílico de la Hora de Apagado",
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 accidentes en horarios laborales picos frente a horas nocturnas.
# Agregamos un índice para mapear el eje X con los intervalos ordenados
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 3: Distribución acumulada de los apagados",
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 todos los cortes operativos.
library(e1071)
library(knitr)
# --- FUNCIÓN DE CONVERSIÓN ---
# Reutilizamos la lógica para convertir decimales a HH:MM
convertir_a_hhmm <- function(horas_decimales) {
horas <- floor(horas_decimales)
minutos <- round((horas_decimales - horas) * 60)
# Ajuste de seguridad: si los minutos se redondean a 60, sumamos 1 a la hora y dejamos minutos en 0
horas <- horas + floor(minutos / 60)
minutos <- minutos %% 60
sprintf("%02d:%02d", horas, minutos)
}
# --- CÁLCULOS MATEMÁTICOS (usando horas_limpias) ---
# 1. Rango
ri <- min(horas_limpias)
rs <- 23:59
# 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"
rs_hhmm <- "23:59"
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 Apagado"
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 (decimal)
round(coeficiente_variabilidad, 2), # CV (decimal/porcentaje)
round(As, 2), # Asimetría (decimal)
round(curtosis_val, 2) # Curtosis (decimal)
)
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 fallos (Límite superior 24h).")
| Variable | Mínimo | Máximo | Media | Me | Mo | S | Cv (%) | As | K |
|---|---|---|---|---|---|---|---|---|---|
| Hora de Apagado | 00:00 | 23:59 | 12:23 | 12:08 | 11:00 | 5.06 | 40.87 | 0.02 | -0.36 |
Buscamos comportamientos “no estándares” o atípicos con respecto a las horas habituales. Al ser el horario un factor repetitivo (0-23:59) 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 Apagado fluctúa entre las 00:00 y las 23:59, con valores que giran en torno a una mediana de 12:08, presentando una desviación estándar de 5.06 horas y un comportamiento general heterogéneo (CV del 40.87%). Tal como se establece en la metodología estadística, con la ausencia de irregularidades extremas, se registra la presencia de 0 valores atípicos; asimismo, la distribución exhibe una asimetría prácticamente nula (0.02, distribución simétrica) y una concentración platicúrtica (-0.36). Esto indica que los eventos de apagado o fallos no se acumulan de manera aguda en un horario específico, sino que se distribuyen de forma aplanada y regular a lo largo de toda la jornada, lo cual refleja un comportamiento temporal normal y esperado para infraestructuras u operaciones continuas de 24 horas.