How to Read and Plot El Niño / La Niña Time Series in Python

Introduction

To read and plot El Niño / La Niña time series in Python, a simple and reliable approach is to use the Oceanic Niño Index (ONI) provided by NOAA/CPC. The ONI is based on the 3-month running mean of sea surface temperature (SST) anomalies in the Niño 3.4 region (central equatorial Pacific).

What are El Niño and La Niña?

El Niño and La Niña are the two opposite phases of the El Niño–Southern Oscillation (ENSO), a major mode of climate variability:

  • El Niño corresponds to warmer-than-average SSTs in the central and eastern tropical Pacific. It typically leads to significant impacts such as increased rainfall in some regions (e.g., South America) and droughts in others (e.g., Australia, Indonesia).
  • La Niña corresponds to cooler-than-average SSTs in the same region, often producing roughly opposite climate effects.

These phenomena influence global weather patterns, including precipitation, temperature, tropical cyclones, and even wildfire activity, making ENSO monitoring essential for climate and environmental studies.

NOAA defines El Niño / La Niña events using a threshold of ±0.5 °C sustained over 5 consecutive overlapping seasons. Note that the most recent ONI values may be revised as new data becomes available.

NOAA provides ONI as a plain text dataset, and additional ENSO-related indices (Niño 3.4, MEI, etc.) are also available. Currently, ONI extends from 1950 to 2026.

Downloads ONI from NOAA

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pandas as pd
import matplotlib.pyplot as plt

# NOAA CPC ONI text file
url = "https://www.cpc.ncep.noaa.gov/data/indices/oni.ascii.txt"

# Read data
df = pd.read_csv(url, sep=r"\s+")

print(df.head())
print(df.columns)

How to Read and Plot El Niño / La Niña Time Series in Python ?
How to Read and Plot El Niño / La Niña Time Series in Python ?

This first step loads the ONI dataset directly from NOAA servers. The file typically contains:

  • YR → year
  • SEAS → overlapping 3-month season (e.g., DJF, JFM, etc.)
  • ANOM → SST anomaly (°C)

Converts the season labels into dates, classifies El Niño / Neutral / La Niña

Usually this file contains columns like YR, SEAS, ANOM.
If needed, you can inspect df.columns and adapt the code below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import pandas as pd
import matplotlib.pyplot as plt

url = "https://www.cpc.ncep.noaa.gov/data/indices/oni.ascii.txt"
df = pd.read_csv(url, sep=r"\s+")

# Keep only the columns we need
# Common NOAA format: YR, SEAS, ANOM
df = df[["YR", "SEAS", "ANOM"]].copy()

# Map overlapping 3-month seasons to a representative month
season_to_month = {
    "DJF": 1,
    "JFM": 2,
    "FMA": 3,
    "MAM": 4,
    "AMJ": 5,
    "MJJ": 6,
    "JJA": 7,
    "JAS": 8,
    "ASO": 9,
    "SON": 10,
    "OND": 11,
    "NDJ": 12,
}

df["month"] = df["SEAS"].map(season_to_month)
df["date"] = pd.to_datetime(dict(year=df["YR"], month=df["month"], day=15))

# Simple classification by threshold
df["phase"] = "Neutral"
df.loc[df["ANOM"] >= 0.5, "phase"] = "El Niño"
df.loc[df["ANOM"] <= -0.5, "phase"] = "La Niña"

print(df.head())

How to Read and Plot El Niño / La Niña Time Series in Python ?
How to Read and Plot El Niño / La Niña Time Series in Python ?

Here we:

  • Convert seasonal labels into actual timestamps (mid-month approximation)
  • Classify each period into El Niño, La Niña, or Neutral based on SST anomaly thresholds

Plots the time series

Plot the ONI time series:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
plt.figure(figsize=(14, 5))
plt.plot(df["date"], df["ANOM"], linewidth=1)

# Threshold lines
plt.axhline(0.5, linestyle="--", linewidth=1)
plt.axhline(-0.5, linestyle="--", linewidth=1)
plt.axhline(0.0, linewidth=0.8)

# Shade El Niño and La Niña periods
elnino = df["ANOM"] >= 0.5
lanina = df["ANOM"] <= -0.5

plt.fill_between(df["date"], df["ANOM"], 0.5, where=elnino, alpha=0.3)
plt.fill_between(df["date"], df["ANOM"], -0.5, where=lanina, alpha=0.3)

plt.title("NOAA Oceanic Niño Index (ONI)")
plt.xlabel("Time")
plt.ylabel("ONI anomaly (°C)")
plt.tight_layout()
plt.show()

How to Read and Plot El Niño / La Niña Time Series in Python ?
How to Read and Plot El Niño / La Niña Time Series in Python ?

This visualization highlights:

  • Warm phases (El Niño) above +0.5 °C
  • Cold phases (La Niña) below −0.5 °C
  • Neutral conditions in between

If you want to extract only El Niño / La Niña periods:

1
2
df_events = df[df["phase"] != "Neutral"].copy()
print(df_events[["date", "SEAS", "ANOM", "phase"]].tail(20))

How to Read and Plot El Niño / La Niña Time Series in Python ?
How to Read and Plot El Niño / La Niña Time Series in Python ?

Detecting official ENSO events (NOAA definition)

If you want the official NOAA-style episodes, not just months above/below ±0.5, use the 5-season persistence rule:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import numpy as np

  df["warm"] = df["ANOM"] >= 0.5
  df["cold"] = df["ANOM"] <= -0.5

  # Rolling 5-season condition
  df["warm5"] = df["warm"].rolling(5, min_periods=5).sum() >= 5
  df["cold5"] = df["cold"].rolling(5, min_periods=5).sum() >= 5

  # Expand to mark the whole 5-season windows
  warm_idx = set()
  cold_idx = set()

  for i in df.index[df["warm5"]]:
      warm_idx.update(range(i - 4, i + 1))

  for i in df.index[df["cold5"]]:
      cold_idx.update(range(i - 4, i + 1))

  df["phase_official_like"] = "Neutral"
  df.loc[df.index.isin(warm_idx), "phase_official_like"] = "El Niño"
  df.loc[df.index.isin(cold_idx), "phase_official_like"] = "La Niña"

  print(df[["date", "SEAS", "ANOM", "phase_official_like"]].tail(30))

How to Read and Plot El Niño / La Niña Time Series in Python ?
How to Read and Plot El Niño / La Niña Time Series in Python ?

This step ensures consistency with NOAA’s official ENSO classification methodology.

Monthly Niño 3.4

If you prefer a monthly resolution, NOAA also provides Niño 3.4 SST anomalies based on ERSSTv5.
This is useful when:

  • You want higher temporal resolution
  • You plan to compute your own rolling averages
  • You want smoother visualizations

Python Code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import pandas as pd
  import matplotlib.pyplot as plt

  url = "https://www.cpc.ncep.noaa.gov/data/indices/ersst5.nino.mth.91-20.ascii"
  df = pd.read_csv(url, sep=r"\s+")

  print(df.columns)

  # Niño 3.4 anomaly column in your file
  df = df[["YR", "MON", "ANOM.3"]].copy()
  df = df.rename(columns={"ANOM.3": "ANOM"})

  # Create datetime
  df["date"] = pd.to_datetime(dict(year=df["YR"], month=df["MON"], day=1))

  anom = df["ANOM"]

  plt.figure(figsize=(16, 6))

  # Background zones
  plt.axhspan(0.5, anom.max() + 0.2, color="red", alpha=0.08)
  plt.axhspan(-0.5, 0.5, color="gray", alpha=0.08)
  plt.axhspan(anom.min() - 0.2, -0.5, color="blue", alpha=0.08)

  # Main line
  plt.plot(df["date"], anom, color="gray", linewidth=1.2, alpha=0.9)

  # Colored overlays
  plt.plot(df["date"], anom.where(anom >= 0.5), color="red", linewidth=2.5, label="El Niño")
  plt.plot(df["date"], anom.where(anom <= -0.5), color="blue", linewidth=2.5, label="La Niña")
  plt.plot(
      df["date"],
      anom.where((anom > -0.5) & (anom < 0.5)),
      color="gray",
      linewidth=2.0,
      label="Neutral"
  )

  # Filled areas
  plt.fill_between(df["date"], 0, anom, where=anom >= 0.5, color="red", alpha=0.25)
  plt.fill_between(df["date"], 0, anom, where=anom <= -0.5, color="blue", alpha=0.25)
  plt.fill_between(
      df["date"], 0, anom,
      where=(anom > -0.5) & (anom < 0.5),
      color="gray", alpha=0.15
  )

  # Threshold lines
  plt.axhline(0.5, color="red", linestyle="--", linewidth=1)
  plt.axhline(-0.5, color="blue", linestyle="--", linewidth=1)
  plt.axhline(0, color="black", linewidth=0.8)

  plt.title("Monthly Niño 3.4 SST Anomalies")
  plt.xlabel("Time")
  plt.ylabel("Anomaly (°C)")
  plt.legend(frameon=False)
  plt.tight_layout()
  plt.show()

How to Read and Plot El Niño / La Niña Time Series in Python ?
How to Read and Plot El Niño / La Niña Time Series in Python ?

Use Cases

The Niño 3.4 index is not only useful for visualization but also plays a key role in many climate and environmental applications.

Precipitation and Drought Monitoring

ENSO strongly influences global rainfall patterns. El Niño events are typically associated with wetter conditions in parts of South America and the southern United States, while La Niña often leads to increased rainfall in Australia and Indonesia. This makes Niño 3.4 a valuable predictor for drought and flood risk.

Wildfire Activity

ENSO affects vegetation dryness and fuel availability, which directly impacts wildfire activity. For example, El Niño conditions can increase fire risk in regions such as the Amazon and Indonesia, while La Niña may enhance fire activity in parts of North America. Combining Niño 3.4 with satellite-derived Fire Radiative Power (FRP) or burned area datasets provides insight into interannual fire variability.

Global Temperature Variability

El Niño and La Niña significantly modulate global temperature anomalies. Strong El Niño events are often associated with temporary spikes in global mean temperature, while La Niña tends to produce cooling effects. This is important for interpreting long-term climate trends.

Tropical Cyclones

ENSO influences hurricane activity worldwide. El Niño tends to suppress Atlantic hurricanes but enhances cyclone activity in the Pacific, while La Niña has the opposite effect.

Vegetation and Agriculture

ENSO impacts crop yields, vegetation growth, and drought conditions. The Niño 3.4 index can be combined with satellite vegetation indices (e.g., NDVI) to monitor ecosystem response and agricultural productivity.

Satellite Observations and Retrievals

ENSO-driven changes in cloud cover, atmospheric moisture, and aerosols can affect satellite retrieval algorithms. Understanding ENSO variability can help interpret biases and uncertainties in remote sensing products.

References

Links Site
ERSSTv5 Niño Indices NOAA CPC – Monthly Niño 3.4 data used in this tutorial
Oceanic Niño Index (ONI) NOAA CPC – Official ENSO classification method
Climate Indices Portal NOAA CPC – Access to multiple ENSO-related datasets
Niño 3.4 Time Series NOAA PSL – Alternative Niño 3.4 dataset and documentation
ERSSTv5 Dataset NOAA NCEI – Source SST dataset behind Niño indices
Image

of