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."
)
}
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.
Analizar el comportamiento de las precipitaciones en Paraguay durante los eventos del fenómeno de El Niño.
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 .
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
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"
)
| Localidad | Desde | Hasta | Meses disponibles |
|---|---|---|---|
| Asuncion | 1981-01 | 2025-12 | 540 |
| Encarnacion | 1981-01 | 1995-12 | 180 |
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)
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"
)
| 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 |
Para evitar confundir dos indicadores distintos, se presentan:
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"
)
| 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"
)
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"
)
| 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")
)
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.
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