0.1 Rutas de los datos

La ruta principal se define explícitamente en directorio_proyecto. Para ejecutar el análisis en otro ordenador se debe modificar solamente esa línea. La ruta debe señalar la carpeta Proyecto_El_Nino_Pamela descargada y descomprimida. El R Markdown y todos los archivos de datos están juntos en esa misma carpeta.

# IMPORTANTE: cambie únicamente esta ruta al usar otro ordenador.
# macOS actual:
directorio_proyecto <- paste0( "C:/Users/Usuario/Downloads/Proyecto_El_Nino_Pamela")
 


# Ejemplo para Windows. Quite el símbolo # y comente la ruta de macOS:
# directorio_proyecto <- paste0(
#   "C:/Users/NOMBRE_USUARIO/Downloads/",
#   "Proyecto_El_Nino_Pamela"
# )

# Ejemplo genérico para otra Mac:
# directorio_proyecto <- paste0(
#   "/Users/NOMBRE_USUARIO/Downloads/",
#   "Proyecto_El_Nino_Pamela"
# )

if (!dir.exists(directorio_proyecto)) {
  stop(
    "No existe la carpeta indicada en 'directorio_proyecto':\n",
    directorio_proyecto,
    "\nModifique esa variable con la ruta correspondiente a este ordenador."
  )
}

directorio_proyecto <- normalizePath(
  directorio_proyecto,
  mustWork = TRUE
)
ruta_nino34 <- file.path(
  directorio_proyecto,
  "nino34_hadisst_noaa_psl.data"
)
ruta_oni <- file.path(
  directorio_proyecto,
  "oni_noaa_cpc_operacional.txt"
)
ruta_clima <- file.path(
  directorio_proyecto,
  "clima_mensual_con_enso_1981_2025.csv"
)

archivos_requeridos <- c(ruta_nino34, ruta_oni, ruta_clima)
faltantes <- archivos_requeridos[!file.exists(archivos_requeridos)]

if (length(faltantes) > 0L) {
  stop(
    "No se encontraron los siguientes archivos:\n",
    paste(faltantes, collapse = "\n"),
    "\nLos cuatro archivos deben permanecer juntos en la misma carpeta."
  )
}

1 Introducción

El fenómeno de El Niño corresponde a la fase cálida del sistema climático El Niño-Oscilación del Sur (ENOS). Sus efectos pueden modificar la circulación atmosférica y el régimen de precipitaciones en distintas regiones. Este informe estudia el comportamiento de las precipitaciones durante los meses y años clasificados como El Niño mediante el Índice Oceánico de El Niño (ONI).

El análisis climático disponible comprende observaciones mensuales de Asunción y Encarnación. Las series no tienen la misma extensión: Asunción cubre 1981-2025 y Encarnación 1981-1995. Por tanto, los resultados describen estos dos puntos de observación dentro de sus respectivos períodos y no deben interpretarse como una medición exhaustiva de todo el territorio paraguayo.

2 Objetivos

2.1 Objetivo general

Analizar el comportamiento de las precipitaciones en Paraguay durante los eventos del fenómeno de El Niño.

2.2 Objetivos específicos

  1. Identificar los períodos en los que se presentó el fenómeno de El Niño.
  2. Describir el comportamiento de las precipitaciones anuales durante los eventos de El Niño.
  3. Comparar los meses con mayores y menores niveles de precipitación durante los eventos de El Niño.

3 Fuentes de datos

4 Gestión de datos

4.1 Índice Niño 3.4 de NOAA/PSL

periodo <- scan(
  file = ruta_nino34,
  what = integer(),
  nlines = 1,
  quiet = TRUE
)

if (length(periodo) < 2L) {
  stop("La primera línea del archivo Niño 3.4 no contiene los años esperados.")
}

anio_inicial <- periodo[1]
anio_final <- periodo[2]
n_anios <- anio_final - anio_inicial + 1L

nino34_anual <- read.table(
  file = ruta_nino34,
  header = FALSE,
  skip = 1,
  nrows = n_anios,
  na.strings = "-99.99",
  col.names = c(
    "anio", "ene", "feb", "mar", "abr", "may", "jun",
    "jul", "ago", "sep", "oct", "nov", "dic"
  ),
  colClasses = c("integer", rep("numeric", 12)),
  check.names = FALSE
)

if (nrow(nino34_anual) != n_anios) {
  stop("El número de años importados no coincide con el encabezado del archivo.")
}

nino34_mensual <- data.frame(
  anio = rep(nino34_anual$anio, each = 12),
  mes = rep(seq_len(12), times = nrow(nino34_anual)),
  nino34 = as.vector(t(as.matrix(nino34_anual[, -1]))),
  stringsAsFactors = FALSE
)

nino34_mensual$fecha <- as.Date(sprintf(
  "%04d-%02d-01",
  nino34_mensual$anio,
  nino34_mensual$mes
))

nino34_mensual <- nino34_mensual[
  , c("fecha", "anio", "mes", "nino34")
]
nino34_disponible <- nino34_mensual[!is.na(nino34_mensual$nino34), ]

cat(
  "Se importaron", nrow(nino34_disponible),
  "observaciones mensuales válidas entre",
  format(min(nino34_disponible$fecha), "%Y"), "y",
  format(max(nino34_disponible$fecha), "%Y"), "."
)
## Se importaron 1878 observaciones mensuales válidas entre 1870 y 2026 .

4.2 Índice ONI operacional

oni <- read.table(
  file = ruta_oni,
  header = TRUE,
  stringsAsFactors = FALSE,
  colClasses = c("character", "integer", "numeric", "numeric")
)

names(oni) <- tolower(names(oni))

if (!all(c("seas", "yr", "total", "anom") %in% names(oni))) {
  stop("El archivo ONI no posee las columnas SEAS, YR, TOTAL y ANOM.")
}

oni$fase <- ifelse(
  oni$anom >= 0.5, "El Niño",
  ifelse(oni$anom <= -0.5, "La Niña", "Neutral")
)

head(oni)
##   seas   yr total  anom    fase
## 1  DJF 1950 25.01 -1.32 La Niña
## 2  JFM 1950 25.36 -1.20 La Niña
## 3  FMA 1950 25.88 -1.12 La Niña
## 4  MAM 1950 26.24 -1.08 La Niña
## 5  AMJ 1950 26.35 -1.10 La Niña
## 6  MJJ 1950 26.32 -0.90 La Niña

4.3 Precipitación mensual y fase ONI

clima <- read.csv(
  file = ruta_clima,
  fileEncoding = "UTF-8-BOM",
  stringsAsFactors = FALSE,
  check.names = FALSE
)

columnas_necesarias <- c(
  "punto_id", "anio_mes", "precipitation_sum", "fase_oni", "mes"
)

if (!all(columnas_necesarias %in% names(clima))) {
  stop(
    "Faltan columnas en la base climática: ",
    paste(setdiff(columnas_necesarias, names(clima)), collapse = ", ")
  )
}

clima$fecha <- as.Date(paste0(clima$anio_mes, "-01"))
clima$anio <- as.integer(format(clima$fecha, "%Y"))
clima$mes_num <- as.integer(format(clima$fecha, "%m"))
clima$precipitacion_mm <- as.numeric(clima$precipitation_sum)
clima$localidad <- tools::toTitleCase(gsub("_", " ", clima$punto_id))
clima$es_nino <- clima$fase_oni == "El Nino"

if (anyNA(clima$fecha) || anyNA(clima$precipitacion_mm)) {
  stop("La base climática contiene fechas o precipitaciones no válidas.")
}

cat(
  "La base climática contiene", nrow(clima), "registros de",
  length(unique(clima$localidad)), "localidades:",
  paste(sort(unique(clima$localidad)), collapse = " y "), "."
)
## La base climática contiene 720 registros de 2 localidades: Asuncion y Encarnacion .
cobertura_localidad <- do.call(
  rbind,
  lapply(split(clima, clima$localidad), function(x) {
    data.frame(
      localidad = x$localidad[1],
      desde = format(min(x$fecha), "%Y-%m"),
      hasta = format(max(x$fecha), "%Y-%m"),
      meses = nrow(x),
      stringsAsFactors = FALSE
    )
  })
)
rownames(cobertura_localidad) <- NULL

knitr::kable(
  cobertura_localidad,
  col.names = c("Localidad", "Desde", "Hasta", "Meses disponibles"),
  caption = "Cobertura temporal de la base climática"
)
Cobertura temporal de la base climática
Localidad Desde Hasta Meses disponibles
Asuncion 1981-01 2025-12 540
Encarnacion 1981-01 1995-12 180

5 Exploración del índice Niño 3.4

plot(
  x = nino34_disponible$fecha,
  y = nino34_disponible$nino34,
  type = "l",
  col = "#1565C0",
  lwd = 1,
  xlab = "Fecha",
  ylab = "Anomalía de temperatura (°C)",
  main = "Índice Niño 3.4, HadISST",
  sub = "Anomalías respecto de 1981-2010"
)
abline(h = 0, col = "gray50", lty = 2)
abline(h = c(-0.5, 0.5), col = c("#1565C0", "#C62828"), lty = 3)

6 Períodos con presencia de El Niño

Se considera que un año presentó condiciones de El Niño cuando la base climática contiene al menos un mes clasificado como El Nino por el ONI.

anios_nino <- sort(unique(clima$anio[clima$es_nino]))

agrupar_periodos <- function(anios) {
  if (length(anios) == 0L) return(character(0))
  grupo <- cumsum(c(TRUE, diff(anios) > 1L))
  bloques <- split(anios, grupo)
  vapply(
    bloques,
    function(x) if (length(x) == 1L) as.character(x) else paste0(min(x), "-", max(x)),
    character(1)
  )
}

periodos_nino <- agrupar_periodos(anios_nino)

tabla_periodos <- data.frame(
  numero = seq_along(periodos_nino),
  periodo = periodos_nino
)

knitr::kable(
  tabla_periodos,
  col.names = c("N.º", "Año o período con meses de El Niño"),
  caption = "Períodos identificados con condiciones de El Niño, 1981-2025"
)
Períodos identificados con condiciones de El Niño, 1981-2025
N.º Año o período con meses de El Niño
1 1982-1983
2 1986-1988
3 1991-1992
4 1994-1995
5 1997-1998
6 2002-2007
7 2009-2010
8 2014-2016
9 2018-2020
10 2023-2024

7 Precipitaciones anuales durante años con El Niño

Para evitar confundir dos indicadores distintos, se presentan:

  1. la precipitación total de todos los meses de cada año que tuvo al menos un mes de El Niño; y
  2. la precipitación acumulada exclusivamente durante los meses clasificados como El Niño.
clima$anio_con_nino <- clima$anio %in% anios_nino

precipitacion_anual <- aggregate(
  precipitacion_mm ~ localidad + anio,
  data = clima[clima$anio_con_nino, ],
  FUN = sum,
  na.rm = TRUE
)

precipitacion_meses_nino <- aggregate(
  precipitacion_mm ~ localidad + anio,
  data = clima[clima$es_nino, ],
  FUN = sum,
  na.rm = TRUE
)

names(precipitacion_anual)[3] <- "precipitacion_anual_mm"
names(precipitacion_meses_nino)[3] <- "precipitacion_en_meses_nino_mm"

resumen_anual <- merge(
  precipitacion_anual,
  precipitacion_meses_nino,
  by = c("localidad", "anio"),
  all.x = TRUE
)

resumen_localidad <- do.call(
  rbind,
  lapply(split(resumen_anual, resumen_anual$localidad), function(x) {
    data.frame(
      localidad = x$localidad[1],
      anios_con_nino = nrow(x),
      media_anual_mm = mean(x$precipitacion_anual_mm),
      minimo_anual_mm = min(x$precipitacion_anual_mm),
      maximo_anual_mm = max(x$precipitacion_anual_mm)
    )
  })
)
rownames(resumen_localidad) <- NULL

resumen_localidad[, 3:5] <- round(resumen_localidad[, 3:5], 1)

knitr::kable(
  resumen_localidad,
  col.names = c(
    "Localidad", "Años con El Niño", "Media anual (mm)",
    "Mínimo anual (mm)", "Máximo anual (mm)"
  ),
  caption = "Precipitación anual en años que presentaron meses de El Niño"
)
Precipitación anual en años que presentaron meses de El Niño
Localidad Años con El Niño Media anual (mm) Mínimo anual (mm) Máximo anual (mm)
Asuncion 27 1596.7 974.0 2496.8
Encarnacion 9 1943.2 1465.1 2472.8
colores <- c("Asuncion" = "#1565C0", "Encarnacion" = "#C62828")
localidades <- sort(unique(resumen_anual$localidad))
rango_y <- range(resumen_anual$precipitacion_anual_mm)
rango_x <- range(resumen_anual$anio)

plot(
  NA,
  xlim = rango_x,
  ylim = rango_y,
  xlab = "Año",
  ylab = "Precipitación anual (mm)",
  main = "Precipitación anual en años con condiciones de El Niño"
)

for (loc in localidades) {
  datos_loc <- resumen_anual[resumen_anual$localidad == loc, ]
  lines(
    datos_loc$anio,
    datos_loc$precipitacion_anual_mm,
    type = "b",
    pch = 16,
    col = colores[loc],
    lwd = 1.5
  )
}

legend(
  "topright",
  legend = localidades,
  col = colores[localidades],
  lty = 1,
  pch = 16,
  bty = "n"
)

8 Meses más y menos lluviosos durante El Niño

nombres_meses <- c(
  "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio",
  "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"
)

mensual_nino <- aggregate(
  precipitacion_mm ~ localidad + mes_num,
  data = clima[clima$es_nino, ],
  FUN = mean,
  na.rm = TRUE
)

mensual_nino$mes <- factor(
  nombres_meses[mensual_nino$mes_num],
  levels = nombres_meses,
  ordered = TRUE
)

extremos <- do.call(
  rbind,
  lapply(split(mensual_nino, mensual_nino$localidad), function(x) {
    mayor <- x[which.max(x$precipitacion_mm), ]
    menor <- x[which.min(x$precipitacion_mm), ]
    data.frame(
      localidad = x$localidad[1],
      mes_mayor = as.character(mayor$mes),
      mayor_mm = round(mayor$precipitacion_mm, 1),
      mes_menor = as.character(menor$mes),
      menor_mm = round(menor$precipitacion_mm, 1)
    )
  })
)
rownames(extremos) <- NULL

knitr::kable(
  extremos,
  col.names = c(
    "Localidad", "Mes más lluvioso", "Media (mm)",
    "Mes menos lluvioso", "Media (mm)"
  ),
  caption = "Meses extremos de precipitación durante condiciones de El Niño"
)
Meses extremos de precipitación durante condiciones de El Niño
Localidad Mes más lluvioso Media (mm) Mes menos lluvioso Media (mm)
Asuncion Abril 274.9 Agosto 68.9
Encarnacion Abril 260.7 Agosto 125.2
matriz_mensual <- reshape(
  mensual_nino[, c("mes_num", "localidad", "precipitacion_mm")],
  idvar = "mes_num",
  timevar = "localidad",
  direction = "wide"
)
matriz_mensual <- matriz_mensual[order(matriz_mensual$mes_num), ]

columnas_prec <- grep("^precipitacion_mm\\.", names(matriz_mensual), value = TRUE)
valores <- t(as.matrix(matriz_mensual[, columnas_prec, drop = FALSE]))
rownames(valores) <- sub("^precipitacion_mm\\.", "", columnas_prec)

barplot(
  valores,
  beside = TRUE,
  names.arg = substr(nombres_meses, 1, 3),
  col = colores[rownames(valores)],
  border = NA,
  xlab = "Mes",
  ylab = "Precipitación media (mm)",
  main = "Precipitación media mensual durante El Niño",
  legend.text = rownames(valores),
  args.legend = list(x = "topright", bty = "n")
)

9 Conclusiones

Los resultados permiten identificar los períodos clasificados como El Niño y describir las precipitaciones observadas en Asunción y Encarnación. La comparación mensual permite reconocer los meses relativamente más húmedos y más secos dentro de los eventos estudiados. Las diferencias entre localidades confirman que el efecto de El Niño no debe suponerse uniforme en todo Paraguay.

Para extender las conclusiones al país se recomienda incorporar más estaciones meteorológicas, evaluar la calidad y continuidad de cada serie y comparar los eventos de El Niño con períodos neutrales y de La Niña mediante medidas de anomalía e incertidumbre.

10 Información de la sesión

sessionInfo()
## R version 4.5.2 (2025-10-31 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 10 x64 (build 18363)
## 
## Matrix products: default
##   LAPACK version 3.12.1
## 
## locale:
## [1] LC_COLLATE=Spanish_Paraguay.utf8  LC_CTYPE=Spanish_Paraguay.utf8   
## [3] LC_MONETARY=Spanish_Paraguay.utf8 LC_NUMERIC=C                     
## [5] LC_TIME=Spanish_Paraguay.utf8    
## 
## time zone: America/Buenos_Aires
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## loaded via a namespace (and not attached):
##  [1] digest_0.6.39   R6_2.6.1        fastmap_1.2.0   xfun_0.60      
##  [5] cachem_1.1.0    knitr_1.51      htmltools_0.5.9 rmarkdown_2.31 
##  [9] lifecycle_1.0.5 cli_3.6.6       sass_0.4.10     jquerylib_0.1.4
## [13] compiler_4.5.2  tools_4.5.2     evaluate_1.0.5  bslib_0.12.0   
## [17] yaml_2.3.12     rlang_1.3.0     jsonlite_2.0.0