12  Mapas de precipitación

12.1 Introducción

Este capítulo muestra como elaborar mapas de precipitación con base en datos de diversas fuentes. El contenido está basado en el tutorial de Milos Popovic How to Create Amazing Precipitation Maps with R in 2D and 3D.

Los datos de precipitación se descargan con el paquete pRecipe para un polígono (o polígonos) definido mediante el paquete giscoR.

12.2 Instalación y carga de paquetes

# Paquete para descargar, visualizar y analizar datos de precipitación
install.packages("pRecipe")

# Paquete para descargar datos de GISCO (Geographic Information System of the Commission)
install.packages("giscoR")

# Paquete para calcular intervalos de clasificación para datos numéricos
install.packages("classInt")
# Colección de paquetes de Tidyverse
library(tidyverse)

# Cálculo de intervalos de clasificación
library(classInt)

# Manejo de datos vectoriales
library(sf)

# Manejo de datos raster
library(terra)

# Datos de precipitación
library(pRecipe)

# Datos de GISCO
library(giscoR)

12.3 Obtención del polígono del país

En el siguiente bloque se especifica el país (o los países) para el que se van a descargar datos de precipitación.

# Código ISO3 del país
pais <- "BRA"
# pais <- c("PAN", "CRI", "NIC")

Se utiliza la función giscoR::gisco_get_countries() para obtener el polígono del país.

# Obtener polígono del país
poligono_pais <- giscoR::gisco_get_countries(
    country = pais,
    resolution = "1"
)

# Desplegar el polígono
plot(poligono_pais$geometry)

12.4 Obtención de datos de precipitación

Se utiliza la función pRecipe::download_data() para la descarga de los datos de precipitación.

# Descarga
pRecipe::download_data(
    dataset = "mswep", # conjunto de datos
    path = path.expand("~"), # ruta de descarga
    domain = "raw", # dominio de la descarga
    timestep = "yearly" # periodo
)

# Archivo descargado
list.files(path.expand("~"), pattern = "\\.nc$")
[1] "mswep_tp_mm_global_197902_202301_025_yearly.nc"

Se recortan los datos de precipitación con el polígono del país.

# Lectura y recorte de los datos de precipitación
# Debe leerse el archivo que se descargó anteriormente
precipitacion <- 
  terra::rast( # lectura
    file.path(path.expand("~"), "mswep_tp_mm_global_197902_202301_025_yearly.nc")
  ) |>
  terra::crop(# recorte
    poligono_pais
  )
# Metadatos
precipitacion
class       : SpatRaster 
dimensions  : 156, 181, 45  (nrow, ncol, nlyr)
resolution  : 0.25, 0.25  (x, y)
extent      : -74, -28.75, -33.75, 5.25  (xmin, xmax, ymin, ymax)
coord. ref. : lon/lat WGS 84 
source(s)   : memory
varname     : precipitation 
names       : preci~ion_1,  preci~ion_2,  preci~ion_3,  preci~ion_4,  preci~ion_5, preci~ion_6, ... 
min values  :       0.000, 4.167708e-02,    0.4929991,    0.2152826,    0.1319321,    9.284902, ... 
max values  :    8710.541, 5.184138e+03, 9338.0312500, 6341.0307617, 4198.7851562, 6542.886719, ... 
unit        :  mm month-1,   mm month-1,   mm month-1,   mm month-1,   mm month-1,  mm month-1, ... 
time (days) : 1979-01-01 to 2023-01-01 

Se despliega un mapa básico de los datos de precipitación recortados.

terra::plot(precipitacion[[1]])
plot(poligono_pais$geometry, add=TRUE)

12.5 Transformación

Los datos raster de precipitación se transforman a una dataframe para que puedan ser visualizados mediante ggplot2.

# Cambiar nombres de las bandas
names(precipitacion) <- 1979:2023
print(precipitacion)
class       : SpatRaster 
dimensions  : 156, 181, 45  (nrow, ncol, nlyr)
resolution  : 0.25, 0.25  (x, y)
extent      : -74, -28.75, -33.75, 5.25  (xmin, xmax, ymin, ymax)
coord. ref. : lon/lat WGS 84 
source(s)   : memory
varname     : precipitation 
names       :       1979,         1980,         1981,         1982,         1983,        1984, ... 
min values  :      0.000, 4.167708e-02,    0.4929991,    0.2152826,    0.1319321,    9.284902, ... 
max values  :   8710.541, 5.184138e+03, 9338.0312500, 6341.0307617, 4198.7851562, 6542.886719, ... 
unit        : mm month-1,   mm month-1,   mm month-1,   mm month-1,   mm month-1,  mm month-1, ... 
time (days) : 1979-01-01 to 2023-01-01 
# Transformar el raster a un dataframe
# para graficarlo en ggplot2
precipitacion_df <- 
  precipitacion |>
    as.data.frame(xy = TRUE) |>
    tidyr::pivot_longer( # convertir de "formato largo" a "formato corto"
        !c("x", "y"),
        names_to = "year",
        values_to = "precipitation"
  ) |>
  dplyr::filter(year < 2023) # filtrado de datos

print(head(precipitacion_df))
# A tibble: 6 × 4
      x     y year  precipitation
  <dbl> <dbl> <chr>         <dbl>
1 -73.9  5.12 1979          1518.
2 -73.9  5.12 1980          1140.
3 -73.9  5.12 1981          2053.
4 -73.9  5.12 1982          1629.
5 -73.9  5.12 1983          1490.
6 -73.9  5.12 1984          1561.

12.6 Visualización

Para visualizar los datos, primero se crea un estilo personalizado para ggplot2.

# Estilo
estilo_precipitacion <- function() {
  theme_minimal() +
    theme(
      axis.line = element_blank(),
      axis.title.x = element_blank(),
      axis.title.y = element_blank(),
      axis.text.x = element_blank(),
      axis.text.y = element_blank(),
      legend.position = "right",
      legend.title = element_text(size = 11, color = "grey10"),
      legend.text = element_text(size = 10, color = "grey10"),
      panel.grid.major = element_line(color = NA),
      panel.grid.minor = element_line(color = NA),
      plot.background = element_rect(fill = NA, color = NA),
      legend.background = element_rect(fill = "white", color = NA),
      panel.border = element_rect(fill = NA, color = NA),
      plot.margin = unit(c(
        t = 0,
        r = 0,
        b = 0,
        l = 0
      ), "lines")
    )
}

# Intervalos para las clases del mapa
intervalos <- classInt::classIntervals(
    precipitacion_df$precipitation,
    n = 5,
    style = "equal"
)$brks

# Colores para el mapa
colores <- hcl.colors(
    n = length(intervalos),
    palette = "Blues",
    rev = TRUE
)

Se genera un panel con un mapa por año.

# Generar un panel de mapas
panel_mapas <- ggplot(data = precipitacion_df) +
  geom_raster(aes(x = x, y = y, fill = precipitation)) +
  geom_contour(aes(x = x, y = y, z = precipitation), color = "white") +
  geom_sf(
    data = poligono_pais,
    fill = "transparent",
    color = "grey10",
    size = .5
  ) +
  scale_fill_gradientn(
    name = "mm",
    colors = colores,
    breaks = intervalos,
    labels = round(intervalos, 0),
    limits = c(
      min(precipitacion_df$precipitation),
      max(precipitacion_df$precipitation)
    )
  ) +
  facet_wrap( ~ year) +
  guides(
    fill = guide_colourbar(
      direction = "vertical",
      barheight = unit(50, "mm"),
      barwidth = unit(5, "mm"),
      title.position = "top",
      label.position = "right",
      title.hjust = .5,
      label.hjust = .5,
      ncol = 1,
      byrow = FALSE
    )
  ) +
  estilo_precipitacion()

# Despliegue
panel_mapas

Seguidamente, se crea un mapa con el promedio de clasificación para todos los años.

# Cálculo del promedio de precipitación
precipitacion_promedio_df <- 
  precipitacion_df |>
  dplyr::group_by(
      x, y, .drop = FALSE
  ) |>
  dplyr::summarise(
      promedio = mean(precipitation)
  )
print(head(precipitacion_promedio_df))
# A tibble: 6 × 3
# Groups:   x [1]
      x     y promedio
  <dbl> <dbl>    <dbl>
1 -73.9 -33.6     247.
2 -73.9 -33.4     229.
3 -73.9 -33.1     209.
4 -73.9 -32.9     192.
5 -73.9 -32.6     176.
6 -73.9 -32.4     162.
# Intervalos para las clases del mapa
intervalos <- 
  classInt::classIntervals(
    precipitacion_promedio_df$promedio,
    n = 5,
    style = "equal"
  )$brks

# Colores para el mapa
colores <- hcl.colors(
    n = length(intervalos),
    palette = "Blues",
    rev = TRUE
)

# Mapa
mapa_promedio <-
  ggplot(data = precipitacion_promedio_df) +
  geom_raster(aes(x = x, y = y, fill = promedio)) +
  geom_contour(aes(x = x, y = y, z = promedio), color = "white") +
  geom_sf(
    data = poligono_pais,
    fill = "transparent",
    color = "grey10",
    size = .5
  ) +
  scale_fill_gradientn(
    name = "mm",
    colors = colores,
    breaks = intervalos,
    labels = round(intervalos, 0),
    limits = c(
      min(precipitacion_promedio_df$promedio),
      max(precipitacion_promedio_df$promedio)
    )
  ) +
  guides(
    fill = guide_colourbar(
      direction = "vertical",
      barheight = unit(50, "mm"),
      barwidth = unit(5, "mm"),
      title.position = "top",
      label.position = "right",
      title.hjust = .5,
      label.hjust = .5,
      ncol = 1,
      byrow = FALSE
    )
  ) +
  estilo_precipitacion()

# Despliegue
mapa_promedio

12.7 Ejercicios

  1. Elabore otros mapas con diferentes polígonos delimitadores y diferentes conjuntos de datos de precipitación.
  2. Elabore mapas interactivos con el paquete tmap o el paquete leaflet.

12.8 Recursos de interés

How to Create Amazing Precipitation Maps with R in 2D and 3D