require(dplyr)
require(tidyr)
require(plotly)Image credits: MEI index at NOAA
Required R packages: Paquetes de R necesarios:
ICEN (Índice Costero El Niño/EL Niño Coastal Index)
Reference: https://siofen.imarpe.gob.pe/nivel2/indice-costero-el-nino-icen
icen <- read.table(
file = "http://met.igp.gob.pe/datos/ICEN.txt",
skip = 5,
header = FALSE
) |>
as_tibble() |>
rename(año = V1, mes = V2, ICEN = V3) |>
mutate(
date = paste(año, mes, 1, sep = "-") |> as.Date(),
ICEN_c = cut(
x = ICEN,
breaks = c(-Inf, -1.3, -1.1, -.7, .5, 1.3, 2.1, 3.5, Inf),
labels = c(
"Niña Fuerte", "Niña Moderada", "Niña Débil",
"Neutro",
"Niño Débil", "Niño Moderado", "Niño Fuerte", "Niño Extraordinario"
)
)
)NOAA indices
Reference: https://psl.noaa.gov/data/timeseries/month/
[EN]: NOAA website keep a catalogue of several environmental indices, most of them up to 2026. Through get_envir_data function, it is possible to read and load any of them as a data table (tibble object).
[ES]: En el sitio web de NOAA se hallan disponibles diversos índices actualizados (la mayoría) al 2026. A través de la función get_envir_data es posible leer los valores directamente a R a manera de una tabla (objeto tibble).
get_envir_data function
get_envir_data <- \(con, index_name = "index", metadata = TRUE, quiet = FALSE){
if(isFALSE(quiet)) sprintf("%s", con) |> cli::cli_progress_step()
sourceLines <- readLines(con = con)
yrsRange <- strsplit(x = sourceLines[1], split = "[[:blank:]]+") |>
unlist() |> as.numeric() |> na.omit()
rowIndex <- abs(diff(nchar(sourceLines))/nchar(sourceLines)[-length(sourceLines)])*100
rowIndex <- which(rowIndex > 80)[1:2] + c(1, 0)
naVals <- sourceLines[rowIndex[2] + 1] |> as.numeric() |> as.character()
# Reading data
envirIndex <- read.table(
file = con,
header = FALSE,
nrows = diff(rowIndex),
skip = rowIndex[1],
colClasses = "character"
) |>
as_tibble() |>
rename(year = V1) |>
rename_with(.cols = -year, .fn = gsub, pattern = "V", replacement = "") |>
pivot_longer(
cols = -year,
names_to = "month",
names_transform = \(x) as.integer(x) - 1,
values_to = "index"
) |>
mutate(
year = as.integer(year),
index = as.numeric(index) |> as.character(),
index = replace(
x = index,
list = index == naVals,
values = NA
),
index = as.numeric(index)
) |>
filter(!is.na(index)) |>
rename(!!index_name := index)
if(isTRUE(metadata)){
metadata <- sourceLines[-seq(from = rowIndex[1], to = rowIndex[2])] |>
gsub(pattern = "(^[[:blank:]]*)|([[:blank:]]*$)", replacement = "")
envirIndex <- list(data = envirIndex, metadata = metadata)
}
envirIndex
}Niño 1+2 (HadISST)
elnino_12_hadisst <- get_envir_data(
con = "https://psl.noaa.gov/data/timeseries/month/data/nino12.long.anom.data",
index_name = "elnino_12_hadisst",
metadata = FALSE,
quiet = TRUE
)Niño 1+2 (ERSSTv6)
elnino_12_ersstv6 <- get_envir_data(
con = "https://psl.noaa.gov/data/correlation/nina1.anom.data",
index_name = "elnino_12_ersstv6",
metadata = FALSE,
quiet = TRUE
)Niño 3 (HadISST)
elnino_3_hadisst11 <- get_envir_data(
con = "https://psl.noaa.gov/data/timeseries/month/data/nino3.long.anom.data",
index_name = "elnino_3_hadisst11",
metadata = FALSE,
quiet = TRUE
)Niño 3 (ERSSTv6)
elnino_3_ersstv6 <- get_envir_data(
con = "https://psl.noaa.gov/data/correlation/nina3.anom.data",
index_name = "elnino_3_ersstv6",
metadata = FALSE,
quiet = TRUE
)Niño 3.4 (HadISST)
elnino_34_hadisst11 <- get_envir_data(
con = "https://psl.noaa.gov/data/timeseries/month/data/nino34.long.anom.data",
index_name = "elnino_34_hadisst11",
metadata = FALSE,
quiet = TRUE
)Niño 3.4 (ERSSTv6)
elnino_34_ersstv6 <- get_envir_data(
con = "https://psl.noaa.gov/data/correlation/nina34.anom.data",
index_name = "elnino_34_ersstv6",
metadata = FALSE,
quiet = TRUE
)Niño 4 (HadISST)
elnino_4_hadisst11 <- get_envir_data(
con = "https://psl.noaa.gov/data/timeseries/month/data/nino4.long.anom.data",
index_name = "elnino_4_hadisst11",
metadata = FALSE,
quiet = TRUE
)Niño 4 (ERSSTv6)
elnino_4_ersstv6 <- get_envir_data(
con = "https://psl.noaa.gov/data/correlation/nina4.anom.data",
index_name = "elnino_4_ersstv6",
metadata = FALSE,
quiet = TRUE
)Multivariate ENSO Index (MEI Extended)
mei_ext <- get_envir_data(
con = "https://psl.noaa.gov/data/timeseries/month/data/mei.ext.long.data",
index_name = "mei_ext",
metadata = FALSE,
quiet = TRUE
)Oceanic Niño Index (ONI)
oni <- get_envir_data(
con = "https://psl.noaa.gov/data/correlation/oni.data",
index_name = "oni",
metadata = FALSE,
quiet = TRUE
)Relative Oceanic Niño Index (RONI)
roni <- get_envir_data(
con = "https://psl.noaa.gov/data/timeseries/month/data/roni.data",
index_name = "roni",
metadata = FALSE,
quiet = TRUE
)Central Tropical Pacific OLR Index
olr <- get_envir_data(
con = "https://psl.noaa.gov/data/correlation/olr.data",
index_name = "olr",
metadata = FALSE,
quiet = TRUE
)Pacific Warm Pool
pac_warmpool <- get_envir_data(
con = "https://psl.noaa.gov/data/timeseries/month/data/pacwarmpool.ersst.data",
index_name = "pac_warmpool",
metadata = FALSE,
quiet = TRUE
)Trans-Niño Index (TNI)
tni <- get_envir_data(
con = "https://psl.noaa.gov/data/timeseries/month/data/tni.long.data",
index_name = "tni",
metadata = FALSE,
quiet = TRUE
)Equatorial Central Pacific Heat Content: 160E-80W
central_pac_heat_cont <- get_envir_data(
con = "https://psl.noaa.gov/data/correlation/heatcentra.data",
index_name = "central_pac_heat_cont",
metadata = FALSE,
quiet = TRUE
)Bivariate ENSO Time-series (BEST)
best <- get_envir_data(
con = "https://psl.noaa.gov/data/correlation/censo.data",
index_name = "best",
metadata = FALSE,
quiet = TRUE
)Warning in readLines(con = con): incomplete final line found on
'https://psl.noaa.gov/data/correlation/censo.data'
PDO (Pacific Decadal Oscillation)
Reference: https://www.ncei.noaa.gov/access/monitoring/pdo/
pdo <- read.table(
file = "https://www.ncei.noaa.gov/pub/data/cmb/ersst/v5/v6/index/ersst.v6.pdo.dat",
skip = 1, header = TRUE
) |>
as_tibble() |>
pivot_longer(
cols = -Year,
names_to = "mes",
values_to = "PDO"
) |>
rename(año = Year) |>
mutate(
mes = seq(12)[match(x = mes, month.abb)],
date = paste(año, mes, 1, sep = "-") |> as.Date(),
PDO_c = cut(
x = PDO,
breaks = c(-Inf, 0, Inf),
labels = c("Frío", "Cálido")
)
) |>
filter(PDO < 99)TPI (Tripole Index for the Interdecadal Pacific Oscillation)
Reference: https://psl.noaa.gov/data/timeseries/IPOTPI/
tpiURL <- "https://psl.noaa.gov/data/timeseries/IPOTPI/tpi.timeseries.ersstv5.data"
yrsRange <- read.table(
file = tpiURL,
header = FALSE, nrow = 1
) |> as.numeric()
tpi <- read.table(
file = tpiURL,
skip = 1,
header = FALSE,
nrow = diff(yrsRange) + 1
) |>
as_tibble() |>
pivot_longer(
cols = -V1,
names_to = "mes",
values_to = "TPI"
) |>
rename(año = V1) |>
mutate(
mes = gsub(x = mes, pattern = "V", replacement = "") |> as.numeric(),
mes = mes - 1,
date = paste(año, mes, 1, sep = "-") |> as.Date(),
TPI_c = cut(
x = TPI,
breaks = c(-Inf, 0, Inf),
labels = c("Frío", "Cálido")
)
) |>
filter(TPI > -99)