Carga de datos y librerias Extraer la variable Conclusion
Variable analizada: Dia de ocurrencia del deslizamiento

La variable DIA representa el dia del mes en el que fue registrado cada deslizamiento. Sus valores son enteros comprendidos entre 1 y 31, por lo que se clasifica como cuantitativa discreta.

Objetivo

Analizar la distribucion de los deslizamientos registrados segun el dia del mes en que ocurrieron, mediante conteos, agrupacion por Sturges, diagramas de barras, ojivas, boxplot e indicadores descriptivos.

1. CARGA DE DATOS Y LIBRERIAS

library(readxl)
library(knitr)

archivo_dataset <- "dataset_deslizamientos_dia_hora.xlsx"

if (!file.exists(archivo_dataset)) {
  stop(
    paste(
      "No se encontro el archivo",
      archivo_dataset,
      "en la carpeta de trabajo."
    )
  )
}

hojas_disponibles <- excel_sheets(
  archivo_dataset
)

if ("Dataset_landslides" %in% hojas_disponibles) {
  hoja_dataset <- "Dataset_landslides"
} else {
  hoja_dataset <- hojas_disponibles[1]
}

datos <- read_excel(
  archivo_dataset,
  sheet = hoja_dataset
)

datos <- as.data.frame(
  datos
)

resumen_dataset <- data.frame(
  Elemento = c(
    "Archivo utilizado",
    "Hoja utilizada",
    "Numero de filas",
    "Numero de columnas",
    "Variable analizada",
    "Tipo de variable"
  ),
  Descripcion = c(
    basename(archivo_dataset),
    hoja_dataset,
    nrow(datos),
    ncol(datos),
    "Dia de ocurrencia del deslizamiento",
    "Cuantitativa discreta"
  )
)

knitr::kable(
  resumen_dataset,
  caption = "Resumen inicial del dataset"
)
Resumen inicial del dataset
Elemento Descripcion
Archivo utilizado dataset_deslizamientos_dia_hora.xlsx
Hoja utilizada Sheet1
Numero de filas 11033
Numero de columnas 32
Variable analizada Dia de ocurrencia del deslizamiento
Tipo de variable Cuantitativa discreta

2. EXTRAER LA VARIABLE

if (!"DIA" %in% names(datos)) {
  stop(
    paste(
      "No se encontro la columna DIA.",
      "Revise que el nombre sea exactamente DIA."
    )
  )
}

DIA_original <- suppressWarnings(
  as.numeric(datos$DIA)
)

total_registros <- length(
  DIA_original
)

datos_faltantes <- sum(
  is.na(DIA_original)
)

datos_fuera_dominio <- sum(
  !is.na(DIA_original) &
    (
      DIA_original < 1 |
      DIA_original > 31 |
      DIA_original %% 1 != 0
    )
)

DIA <- DIA_original[
  !is.na(DIA_original) &
    DIA_original >= 1 &
    DIA_original <= 31 &
    DIA_original %% 1 == 0
]

DIA <- as.integer(
  DIA
)

n <- length(
  DIA
)

if (n == 0) {
  stop(
    "No existen datos validos en la variable DIA."
  )
}

tabla_extraccion <- data.frame(
  Indicador = c(
    "Registros originales",
    "Datos faltantes",
    "Datos fuera del dominio",
    "Datos validos utilizados"
  ),
  Resultado = c(
    total_registros,
    datos_faltantes,
    datos_fuera_dominio,
    n
  )
)

knitr::kable(
  tabla_extraccion,
  caption = "Control de extraccion de la variable DIA"
)
Control de extraccion de la variable DIA
Indicador Resultado
Registros originales 11033
Datos faltantes 0
Datos fuera del dominio 0
Datos validos utilizados 11033

3. CONTEO

3.1. Conteo inicial

conteo_inicial <- data.frame(
  Indicador = c(
    "Numero de datos validos",
    "Valor minimo",
    "Valor maximo",
    "Valores diferentes"
  ),
  Resultado = c(
    n,
    min(DIA),
    max(DIA),
    length(unique(DIA))
  )
)

knitr::kable(
  conteo_inicial,
  caption = "Conteo inicial de la variable DIA"
)
Conteo inicial de la variable DIA
Indicador Resultado
Numero de datos validos 11033
Valor minimo 1
Valor maximo 31
Valores diferentes 31

3.2. Justificacion de la agrupacion

La variable DIA posee 31 valores posibles y el dataset contiene una gran cantidad de registros. Una tabla con el conteo de cada valor es util para la revision individual, pero para resumir la distribucion se aplica la regla de Sturges y se construyen intervalos agrupados.

El valor cero no se incluye porque no representa un dia del mes y se encuentra fuera del dominio de la variable:

\[ DIA=\{1,2,3,\ldots,31\} \]

3.3. Aplicacion de Sturges y definicion de clases

La regla de Sturges se expresa como:

\[ k=1+3.322\log_{10}(n) \]

valor_sturges <- 1 +
  3.322 *
  log10(n)

numero_clases <- ceiling(
  valor_sturges
)

valor_minimo <- min(
  DIA
)

valor_maximo <- max(
  DIA
)

limite_inicial <- valor_minimo - 0.5
limite_final <- valor_maximo + 0.5

rango_real <- limite_final -
  limite_inicial

amplitud_clase <- rango_real /
  numero_clases

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

limites_inferiores <- head(
  limites_clase,
  -1
)

limites_superiores <- tail(
  limites_clase,
  -1
)

marcas_clase <- (
  limites_inferiores +
    limites_superiores
) / 2

intervalos_texto <- paste0(
  "[",
  round(limites_inferiores, 2),
  " ; ",
  round(limites_superiores, 2),
  ")"
)

tabla_sturges <- data.frame(
  Elemento = c(
    "Numero de datos",
    "Resultado de Sturges",
    "Numero de clases",
    "Limite inicial",
    "Limite final",
    "Rango real",
    "Amplitud de clase"
  ),
  Resultado = c(
    n,
    valor_sturges,
    numero_clases,
    limite_inicial,
    limite_final,
    rango_real,
    amplitud_clase
  )
)

knitr::kable(
  tabla_sturges,
  digits = 4,
  caption = "Aplicacion de Sturges y definicion de clases"
)
Aplicacion de Sturges y definicion de clases
Elemento Resultado
Numero de datos 11033.0000
Resultado de Sturges 14.4298
Numero de clases 15.0000
Limite inicial 0.5000
Limite final 31.5000
Rango real 31.0000
Amplitud de clase 2.0667

Resultado de Sturges

Se obtuvieron 15 clases con una amplitud aproximada de 2.07 dias.

Las barras se presentan separadas para conservar la lectura de una variable discreta.

3.4. Calculo de ni y hi

clase_dia <- cut(
  DIA,
  breaks = limites_clase,
  include.lowest = TRUE,
  right = FALSE,
  dig.lab = 5
)

ni_agrupada <- as.numeric(
  table(clase_dia)
)

hi_agrupada <- ni_agrupada /
  n

Ni_agrupada <- cumsum(
  ni_agrupada
)

porcentaje_acumulado_ascendente <- c(
  0,
  Ni_agrupada /
    n *
    100
)

porcentaje_acumulado_descendente <- c(
  100,
  100 -
    Ni_agrupada /
    n *
    100
)

4. TABLA DE FRECUENCIAS

4.1. Tabla individual

dias_completos <- 1:31

conteo_dias <- table(
  factor(
    DIA,
    levels = dias_completos
  )
)

tabla_individual <- data.frame(
  Dia = dias_completos,
  ni = as.numeric(conteo_dias)
)

tabla_individual$hi <- tabla_individual$ni /
  n

knitr::kable(
  tabla_individual,
  digits = 4,
  col.names = c(
    "Dia del mes",
    "ni",
    "hi"
  ),
  caption = "Tabla Nro. 1. Conteo individual de los dias de ocurrencia"
)
Tabla Nro. 1. Conteo individual de los dias de ocurrencia
Dia del mes ni hi
1 341 0.0309
2 296 0.0268
3 346 0.0314
4 342 0.0310
5 347 0.0315
6 491 0.0445
7 399 0.0362
8 358 0.0324
9 361 0.0327
10 358 0.0324
11 353 0.0320
12 393 0.0356
13 313 0.0284
14 335 0.0304
15 392 0.0355
16 450 0.0408
17 388 0.0352
18 433 0.0392
19 433 0.0392
20 409 0.0371
21 369 0.0334
22 372 0.0337
23 302 0.0274
24 356 0.0323
25 324 0.0294
26 313 0.0284
27 358 0.0324
28 326 0.0295
29 306 0.0277
30 299 0.0271
31 170 0.0154

4.2. Tabla agrupada

tabla_agrupada <- data.frame(
  Clase = seq_len(numero_clases),
  Intervalo = intervalos_texto,
  ni = ni_agrupada,
  hi = hi_agrupada
)

knitr::kable(
  tabla_agrupada,
  digits = 4,
  col.names = c(
    "Clase",
    "Intervalo",
    "ni",
    "hi"
  ),
  caption = "Tabla Nro. 2. Distribucion agrupada de los dias mediante Sturges"
)
Tabla Nro. 2. Distribucion agrupada de los dias mediante Sturges
Clase Intervalo ni hi
1 [0.5 ; 2.57) 637 0.0577
2 [2.57 ; 4.63) 688 0.0624
3 [4.63 ; 6.7) 838 0.0760
4 [6.7 ; 8.77) 757 0.0686
5 [8.77 ; 10.83) 719 0.0652
6 [10.83 ; 12.9) 746 0.0676
7 [12.9 ; 14.97) 648 0.0587
8 [14.97 ; 17.03) 1230 0.1115
9 [17.03 ; 19.1) 866 0.0785
10 [19.1 ; 21.17) 778 0.0705
11 [21.17 ; 23.23) 674 0.0611
12 [23.23 ; 25.3) 680 0.0616
13 [25.3 ; 27.37) 671 0.0608
14 [27.37 ; 29.43) 632 0.0573
15 [29.43 ; 31.5) 469 0.0425

5. GRAFICAS

5.1. Diagrama de barras de cantidad por dia

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

posiciones_cantidad <- barplot(
  height = tabla_individual$ni,
  names.arg = tabla_individual$Dia,
  space = 0.20,
  col = "#E9D8C2",
  border = "#444444",
  main = paste0(
    "Grafica Nro. 1: Cantidad de deslizamientos\n",
    "segun el dia del mes"
  ),
  xlab = "Dia de ocurrencia",
  ylab = "Cantidad",
  cex.names = 0.72,
  las = 1,
  ylim = c(
    0,
    max(tabla_individual$ni) * 1.18
  )
)

text(
  x = posiciones_cantidad,
  y = tabla_individual$ni,
  labels = tabla_individual$ni,
  pos = 3,
  cex = 0.58,
  font = 2
)

5.2. Diagrama de barras de porcentaje por dia

porcentaje_individual <- tabla_individual$hi *
  100

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

posiciones_porcentaje <- barplot(
  height = porcentaje_individual,
  names.arg = tabla_individual$Dia,
  space = 0.20,
  col = "#CFA6B8",
  border = "#444444",
  main = paste0(
    "Grafica Nro. 2: Porcentaje de deslizamientos\n",
    "segun el dia del mes"
  ),
  xlab = "Dia de ocurrencia",
  ylab = "Porcentaje",
  cex.names = 0.72,
  las = 1,
  ylim = c(
    0,
    max(porcentaje_individual) * 1.18
  )
)

text(
  x = posiciones_porcentaje,
  y = porcentaje_individual,
  labels = round(porcentaje_individual, 2),
  pos = 3,
  cex = 0.52,
  font = 2
)

5.3. Diagrama de barras agrupadas mediante Sturges

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

posiciones_agrupadas <- barplot(
  height = ni_agrupada,
  names.arg = intervalos_texto,
  space = 0.25,
  col = "#E9D8C2",
  border = "#333333",
  main = paste0(
    "Grafica Nro. 3: Cantidad agrupada de deslizamientos\n",
    "segun los intervalos obtenidos mediante Sturges"
  ),
  xlab = "Intervalos del dia de ocurrencia",
  ylab = "Cantidad",
  las = 2,
  cex.names = 0.62,
  ylim = c(
    0,
    max(ni_agrupada) * 1.18
  )
)

text(
  x = posiciones_agrupadas,
  y = ni_agrupada,
  labels = ni_agrupada,
  pos = 3,
  cex = 0.75,
  font = 2
)

5.4. Ojivas ascendente y descendente

puntos_ojiva <- limites_clase

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

plot(
  puntos_ojiva,
  porcentaje_acumulado_ascendente,
  type = "o",
  pch = 16,
  lwd = 2,
  col = "#F39C12",
  main = paste0(
    "Grafica Nro. 4: Distribucion acumulada porcentual\n",
    "mediante ojivas ascendente y descendente"
  ),
  xlab = "Limites de clase del dia de ocurrencia",
  ylab = "Porcentaje",
  xlim = range(puntos_ojiva),
  ylim = c(0, 100),
  las = 1
)

grid(
  col = "gray85",
  lty = 1
)

lines(
  puntos_ojiva,
  porcentaje_acumulado_ascendente,
  type = "o",
  pch = 16,
  lwd = 2,
  col = "#F39C12"
)

lines(
  puntos_ojiva,
  porcentaje_acumulado_descendente,
  type = "o",
  pch = 16,
  lwd = 2,
  col = "#1F45FC"
)

legend(
  "bottomright",
  legend = c(
    "Ascendente (Menor que)",
    "Descendente (Mayor que)"
  ),
  col = c(
    "#F39C12",
    "#1F45FC"
  ),
  pch = 16,
  lty = 1,
  lwd = 2,
  bg = "white",
  bty = "o"
)

5.5. Diagrama de caja

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

boxplot(
  DIA,
  horizontal = TRUE,
  col = "#A7D3E8",
  border = "#222222",
  outline = TRUE,
  outpch = 1,
  outcol = "red",
  main = paste0(
    "Grafica Nro. 5: Diagrama de caja y bigotes\n",
    "del dia de ocurrencia"
  ),
  xlab = "Dia de ocurrencia",
  las = 1
)

5.6. Diagrama de barras agrupadas con boxplot superpuesto

frecuencia_maxima <- max(
  ni_agrupada
)

limite_y_superior <- frecuencia_maxima *
  1.25

posicion_boxplot <- frecuencia_maxima *
  0.55

altura_boxplot <- frecuencia_maxima *
  0.18

estadisticas_boxplot <- boxplot.stats(
  DIA
)

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_clase *
  0.08

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

plot(
  NA,
  xlim = c(limite_inicial, limite_final),
  ylim = c(0, limite_y_superior),
  main = paste0(
    "Grafica Nro. 6: Cantidad agrupada de deslizamientos\n",
    "con boxplot superpuesto"
  ),
  xlab = "Dia de ocurrencia",
  ylab = "Cantidad",
  xaxt = "n",
  las = 1
)

axis(
  side = 1,
  at = marcas_clase,
  labels = round(marcas_clase, 1),
  cex.axis = 0.75
)

for (i in seq_len(numero_clases)) {
  rect(
    xleft = limites_inferiores[i] + ancho_gap,
    ybottom = 0,
    xright = limites_superiores[i] - ancho_gap,
    ytop = ni_agrupada[i],
    col = "#E9D8C2",
    border = "#333333"
  )
}

text(
  x = marcas_clase,
  y = ni_agrupada,
  labels = ni_agrupada,
  pos = 3,
  cex = 0.78,
  font = 2
)

segments(
  x0 = bigote_inferior,
  y0 = posicion_boxplot,
  x1 = bigote_superior,
  y1 = posicion_boxplot,
  lty = 2,
  lwd = 1.5,
  col = "#333333"
)

segments(
  x0 = bigote_inferior,
  y0 = posicion_boxplot - altura_boxplot * 0.18,
  x1 = bigote_inferior,
  y1 = posicion_boxplot + altura_boxplot * 0.18,
  lwd = 1.5
)

segments(
  x0 = bigote_superior,
  y0 = posicion_boxplot - altura_boxplot * 0.18,
  x1 = bigote_superior,
  y1 = posicion_boxplot + altura_boxplot * 0.18,
  lwd = 1.5
)

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

segments(
  x0 = mediana_boxplot,
  y0 = posicion_boxplot - altura_boxplot / 2,
  x1 = mediana_boxplot,
  y1 = posicion_boxplot + altura_boxplot / 2,
  lwd = 3,
  col = "#111111"
)

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

6. INDICADORES

6.1. Calculo de indicadores

media_dia <- mean(
  DIA
)

mediana_dia <- median(
  DIA
)

frecuencias_moda <- table(
  DIA
)

frecuencia_maxima_moda <- max(
  frecuencias_moda
)

modas_dia <- as.numeric(
  names(
    frecuencias_moda[
      frecuencias_moda ==
        frecuencia_maxima_moda
    ]
  )
)

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

rango_texto <- paste0(
  min(DIA),
  " - ",
  max(DIA)
)

varianza_dia <- var(
  DIA
)

desviacion_dia <- sd(
  DIA
)

coeficiente_variacion <- (
  desviacion_dia /
    media_dia
) * 100

momento_2 <- mean(
  (DIA - media_dia)^2
)

momento_3 <- mean(
  (DIA - media_dia)^3
)

momento_4 <- mean(
  (DIA - media_dia)^4
)

asimetria_dia <- momento_3 /
  momento_2^(3 / 2)

curtosis_dia <- (
  momento_4 /
    momento_2^2
) - 3

valores_atipicos <- boxplot.stats(
  DIA
)$out

cantidad_atipicos <- length(
  valores_atipicos
)

texto_valores_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,
  "homogeneos",
  "heterogeneos"
)

interpretacion_asimetria <- ifelse(
  asimetria_dia > 0.10,
  "asimetria positiva hacia la derecha",
  ifelse(
    asimetria_dia < -0.10,
    "asimetria negativa hacia la izquierda",
    "distribucion aproximadamente simetrica"
  )
)

interpretacion_curtosis <- ifelse(
  curtosis_dia > 0.10,
  "leptocurtica",
  ifelse(
    curtosis_dia < -0.10,
    "platicurtica",
    "mesocurtica"
  )
)

clase_modal <- which.max(
  ni_agrupada
)

centro_intervalo_modal <- marcas_clase[
  clase_modal
]

tercio_1 <- limite_inicial +
  rango_real / 3

tercio_2 <- limite_inicial +
  2 * rango_real / 3

parte_variable <- ifelse(
  centro_intervalo_modal <= tercio_1,
  "parte baja",
  ifelse(
    centro_intervalo_modal <= tercio_2,
    "parte media",
    "parte alta"
  )
)

intervalo_modal_texto <- intervalos_texto[
  clase_modal
]

6.2. Tabla resumen de indicadores

tabla_indicadores <- data.frame(
  Medida = c(
    "Media",
    "Mediana",
    "Moda",
    "Rango",
    "Varianza",
    "Desviacion estandar",
    "Coeficiente de variacion (%)",
    "Asimetria",
    "Curtosis",
    "Valores atipicos"
  ),
  Valor = c(
    round(media_dia, 2),
    round(mediana_dia, 2),
    texto_moda,
    rango_texto,
    round(varianza_dia, 2),
    round(desviacion_dia, 2),
    round(coeficiente_variacion, 2),
    round(asimetria_dia, 2),
    round(curtosis_dia, 2),
    texto_valores_atipicos
  )
)

knitr::kable(
  tabla_indicadores,
  col.names = c(
    "Medida",
    "Valor"
  ),
  caption = "Tabla Nro. 3. Indicadores estadisticos de la variable DIA"
)
Tabla Nro. 3. Indicadores estadisticos de la variable DIA
Medida Valor
Media 15.53
Mediana 16
Moda 6
Rango 1 - 31
Varianza 73.03
Desviacion estandar 8.55
Coeficiente de variacion (%) 55.04
Asimetria 0.03
Curtosis -1.13
Valores atipicos No existen

7. CONCLUSION

Conclusion de la variable DIA

La variable dia de ocurrencia fluctua entre 1 y 31 dias, y sus valores giran alrededor de un promedio de 15.53 dias, con una desviacion estandar de 8.55 dias. De acuerdo con el coeficiente de variacion, los datos son heterogeneos. La mayor presencia de registros se encuentra en el intervalo [14.97 ; 17.03), ubicado en la parte media de la variable. La distribucion presenta distribucion aproximadamente simetrica y una forma platicurtica, sin presencia de valores atipicos. Este comportamiento no se considera beneficioso ni perjudicial por si mismo, pero permite identificar la concentracion temporal de los deslizamientos dentro del mes.