Análisis de series hidrometeorológicas de precipitación en la estación C02 Rumihurco

archivo <- "C:/Users/Usuario/Downloads/C02-Rumihurco_Precipitación-Subhorario_validado.csv"

data0 <- read.csv(
  archivo,
  stringsAsFactors = FALSE
)

str(data0)
## 'data.frame':    736416 obs. of  2 variables:
##  $ fecha: chr  "2019/01/01 00:00:00" "2019/01/01 00:05:00" "2019/01/01 00:10:00" "2019/01/01 00:15:00" ...
##  $ valor: num  0 0 0 0 0 0 0 0 0 0 ...
head(data0)
##                 fecha valor
## 1 2019/01/01 00:00:00     0
## 2 2019/01/01 00:05:00     0
## 3 2019/01/01 00:10:00     0
## 4 2019/01/01 00:15:00     0
## 5 2019/01/01 00:20:00     0
## 6 2019/01/01 00:25:00     0

1 Carga de datos

archivo <- file.choose()

data0 <- read.csv(
  archivo,
  stringsAsFactors = FALSE
)

str(data0)
## 'data.frame':    736416 obs. of  2 variables:
##  $ fecha: chr  "2019/01/01 00:00:00" "2019/01/01 00:05:00" "2019/01/01 00:10:00" "2019/01/01 00:15:00" ...
##  $ valor: num  0 0 0 0 0 0 0 0 0 0 ...
head(data0)
##                 fecha valor
## 1 2019/01/01 00:00:00     0
## 2 2019/01/01 00:05:00     0
## 3 2019/01/01 00:10:00     0
## 4 2019/01/01 00:15:00     0
## 5 2019/01/01 00:20:00     0
## 6 2019/01/01 00:25:00     0

2 Conversión de fecha

data0$fecha <- as.POSIXct(
  data0$fecha,
  format = "%Y/%m/%d %H:%M:%S"
)

range(data0$fecha)
## [1] "2019-01-01 00:00:00 -05" "2025-12-31 23:55:00 -05"

3 Serie temporal de precipitación a 5 minutos

plot_5min <- ggplot(
  data = data0,
  aes(
    x = fecha,
    y = valor
  )
) +
  geom_line() +
  labs(
    title = "Serie temporal de precipitación - 5 min",
    x = "Fecha",
    y = "Precipitación [mm]",
    caption = "Elaborado por: Arelys Quimbitaz"
  ) +
  theme_bw() +
  theme(
    plot.title = element_text(
      hjust = 0.5,
      face = "bold"
    ),
    plot.caption = element_text(
      hjust = 1
    )
  )

plot_5min

4 Agregación temporal de la precipitación

library(zoo)

# Crear objeto zoo con la serie de 5 minutos
zdata5min <- zoo(
  data0$valor,
  data0$fecha
)

# 15 minutos
zdata15min <- aggregate(
  zdata5min,
  cut(index(zdata5min), "15 min"),
  function(x) sum(x, na.rm = TRUE)
)

# 30 minutos
zdata30min <- aggregate(
  zdata5min,
  cut(index(zdata5min), "30 min"),
  function(x) sum(x, na.rm = TRUE)
)

# 120 minutos
zdata120min <- aggregate(
  zdata5min,
  cut(index(zdata5min), "2 hours"),
  function(x) sum(x, na.rm = TRUE)
)

# 1440 minutos = 1 día
zdata1440min <- aggregate(
  zdata5min,
  as.Date(index(zdata5min)),
  function(x) sum(x, na.rm = TRUE)
)

# Revisar
head(zdata15min)
##          2019-01-01 2019-01-01 00:15:00 2019-01-01 00:30:00 2019-01-01 00:45:00 
##                   0                   0                   0                   0 
## 2019-01-01 01:00:00 2019-01-01 01:15:00 
##                   0                   0
head(zdata30min)
##          2019-01-01 2019-01-01 00:30:00 2019-01-01 01:00:00 2019-01-01 01:30:00 
##                   0                   0                   0                   0 
## 2019-01-01 02:00:00 2019-01-01 02:30:00 
##                   0                   0
head(zdata120min)
##          2019-01-01 2019-01-01 02:00:00 2019-01-01 04:00:00 2019-01-01 06:00:00 
##                   0                   0                   0                   0 
## 2019-01-01 08:00:00 2019-01-01 10:00:00 
##                   0                   0
head(zdata1440min)
## 2019-01-01 2019-01-02 2019-01-03 2019-01-04 2019-01-05 2019-01-06 
##          0          0          0          0          0          3
# Unir las series para graficarlas

data5 <- data.frame(
  fecha = index(zdata5min),
  precipitacion = as.numeric(zdata5min),
  duracion = "5 min"
)

data15 <- data.frame(
  fecha = as.POSIXct(index(zdata15min)),
  precipitacion = as.numeric(zdata15min),
  duracion = "15 min"
)

data30 <- data.frame(
  fecha = as.POSIXct(index(zdata30min)),
  precipitacion = as.numeric(zdata30min),
  duracion = "30 min"
)

data120 <- data.frame(
  fecha = as.POSIXct(index(zdata120min)),
  precipitacion = as.numeric(zdata120min),
  duracion = "120 min"
)

data1440 <- data.frame(
  fecha = as.POSIXct(index(zdata1440min)),
  precipitacion = as.numeric(zdata1440min),
  duracion = "1440 min"
)

series_total <- rbind(
  data5,
  data15,
  data30,
  data120,
  data1440
)

series_total$duracion <- factor(
  series_total$duracion,
  levels = c(
    "5 min",
    "15 min",
    "30 min",
    "120 min",
    "1440 min"
  )
)
plot_series <- ggplot(
  data = series_total,
  aes(
    x = fecha,
    y = precipitacion
  )
) +
  geom_line(
    linewidth = 0.25,
    na.rm = TRUE
  ) +
  facet_wrap(
    ~ duracion,
    ncol = 1,
    scales = "free_y"
  ) +
  labs(
    title = "Series de precipitación - Estación C02 Rumihurco",
    x = "Fecha",
    y = "Precipitación [mm]",
    caption = "Elaborado por: Arelys Quimbitaz"
  ) +
  theme_bw() +
  theme(
    plot.title = element_text(
      hjust = 0.5,
      face = "bold"
    ),
    strip.text = element_text(
      face = "bold"
    ),
    plot.caption = element_text(
      hjust = 1
    )
  )

plot_series

# Función para estadística descriptiva
estadistica_serie <- function(x) {
  
  x <- x[!is.na(x)]
  
  promedio <- mean(x)
  mediana <- median(x)
  desviacion <- sd(x)
  asimetria <- moments::skewness(x)
  coef_variacion <- (desviacion / promedio) * 100
  curtosis <- moments::kurtosis(x)
  
  return(
    c(
      Promedio = promedio,
      Mediana = mediana,
      Desviacion_estandar = desviacion,
      Coef_asimetria = asimetria,
      Coef_variacion = coef_variacion,
      Curtosis = curtosis
    )
  )
}





# Calculae estadistica para cada duración 

est5 <- estadistica_serie(
  as.numeric(zdata5min)
)

est15 <- estadistica_serie(
  as.numeric(zdata15min)
)

est30 <- estadistica_serie(
  as.numeric(zdata30min)
)

est120 <- estadistica_serie(
  as.numeric(zdata120min)
)

est1440 <- estadistica_serie(
  as.numeric(zdata1440min)
)


# Crear tabla final

tabla_estadistica <- data.frame(
  Duracion = c(
    "5 min",
    "15 min",
    "30 min",
    "120 min",
    "1440 min"
  ),
  
  rbind(
    est5,
    est15,
    est30,
    est120,
    est1440
  )
)


# Redondear a 3 decimales

tabla_estadistica[, -1] <- round(
  tabla_estadistica[, -1],
  3
)


tabla_estadistica
##         Duracion Promedio Mediana Desviacion_estandar Coef_asimetria
## est5       5 min    0.011       0               0.090         18.989
## est15     15 min    0.031       0               0.236         16.573
## est30     30 min    0.063       0               0.420         13.662
## est120   120 min    0.252       0               1.204          8.143
## est1440 1440 min    3.020       0               6.365          3.142
##         Coef_variacion Curtosis
## est5           819.400  571.696
## est15          748.272  425.075
## est30          666.640  287.948
## est120         478.196   91.095
## est1440        210.745   14.641
# Histograma para las diferentes duraciones

hist_data <- series_total[
  !is.na(series_total$precipitacion) &
    series_total$precipitacion > 0,
]

plot_hist <- ggplot(
  data = hist_data,
  aes(x = precipitacion)
) +
  geom_histogram(
    bins = 30,
    color = "black",
    fill = "grey75"
  ) +
  facet_wrap(
    ~ duracion,
    scales = "free",
    ncol = 2
  ) +
  labs(
    title = "Histogramas de precipitación - Estación C02 Rumihurco",
    x = "Precipitación [mm]",
    y = "Frecuencia",
    caption = "Elaborado por: Arelys Quimbitaz"
  ) +
  theme_bw() +
  theme(
    plot.title = element_text(
      hjust = 0.5,
      face = "bold"
    ),
    strip.text = element_text(
      face = "bold"
    ),
    plot.caption = element_text(
      hjust = 1
    )
  )

plot_hist

# Intensidades para cada duración

i5 <- zdata5min / (5 / 60)
i15 <- zdata15min / (15 / 60)
i30 <- zdata30min / (30 / 60)
i120 <- zdata120min / (120 / 60)
i1440 <- zdata1440min / (1440 / 60)


# Función segura para obtener máximos anuales

max_anual <- function(serie) {
  
  fechas <- index(serie)
  
  fechas <- as.POSIXct(
    fechas,
    origin = "1970-01-01"
  )
  
  anio <- format(
    fechas,
    "%Y"
  )
  
  resultado <- aggregate(
    as.numeric(serie),
    by = list(anio = anio),
    FUN = function(x) {
      max(
        x,
        na.rm = TRUE
      )
    }
  )
  
  return(resultado)
}


# Máximos anuales

max5 <- max_anual(i5)
max15 <- max_anual(i15)
max30 <- max_anual(i30)
max120 <- max_anual(i120)
max1440 <- max_anual(i1440)


# Revisar resultados

max5
##   anio    x
## 1 2019 68.4
## 2 2020 57.6
## 3 2021 58.8
## 4 2022 49.2
## 5 2023 62.4
## 6 2024 43.2
## 7 2025 76.8
max15
##   anio    x
## 1 2019 44.0
## 2 2020 28.0
## 3 2021 49.6
## 4 2022 43.6
## 5 2023 45.6
## 6 2024 29.6
## 7 2025 46.4
max30
##   anio    x
## 1 2019 39.0
## 2 2020 21.8
## 3 2021 33.6
## 4 2022 30.4
## 5 2023 27.6
## 6 2024 22.8
## 7 2025 31.8
max120
##   anio     x
## 1 2019  9.80
## 2 2020  9.85
## 3 2021 12.70
## 4 2022  8.55
## 5 2023 11.00
## 6 2024  8.00
## 7 2025 12.75
max1440
##   anio        x
## 1 2019 1.625000
## 2 2020 1.383333
## 3 2021 2.050000
## 4 2022 1.375000
## 5 2023 1.675000
## 6 2024 1.904167
## 7 2025 1.912500
## 8 2026 0.000000
# Preparar máximos anuales de cada duración

m5 <- max5
names(m5) <- c("Anio", "X5min")

m15 <- max15
names(m15) <- c("Anio", "X15min")

m30 <- max30
names(m30) <- c("Anio", "X30min")

m120 <- max120
names(m120) <- c("Anio", "X120min")

m1440 <- max1440
names(m1440) <- c("Anio", "X1440min")


# Eliminar cualquier año fuera del periodo 2019-2025

m5 <- m5[m5$Anio >= "2019" & m5$Anio <= "2025", ]
m15 <- m15[m15$Anio >= "2019" & m15$Anio <= "2025", ]
m30 <- m30[m30$Anio >= "2019" & m30$Anio <= "2025", ]
m120 <- m120[m120$Anio >= "2019" & m120$Anio <= "2025", ]
m1440 <- m1440[m1440$Anio >= "2019" & m1440$Anio <= "2025", ]


# Unir las cinco duraciones por año

tabla_maximos <- merge(m5, m15, by = "Anio")
tabla_maximos <- merge(tabla_maximos, m30, by = "Anio")
tabla_maximos <- merge(tabla_maximos, m120, by = "Anio")
tabla_maximos <- merge(tabla_maximos, m1440, by = "Anio")


# Mostrar tabla

tabla_maximos
##   Anio X5min X15min X30min X120min X1440min
## 1 2019  68.4   44.0   39.0    9.80 1.625000
## 2 2020  57.6   28.0   21.8    9.85 1.383333
## 3 2021  58.8   49.6   33.6   12.70 2.050000
## 4 2022  49.2   43.6   30.4    8.55 1.375000
## 5 2023  62.4   45.6   27.6   11.00 1.675000
## 6 2024  43.2   29.6   22.8    8.00 1.904167
## 7 2025  76.8   46.4   31.8   12.75 1.912500
# Pasar la tabla a formato largo
library(reshape2)

maximos_largos <- melt(
  tabla_maximos,
  id.vars = "Anio",
  variable.name = "Duracion",
  value.name = "Intensidad"
)

# Cambiar nombres de las duraciones
maximos_largos$Duracion <- factor(
  maximos_largos$Duracion,
  levels = c(
    "X5min",
    "X15min",
    "X30min",
    "X120min",
    "X1440min"
  ),
  labels = c(
    "5 min",
    "15 min",
    "30 min",
    "120 min",
    "1440 min"
  )
)

# Año como número
maximos_largos$Anio <- as.numeric(
  as.character(maximos_largos$Anio)
)

# Gráfico
plot_maximos <- ggplot(
  data = maximos_largos,
  aes(
    x = Anio,
    y = Intensidad,
    color = Duracion,
    group = Duracion
  )
) +
  geom_line(
    linewidth = 0.8
  ) +
  geom_point(
    size = 2
  ) +
  labs(
    title = "Máximas anuales de intensidad - Estación C02 Rumihurco",
    x = "Año",
    y = "Intensidad máxima anual [mm/h]",
    color = "Duración",
    caption = "Elaborado por: Arelys Quimbitaz"
  ) +
  scale_x_continuous(
    breaks = 2019:2025
  ) +
  theme_bw() +
  theme(
    plot.title = element_text(
      hjust = 0.5,
      face = "bold"
    ),
    legend.position = "bottom",
    plot.caption = element_text(
      hjust = 1
    )
  )

plot_maximos

# Histogramas de máximas anuales de intensidad

plot_hist_max <- ggplot(
  data = maximos_largos,
  aes(x = Intensidad)
) +
  geom_histogram(
    bins = 4,
    color = "black",
    fill = "grey75"
  ) +
  facet_wrap(
    ~ Duracion,
    scales = "free_x",
    ncol = 2
  ) +
  labs(
    title = "Histogramas de máximas anuales de intensidad - Estación C02 Rumihurco",
    x = "Intensidad máxima anual [mm/h]",
    y = "Frecuencia",
    caption = "Elaborado por: Arelys Quimbita "
  ) +
  theme_bw() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    strip.text = element_text(face = "bold"),
    plot.caption = element_text(hjust = 1)
  )

plot_hist_max

5 Comentario e interpretación de resultados

5.1 Comportamiento de las series de precipitación

Las series de precipitación muestran que, a medida que aumenta la duración de agregación, también aumenta la altura de precipitación acumulada. En la serie de 5 minutos predominan valores pequeños y numerosos periodos sin precipitación, mientras que para duraciones mayores, como 120 y 1440 minutos, los valores acumulados son mayores debido a que se suma la precipitación ocurrida durante intervalos de tiempo más largos.

También se observan periodos con ausencia de información en la serie, lo cual se refleja como espacios sin datos en las gráficas.

5.2 Estadística descriptiva

Los resultados muestran un aumento progresivo del promedio al aumentar la duración de agregación. El promedio pasa aproximadamente de 0.011 mm para 5 minutos a 3.020 mm para 1440 minutos. Esto se debe a que los intervalos de mayor duración acumulan una mayor cantidad de precipitación.

La mediana es igual a cero en todas las duraciones analizadas, lo que indica que una gran proporción de los intervalos no registra precipitación.

La desviación estándar también aumenta conforme aumenta la duración. Para 5 minutos se obtuvo aproximadamente 0.090 mm, mientras que para 1440 minutos aumenta hasta aproximadamente 6.365 mm. Este comportamiento está asociado con el incremento de la magnitud de los valores acumulados.

El coeficiente de asimetría disminuye al aumentar la duración. Para la serie de 5 minutos alcanza aproximadamente 18.99, mientras que para 1440 minutos disminuye a aproximadamente 3.14. Esto indica que las series de corta duración presentan una distribución fuertemente asimétrica hacia la derecha, debido a la presencia de numerosos valores pequeños y pocos eventos de precipitación intensa.

El coeficiente de variación también disminuye notablemente con el incremento de la duración, desde valores superiores al 800 % para 5 minutos hasta aproximadamente 211 % para 1440 minutos. Por lo tanto, las series de corta duración presentan una mayor variabilidad relativa respecto a su valor promedio.

En general, al aumentar la duración de agregación, la distribución de la precipitación se vuelve menos variable y menos asimétrica.

5.3 Histogramas de las series completas

Los histogramas muestran una distribución sesgada hacia la derecha para todas las duraciones. Existe una elevada concentración de eventos de precipitación de pequeña magnitud y una menor cantidad de eventos con valores altos.

Para las duraciones de 5, 15 y 30 minutos, la concentración de observaciones cerca de valores pequeños es mayor, mientras que en las duraciones de 120 y 1440 minutos el rango de precipitación aumenta debido a la acumulación temporal.

Por lo tanto, el incremento de la duración produce una distribución con mayores valores de precipitación acumulada y una reducción progresiva de la asimetría relativa.

5.4 Máximas anuales de intensidad

Las máximas anuales de intensidad muestran un comportamiento inverso al observado en las alturas acumuladas. Las mayores intensidades corresponden a las duraciones más cortas.

En la duración de 5 minutos se observan intensidades máximas anuales superiores a 40 mm/h y que alcanzan valores cercanos a 77 mm/h, mientras que para 1440 minutos las intensidades se encuentran aproximadamente entre 1 y 2 mm/h.

Este comportamiento se explica porque la intensidad se obtiene dividiendo la precipitación acumulada para la duración del evento expresada en horas. Por esta razón, un evento intenso registrado en un intervalo corto genera una intensidad elevada, mientras que al incrementar la duración la precipitación se distribuye sobre un intervalo de tiempo mayor y la intensidad promedio disminuye.

También se observa variabilidad interanual, ya que los máximos de intensidad cambian de un año a otro.

5.5 Histogramas de máximas anuales

Los histogramas de máximas anuales muestran la distribución de los máximos registrados entre 2019 y 2025 para cada duración.

Debido a que se dispone de siete años de información, cada histograma contiene solamente siete observaciones. Por esta razón, la forma de estas distribuciones es menos continua que la observada en los histogramas de las series completas.

A pesar de ello, se identifica claramente que las máximas anuales de intensidad disminuyen conforme aumenta la duración. Las mayores intensidades corresponden a 5 minutos, seguidas por 15, 30, 120 y finalmente 1440 minutos.

5.6 Conclusión

El análisis demuestra que la duración temporal tiene una influencia importante sobre las características estadísticas de las series de precipitación.

Al aumentar la duración de agregación, aumenta la precipitación acumulada y la desviación estándar en términos absolutos, mientras que disminuyen la asimetría y el coeficiente de variación. Esto indica que las series agregadas a mayores duraciones presentan un comportamiento relativamente más estable.

Por otra parte, las intensidades máximas anuales disminuyen conforme aumenta la duración, debido a que los eventos de alta intensidad se concentran principalmente en intervalos cortos de tiempo.

En consecuencia, las duraciones pequeñas representan mejor los eventos intensos de corta duración, mientras que las duraciones grandes permiten analizar el comportamiento acumulado de la precipitación.