Carga de datos y librerías Extraer la variable Conclusión

1. CARGA DE DATOS Y LIBRERÍAS

library(readxl)
library(gt)
library(e1071)

datos <- read_excel(
  "dataset_deslizamientos_dia_hora.xlsx",
  sheet = 1
)

2. EXTRAER LA VARIABLE

HORA <- as.numeric(
  datos$HORA
)

HORA <- HORA[
  !is.na(HORA) &
  HORA >= 0 &
  HORA <= 23 &
  HORA %% 1 == 0
]

HORA <- as.integer(
  HORA
)

N_total <- length(
  HORA
)

3. CONTEO

La variable HORA presenta 24 valores posibles y una cantidad elevada de registros, por lo que se aplica la regla de Sturges para resumir su distribución mediante intervalos.

El valor cero se conserva porque pertenece al dominio horario y representa las 00:00. Su interpretación debe realizarse con cautela si la fuente original también utilizó cero para una hora no especificada.

3.1. Parámetros de clasificación

xmin <- min(HORA)
xmax <- max(HORA)

limite_inicial <- xmin - 0.5
limite_final <- xmax + 0.5

rango_real <- limite_final - limite_inicial

k <- ceiling(
  1 + 3.322 * log10(N_total)
)

amplitud <- rango_real / k

parametros <- data.frame(
  Observaciones = N_total,
  Minimo = xmin,
  Maximo = xmax,
  Rango = rango_real,
  Clases_Sturges = k,
  Amplitud = round(amplitud, 4)
)

parametros
##   Observaciones Minimo Maximo Rango Clases_Sturges Amplitud
## 1         11033      0     23    24             15      1.6

3.2. Definición de clases

limites_clase <- seq(
  from = limite_inicial,
  to = limite_final,
  length.out = k + 1
)

Li <- head(
  limites_clase,
  -1
)

Ls <- tail(
  limites_clase,
  -1
)

MC <- (
  Li + Ls
) / 2

clases_etiquetas <- paste0(
  "[",
  round(Li, 2),
  " ; ",
  round(Ls, 2),
  ")"
)

3.3. Cálculo de frecuencias

clase_hora <- cut(
  HORA,
  breaks = limites_clase,
  include.lowest = TRUE,
  right = FALSE
)

ni <- as.numeric(
  table(clase_hora)
)

hi <- ni / N_total

Hi_asc <- cumsum(
  hi
) * 100

Hi_dsc <- rev(
  cumsum(
    rev(hi)
  )
) * 100

4. TABLA DE FRECUENCIAS

4.1. Tabla individual

horas_completas <- 0:23

conteo_horas <- table(
  factor(
    HORA,
    levels = horas_completas
  )
)

tabla_individual <- data.frame(
  Hora = as.character(
    horas_completas
  ),
  ni = as.numeric(
    conteo_horas
  ),
  hi = as.numeric(
    conteo_horas
  ) / N_total
)

tabla_individual <- rbind(
  tabla_individual,
  data.frame(
    Hora = "TOTAL",
    ni = sum(
      tabla_individual$ni
    ),
    hi = sum(
      tabla_individual$hi
    )
  )
)

tabla_individual |>

  tabla_blanca(
    titulo = "Tabla Nro. 1",
    subtitulo = "Conteo individual de las horas de ocurrencia"
  ) |>

  fmt_number(
    columns = hi,
    decimals = 4
  ) |>

  cols_label(
    Hora = "Hora del día",
    ni = "ni",
    hi = "hi"
  ) |>

  cols_width(
    Hora ~ px(430),
    ni ~ px(220),
    hi ~ px(220)
  ) |>

  tab_style(
    style = cell_text(
      weight = "bold"
    ),
    locations = cells_body(
      rows = Hora == "TOTAL"
    )
  )
Tabla Nro. 1
Conteo individual de las horas de ocurrencia
Hora del día ni hi
0 5584 0.5061
1 78 0.0071
2 115 0.0104
3 101 0.0092
4 119 0.0108
5 93 0.0084
6 104 0.0094
7 98 0.0089
8 296 0.0268
9 604 0.0547
10 121 0.0110
11 83 0.0075
12 148 0.0134
13 537 0.0487
14 389 0.0353
15 448 0.0406
16 237 0.0215
17 219 0.0198
18 391 0.0354
19 205 0.0186
20 225 0.0204
21 148 0.0134
22 140 0.0127
23 550 0.0499
TOTAL 11033 1.0000
Elaborado por: Geología Grupo 1

4.2. Tabla agrupada

tabla_agrupada <- data.frame(
  Intervalo = clases_etiquetas,
  ni = ni,
  hi = hi
)

tabla_agrupada <- rbind(
  tabla_agrupada,
  data.frame(
    Intervalo = "TOTAL",
    ni = sum(ni),
    hi = sum(hi)
  )
)

tabla_agrupada |>

  tabla_blanca(
    titulo = "Tabla Nro. 2",
    subtitulo = "Distribución agrupada de las horas mediante Sturges"
  ) |>

  fmt_number(
    columns = hi,
    decimals = 4
  ) |>

  cols_label(
    Intervalo = "Intervalo",
    ni = "ni",
    hi = "hi"
  ) |>

  cols_width(
    Intervalo ~ px(430),
    ni ~ px(220),
    hi ~ px(220)
  ) |>

  tab_style(
    style = cell_text(
      weight = "bold"
    ),
    locations = cells_body(
      rows = Intervalo == "TOTAL"
    )
  )
Tabla Nro. 2
Distribución agrupada de las horas mediante Sturges
Intervalo ni hi
[-0.5 ; 1.1) 5662 0.5132
[1.1 ; 2.7) 115 0.0104
[2.7 ; 4.3) 220 0.0199
[4.3 ; 5.9) 93 0.0084
[5.9 ; 7.5) 202 0.0183
[7.5 ; 9.1) 900 0.0816
[9.1 ; 10.7) 121 0.0110
[10.7 ; 12.3) 231 0.0209
[12.3 ; 13.9) 537 0.0487
[13.9 ; 15.5) 837 0.0759
[15.5 ; 17.1) 456 0.0413
[17.1 ; 18.7) 391 0.0354
[18.7 ; 20.3) 430 0.0390
[20.3 ; 21.9) 148 0.0134
[21.9 ; 23.5) 690 0.0625
TOTAL 11033 1.0000
Elaborado por: Geología Grupo 1

5. GRÁFICAS

5.1. Cantidad de deslizamientos por hora

tabla_individual_sin_total <- tabla_individual[
  tabla_individual$Hora != "TOTAL",
]

grafica_barras(
  valores = tabla_individual_sin_total$ni,
  etiquetas = tabla_individual_sin_total$Hora,
  titulo = paste0(
    "Gráfica Nro. 1: Cantidad de deslizamientos\n",
    "según la hora del día"
  ),
  eje_x = "Hora de ocurrencia",
  eje_y = "Cantidad",
  color = "#E9D8C2",
  espacio = 0.20,
  rotacion = 1,
  tamano = 0.72
)

5.2. Porcentaje de deslizamientos por hora

porcentaje_individual <- (
  tabla_individual_sin_total$hi *
  100
)

grafica_barras(
  valores = porcentaje_individual,
  etiquetas = tabla_individual_sin_total$Hora,
  titulo = paste0(
    "Gráfica Nro. 2: Porcentaje de deslizamientos\n",
    "según la hora del día"
  ),
  eje_x = "Hora de ocurrencia",
  eje_y = "Porcentaje",
  color = "#CFA6B8",
  espacio = 0.20,
  rotacion = 1,
  tamano = 0.72
)

5.3. Diagrama de barras agrupadas

grafica_barras(
  valores = ni,
  etiquetas = clases_etiquetas,
  titulo = paste0(
    "Gráfica Nro. 3: Cantidad agrupada de deslizamientos\n",
    "según los intervalos obtenidos mediante Sturges"
  ),
  eje_x = "Intervalos de la hora de ocurrencia",
  eje_y = "Cantidad",
  color = "#E9D8C2",
  espacio = 0.25,
  rotacion = 2,
  tamano = 0.62
)

5.4. Diagrama de caja

par(
  mar = c(
    5,
    5,
    5,
    2
  )
)

boxplot(
  HORA,
  horizontal = TRUE,
  col = "#A7D3E8",
  border = "#222222",
  outline = TRUE,
  outpch = 1,
  outcol = "red",
  main = paste0(
    "Gráfica Nro. 4: Diagrama de caja y bigotes\n",
    "de la hora de ocurrencia"
  ),
  xlab = "Hora de ocurrencia"
)

5.5. Ojivas ascendente y descendente

puntos_ojiva <- seq_len(
  k
)

par(
  mar = c(
    8,
    5,
    5,
    10
  )
)

plot(
  puntos_ojiva,
  Hi_asc,
  type = "b",
  pch = 17,
  col = "#F39C12",
  xaxt = "n",
  xlab = "",
  ylab = "Porcentaje",
  ylim = c(
    0,
    100
  ),
  main = paste0(
    "Gráfica Nro. 5: Distribución acumulada porcentual\n",
    "mediante ojivas ascendente y descendente"
  )
)

grid(
  col = "gray85"
)

lines(
  puntos_ojiva,
  Hi_dsc,
  type = "b",
  pch = 16,
  col = "#1F45FC"
)

axis(
  side = 1,
  at = puntos_ojiva,
  labels = clases_etiquetas,
  las = 2,
  cex.axis = 0.65
)

mtext(
  "Intervalos de la hora de ocurrencia",
  side = 1,
  line = 6
)

legend(
  "topright",
  inset = c(
    -0.30,
    0
  ),
  xpd = TRUE,
  legend = c(
    "Ascendente (Menor que)",
    "Descendente (Mayor que)"
  ),
  col = c(
    "#F39C12",
    "#1F45FC"
  ),
  pch = c(
    17,
    16
  ),
  lty = 1,
  bty = "n"
)

5.6. Barras agrupadas con boxplot superpuesto

frecuencia_maxima <- max(
  ni
)

posicion_boxplot <- frecuencia_maxima *
  0.55

altura_boxplot <- frecuencia_maxima *
  0.18

estadisticas_boxplot <- boxplot.stats(
  HORA
)

bigote_inferior <- estadisticas_boxplot$stats[1]
primer_cuartil <- estadisticas_boxplot$stats[2]
mediana_boxplot <- estadisticas_boxplot$stats[3]
tercer_cuartil <- estadisticas_boxplot$stats[4]
bigote_superior <- estadisticas_boxplot$stats[5]
atipicos_boxplot <- estadisticas_boxplot$out

ancho_gap <- amplitud *
  0.08

par(
  mar = c(
    5,
    5,
    5,
    2
  )
)

plot(
  NA,
  xlim = c(
    limite_inicial,
    limite_final
  ),
  ylim = c(
    0,
    frecuencia_maxima * 1.25
  ),
  main = paste0(
    "Gráfica Nro. 6: Cantidad agrupada de deslizamientos\n",
    "con boxplot superpuesto"
  ),
  xlab = "Hora de ocurrencia",
  ylab = "Cantidad",
  xaxt = "n"
)

axis(
  side = 1,
  at = MC,
  labels = round(
    MC,
    1
  )
)

for (
  i in seq_len(k)
) {
  rect(
    xleft = Li[i] + ancho_gap,
    ybottom = 0,
    xright = Ls[i] - ancho_gap,
    ytop = ni[i],
    col = "#E9D8C2",
    border = "#333333"
  )
}

text(
  MC,
  ni,
  labels = ni,
  pos = 3,
  cex = 0.75,
  font = 2
)

segments(
  bigote_inferior,
  posicion_boxplot,
  bigote_superior,
  posicion_boxplot,
  lty = 2,
  lwd = 1.5
)

segments(
  bigote_inferior,
  posicion_boxplot - altura_boxplot * 0.18,
  bigote_inferior,
  posicion_boxplot + altura_boxplot * 0.18,
  lwd = 1.5
)

segments(
  bigote_superior,
  posicion_boxplot - altura_boxplot * 0.18,
  bigote_superior,
  posicion_boxplot + altura_boxplot * 0.18,
  lwd = 1.5
)

rect(
  primer_cuartil,
  posicion_boxplot - altura_boxplot / 2,
  tercer_cuartil,
  posicion_boxplot + altura_boxplot / 2,
  col = "#A7D3E8",
  border = "#222222",
  lwd = 1.3
)

segments(
  mediana_boxplot,
  posicion_boxplot - altura_boxplot / 2,
  mediana_boxplot,
  posicion_boxplot + altura_boxplot / 2,
  lwd = 3
)

if (
  length(atipicos_boxplot) > 0
) {
  points(
    atipicos_boxplot,
    rep(
      posicion_boxplot,
      length(atipicos_boxplot)
    ),
    pch = 1,
    col = "red",
    cex = 1.1
  )
}

6. INDICADORES

6.1. Cálculo de indicadores

media_hora <- mean(
  HORA
)

mediana_hora <- median(
  HORA
)

frecuencias_moda <- table(
  HORA
)

modas_hora <- as.numeric(
  names(
    frecuencias_moda[
      frecuencias_moda ==
      max(frecuencias_moda)
    ]
  )
)

texto_moda <- paste(
  modas_hora,
  collapse = ", "
)

varianza_hora <- var(
  HORA
)

desviacion_hora <- sd(
  HORA
)

coeficiente_variacion <- (
  desviacion_hora /
  media_hora
) * 100

asimetria_hora <- e1071::skewness(
  HORA
)

curtosis_hora <- e1071::kurtosis(
  HORA
)

valores_atipicos <- boxplot.stats(
  HORA
)$out

cantidad_atipicos <- length(
  valores_atipicos
)

texto_atipicos <- if (
  cantidad_atipicos == 0
) {
  "No existen"
} else {
  paste0(
    cantidad_atipicos,
    " valores entre ",
    min(valores_atipicos),
    " y ",
    max(valores_atipicos)
  )
}

interpretacion_cv <- ifelse(
  coeficiente_variacion <= 30,
  "homogéneos",
  "heterogéneos"
)

interpretacion_asimetria <- ifelse(
  asimetria_hora > 0.10,
  "asimetría positiva hacia la derecha",
  ifelse(
    asimetria_hora < -0.10,
    "asimetría negativa hacia la izquierda",
    "distribución aproximadamente simétrica"
  )
)

interpretacion_curtosis <- ifelse(
  curtosis_hora > 0.10,
  "leptocúrtica",
  ifelse(
    curtosis_hora < -0.10,
    "platicúrtica",
    "mesocúrtica"
  )
)

clase_modal <- which.max(
  ni
)

intervalo_modal <- clases_etiquetas[
  clase_modal
]

centro_modal <- MC[
  clase_modal
]

parte_variable <- ifelse(
  centro_modal <= limite_inicial + rango_real / 3,
  "parte baja",
  ifelse(
    centro_modal <= limite_inicial + 2 * rango_real / 3,
    "parte media",
    "parte alta"
  )
)

hora_cero_n <- sum(
  HORA == 0
)

hora_cero_pct <- (
  hora_cero_n /
  N_total
) * 100

6.2. Tabla de indicadores

tabla_indicadores <- data.frame(
  Medida = c(
    "Media",
    "Mediana",
    "Moda",
    "Rango",
    "Varianza",
    "Desviación estándar",
    "Coeficiente de variación (%)",
    "Asimetría",
    "Curtosis",
    "Valores atípicos"
  ),
  Valor = c(
    round(media_hora, 2),
    round(mediana_hora, 2),
    texto_moda,
    paste0(
      min(HORA),
      " - ",
      max(HORA)
    ),
    round(varianza_hora, 2),
    round(desviacion_hora, 2),
    round(coeficiente_variacion, 2),
    round(asimetria_hora, 2),
    round(curtosis_hora, 2),
    texto_atipicos
  )
)

tabla_indicadores |>

  tabla_blanca(
    titulo = "Tabla Nro. 3",
    subtitulo = "Indicadores estadísticos de la variable HORA"
  ) |>

  cols_label(
    Medida = "Medida",
    Valor = "Valor"
  ) |>

  cols_width(
    Medida ~ px(500),
    Valor ~ px(370)
  )
Tabla Nro. 3
Indicadores estadísticos de la variable HORA
Medida Valor
Media 6.84
Mediana 0
Moda 0
Rango 0 - 23
Varianza 64.84
Desviación estándar 8.05
Coeficiente de variación (%) 117.68
Asimetría 0.66
Curtosis -1.09
Valores atípicos No existen
Elaborado por: Geología Grupo 1

7. CONCLUSIÓN

La variable hora de ocurrencia fluctúa entre 0 y 23 horas, y sus valores giran alrededor de un promedio de 6.84 horas, con una desviación estándar de 8.05 horas. De acuerdo con el coeficiente de variación, los datos son heterogéneos. La mayor presencia de registros se encuentra en el intervalo [-0.5 ; 1.1), ubicado en la parte baja de la variable. La distribución presenta asimetría positiva hacia la derecha y una forma platicúrtica, sin presencia de valores atípicos. Este comportamiento no se considera beneficioso ni perjudicial por sí mismo, pero permite identificar la concentración temporal de los registros a lo largo del día. La hora 0 representa 50.61% de los datos, por lo que debe confirmarse si todos esos registros corresponden realmente a las 00:00 o si algunos representan una hora no especificada.