📦 1. Preparación del entorno de trabajo

Se configura el entorno en R, definiendo el directorio de trabajo y cargando los paquetes necesarios para asegurar un flujo de trabajo ordenado y reproducible.

# ------------------------------------------------------------
# Instalación y carga de paquetes
# ------------------------------------------------------------

# Establecer mirror de CRAN
options(repos = c(CRAN = "https://cloud.r-project.org"))

# Lista de paquetes necesarios para el curso
packages <- c(
  "openxlsx",   # lectura/escritura de Excel
  "terra",      # manejo de datos raster
  "zoo",        # series de tiempo
  "hydroTSM",   # herramientas hidrológicas
  "ggplot2",    # gráficos
  "ggnewscale", # múltiples escalas en gráficos
  "ggspatial",  # elementos espaciales en mapas
  "colorspace", # manejo de colores
  "tidyterra",  # integración terra + tidyverse
  "sf"          # datos vectoriales espaciales
)

# ------------------------------------------------------------
# Instalación de paquetes (solo si no están instalados)
# ------------------------------------------------------------
for (pkg in packages) {
  if (!requireNamespace(pkg, quietly = TRUE)) {
    install.packages(pkg)
  }
}

# ------------------------------------------------------------
# Carga de paquetes
# ------------------------------------------------------------
invisible(
  lapply(packages, function(pkg) {
    suppressPackageStartupMessages(
      library(pkg, character.only = TRUE)
    )
  })
)
## Warning: package 'ggplot2' was built under R version 4.5.2

📂 2. Importación e integración de datos hidrológicos

Se importan datos desde diferentes formatos (.csv y .xlsx)y se integran en una sola base, organizando la información para su análisis.

# Leer archivo CSV con datos de precip
data_csv <- read.csv(
  "./inputs/data_prec.csv",
  stringsAsFactors = FALSE
)

# Visualizar las primeras filas
head(data_csv)
##       Time   Prec
## 1 1/1/1981  53.45
## 2 1/2/1981 192.57
## 3 1/3/1981 386.57
## 4 1/4/1981 176.06
## 5 1/5/1981  83.82
## 6 1/6/1981  41.35
# leer datos en Excel con datos de caudal
data_xlsx <- read.xlsx('./inputs/data_runoff.xlsx',
                       sheet = 1, detectDates = TRUE)

# visualizar las primeras filas
head(data_xlsx)
##         Time Runoff
## 1 1981-01-01   10.7
## 2 1981-02-01   74.8
## 3 1981-03-01  213.1
## 4 1981-04-01   96.4
## 5 1981-05-01    4.7
## 6 1981-06-01    4.6
# extraer datos
time <- as.Date(data_csv$Time, format = '%d/%m/%Y')
prec <- data_csv$Prec
runoff <- data_xlsx$Runoff

# crear dataframe con datos combinados
database <- data.frame(Time = time, Prec = prec, Runoff = runoff)

# visualizar primeras y 煤ltimas filas
head(database)
##         Time   Prec Runoff
## 1 1981-01-01  53.45   10.7
## 2 1981-02-01 192.57   74.8
## 3 1981-03-01 386.57  213.1
## 4 1981-04-01 176.06   96.4
## 5 1981-05-01  83.82    4.7
## 6 1981-06-01  41.35    4.6
tail(database)
##           Time  Prec Runoff
## 115 1990-07-01 26.55    0.4
## 116 1990-08-01 18.59    0.6
## 117 1990-09-01 14.38    0.8
## 118 1990-10-01 14.73    8.9
## 119 1990-11-01 13.36   29.7
## 120 1990-12-01 14.74   26.2

💾 3. Exportación y almacenamiento de datos

Se muestran distintas formas de guardar datos en R, permitiendo conservar resultados y reutilizarlos en futuros análisis.

# exportar datos en distintos formatos

# CSV: formato de texto simple, compatible con Excel y otros programas
write.csv(database, './outputs/database.csv', row.names = FALSE)

# TXT: archivo de texto con separador TAB, 煤til para intercambio de datos
write.table(database, './outputs/database.txt',
            sep = "\t", row.names = FALSE)

# Excel: formato más amigable para usuarios no técnicos
write.xlsx(database, './outputs/database.xlsx',
           rowNames = FALSE)

# RData: guarda uno o varios objetos de R (se carga con load())
save(database, file = './outputs/database.RData')

# RDS: guarda un solo objeto de R (se lee con readRDS())
saveRDS(database, './outputs/database.rds')
# leer datos en formato RData
# carga uno o varios objetos directamente en el entorno de trabajo
load('./outputs/database.rdata')

# el objeto ya existe con su nombre original
head(database)
##         Time   Prec Runoff
## 1 1981-01-01  53.45   10.7
## 2 1981-02-01 192.57   74.8
## 3 1981-03-01 386.57  213.1
## 4 1981-04-01 176.06   96.4
## 5 1981-05-01  83.82    4.7
## 6 1981-06-01  41.35    4.6
# leer datos en formato RDS
# se debe asignar a un objeto al momento de leerlo
ans <- readRDS('./outputs/database.rds')

# visualizar contenido
head(ans)
##         Time   Prec Runoff
## 1 1981-01-01  53.45   10.7
## 2 1981-02-01 192.57   74.8
## 3 1981-03-01 386.57  213.1
## 4 1981-04-01 176.06   96.4
## 5 1981-05-01  83.82    4.7
## 6 1981-06-01  41.35    4.6

📊 4. Visualización básica de datos hidrológicos

Se elaboran gráficos como hidrogramas, hietogramas y diagramas de dispersión para analizar el comportamiento temporal y la relación entre variables.

# crear hidrograma (caudal vs tiempo)
plot(x = time, y = runoff,
     type = 'o', pch = 16, lwd = 1.8, col = 'darkblue',
     xlab = 'Tiempo [meses]',
     ylab = 'Escurrimiento [mm/mes]',
     main = 'Hidrograma')

# crear hietograma (precipitación vs tiempo)
barplot(height = prec, names.arg = time,
        col = 'dodgerblue',
        xlab = 'Tiempo [meses]',
        ylab = 'Precipitación [mm]',
        main = 'Hietograma')

# crear diagrama de dispersión (precipitación vs escorrentía)
plot(x = prec, y = runoff,
     cex = 1, pch = 21, col = 'black', bg = 'cyan',
     xlab = 'Precipitación [mm/mes]',
     ylab = 'Escorrimiento [mm/mes]',
     main = 'Diagrama de dispersión')

# agregar línea de regresión lineal
abline(lm(runoff ~ prec), col = 'red', lty = 2, lwd = 2)

# crear diagrama de cajas (distribución mensual)
bp <- t(matrix(runoff, nrow = 12))  # ordenar datos por año

boxplot(x = bp,
        border = 'black',
        boxwex = 0.6,
        staplewex = 0.2,
        col = 'gray90',
        medcol = "red",
        medlwd = 2,
        boxlty = 3,
        whisklty = 1,
        staplelwd = 1,
        pch = 20,
        names = month.abb,
        xlab = 'Mes',
        ylab = 'Escorrimiento [mm/mes]',
        main = 'Boxplot')

🔀 5. Organización de gráficos

Se utilizan herramientas para combinar múltiples gráficos en una sola figura y automatizar su generación, mejorando la presentación de resultados.

# png('./outputs/multipanel.png', units='px', height=500, width=700)

# ajustar parámetros gráficos
par(
  mfrow = c(2, 2),          # 4 gráficos (2x2)
  mar = c(4, 4, 1.5, 0.5),  # márgenes internos
  oma = c(0, 0, 1, 1),      # márgenes externos
  mgp = c(1.8, 0.3, 0),     # posición de textos en ejes
  cex = 0.7,                # tamaño general del texto
  cex.axis = 0.7,           # tamaño de ejes
  tck = -0.02               # marcas hacia adentro
)

# crear figuras
plot(x = time, y = runoff, type = 'l', lwd = 1.8, col = 'blue',
     xlab = 'Tiempo [meses]', ylab = 'Escorrentía [mm/mes]',
     main = 'Hidrograma')

barplot(height = prec, names.arg = time, col = 'darkred', border = 'darkred',
        xlab = 'Tiempo [meses]', ylab = 'Precipitación [mm]',
        main = 'Hietograma')

plot(x = prec, y = runoff, cex = 1, pch = 21, col = 'black', bg = 'cyan',
     xlab = 'Precipitación [mm/mes]', ylab = 'Escorrentía [mm/mes]',
     main = 'Diagrama de dispersión')
abline(lm(runoff ~ prec), col = 'red', lty = 2)

boxplot(x = t(matrix(runoff, nrow = 12)), border = 'black', boxwex = 0.3,
        staplewex = 0.2, col = 'gray90', medcol = "red", medlwd = 1,
        boxlty = 1, whisklty = 1, staplelwd = 1, pch = 20,
        names = month.abb, xlab = 'Mes', ylab = 'Escorrentía [mm/mes]',
        main = 'Boxplot')

# dev.off()

🗺️ 6. Lectura de datos geoespaciales de la cuenca

Se cargan datos espaciales como el modelo de elevación, la cuenca y la red de ríos, fundamentales para el análisis hidrológico.

# leer datos geoespaciales de la cuenca
dem <- rast('./inputs/dem.tif')
cat <- vect('./inputs/basin.shp')
riv <- vect('./inputs/rivers.shp')

# explorar atributos de los datos vectoriales
as.data.frame(cat)
##   Region     Area Vertiente Outlet COMID
## 1      A 5379.229   Pacific    ETI     1
# mostrar objeto vectorial
plot(cat)

# explorar propiedades del raster
print(dem)
## class       : SpatRaster 
## size        : 251, 429, 1  (nrow, ncol, nlyr)
## resolution  : 0.004166667, 0.004166667  (x, y)
## extent      : -80.89583, -79.10833, -4.383333, -3.3375  (xmin, xmax, ymin, ymax)
## coord. ref. : lon/lat WGS 84 (EPSG:4326) 
## source      : dem.tif 
## name        : dem
res(dem) # resolución
## [1] 0.004166667 0.004166667
crs(dem) # proyección
## [1] "GEOGCRS[\"WGS 84\",\n    ENSEMBLE[\"World Geodetic System 1984 ensemble\",\n        MEMBER[\"World Geodetic System 1984 (Transit)\"],\n        MEMBER[\"World Geodetic System 1984 (G730)\"],\n        MEMBER[\"World Geodetic System 1984 (G873)\"],\n        MEMBER[\"World Geodetic System 1984 (G1150)\"],\n        MEMBER[\"World Geodetic System 1984 (G1674)\"],\n        MEMBER[\"World Geodetic System 1984 (G1762)\"],\n        MEMBER[\"World Geodetic System 1984 (G2139)\"],\n        MEMBER[\"World Geodetic System 1984 (G2296)\"],\n        ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n            LENGTHUNIT[\"metre\",1]],\n        ENSEMBLEACCURACY[2.0]],\n    PRIMEM[\"Greenwich\",0,\n        ANGLEUNIT[\"degree\",0.0174532925199433]],\n    CS[ellipsoidal,2],\n        AXIS[\"geodetic latitude (Lat)\",north,\n            ORDER[1],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n        AXIS[\"geodetic longitude (Lon)\",east,\n            ORDER[2],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n    USAGE[\n        SCOPE[\"Horizontal component of 3D system.\"],\n        AREA[\"World.\"],\n        BBOX[-90,-180,90,180]],\n    ID[\"EPSG\",4326]]"
# mostrar objeto raster
plot(dem)

# enmascarar modelo de elevacion respecto de la cuenca
dem_cat <- mask(dem, cat)

# mostrar objeto raster enmascarado
plot(dem_cat)

🌄 7. Elaboración de mapas temáticos

Se construyen mapas que integran información espacial e hidrológica, facilitando la interpretación del territorio.

# Crear un mapa básico
  plot(dem_cat,
       col = terrain.colors(100, alpha=0.5),
       main = 'Mapa de la cuenca',
       xlab='Longitud',
       ylab='Latitud')
  plot(cat, lwd=1, add = TRUE)
  plot(riv, lwd=3, col = 'dodgerblue2', add = TRUE)
  grid()

# crear mapa de relieve
slp <- terrain(dem_cat, "slope", unit = "radians")
asp <- terrain(dem_cat, "aspect", unit = "radians")
hsd <- shade(slp, asp, angle=45, direction=300, normalize=TRUE)
dem.df <- as.data.frame(dem_cat, xy=TRUE)
names(dem.df)[3] <- "alt"
hsd.df <- as.data.frame(hsd, xy=TRUE)
names(hsd.df)[3] <- "hillshade"

# crear mapa con relieve sombreado
plt <- ggplot() +
  geom_raster(data = hsd.df, aes(x, y, fill = hillshade), show.legend = FALSE) +
  scale_fill_distiller(palette = "Greys") +
  new_scale_fill() +
  geom_raster(data = dem.df, aes(x, y, fill = alt), alpha = 0.7) +
  scale_fill_gradientn(colors = terrain.colors(10), name = "Elevación (msnm)") +
  geom_sf(data = st_as_sf(cat), color = 'black', fill = NA) +
  geom_sf(data = st_as_sf(riv), color = 'dodgerblue2', size = 0.3, linewidth = 1) +
  theme_bw() +
  labs(title = 'Cuenca de estudio', subtitle = 'Mapa de elevación',
       x = 'Longitud', y = 'Latitud') +
  annotation_scale(location = "br", width_hint = 0.3) +
  annotation_north_arrow(location = "tl", which_north = "true",
                         pad_x = unit(0.2, "in"), pad_y = unit(0.2, "in"),
                         style = north_arrow_fancy_orienteering)

# mostrar figura
print(plt)

# guardar figura en carpeta de salida
ggsave('./outputs/map_cuenca.png', plot=plt, units='px', height=1000, width=1500, scale=2)

```

📌 Clase 1 · Parte 1 → Clase 1 · Parte 2