Climate Warming Stripes — ggplot2

Climate warming stripes (also known as "warming stripes") display temperature anomaly data as a sequence of vertical colored bars, one per year, using a blue-to-red diverging colormap. Created by climate scientist Ed Hawkins, this minimalist visualization strips away axes, labels, and gridlines to communicate long-term warming trends through pure color encoding. The progression from cool blues to warm reds makes temperature change immediately visible at a glance.

Climate Warming Stripes rendered with ggplot2

Renders

R source (ggplot2)

#' anyplot.ai
#' heatmap-stripes-climate: Climate Warming Stripes
#' Library: ggplot2 3.5.1 | R 4.4.1
#' Quality: 90/100 | Created: 2026-06-02

library(ggplot2)
library(ragg)

set.seed(42)

# Theme tokens
THEME       <- Sys.getenv("ANYPLOT_THEME", "light")
PAGE_BG     <- if (THEME == "light") "#FAF8F1" else "#1A1A17"
INK         <- if (THEME == "light") "#1A1A17" else "#F0EFE8"

# Data - synthetic global temperature anomalies 1880-2024 (relative to 1961-1990 baseline)
years   <- 1880:2024
n       <- length(years)
trend   <- (years - 1880) / (2024 - 1880) * 1.2
noise   <- rnorm(n, 0, 0.12)
dip     <- ifelse(years >= 1945 & years <= 1975, -0.12, 0)
anomaly <- trend + noise + dip
anomaly <- anomaly - mean(anomaly[years >= 1961 & years <= 1990])

df <- data.frame(year = years, anomaly = anomaly)

# Imprint diverging colormap: Imprint blue (cold) -> page neutral -> Imprint red (warm)
MID_COLOR <- if (THEME == "light") "#FAF8F1" else "#1A1A17"

# Title: 50 chars — below the 67-char baseline, no font-size scaling needed
title_text <- "heatmap-stripes-climate · r · ggplot2 · anyplot.ai"

# Warming stripes: one full-height bar per year, no axes, no labels, no grid
p <- ggplot(df, aes(x = year, y = 1, fill = anomaly)) +
    geom_tile(width = 1, height = 2) +
    scale_fill_gradient2(
        low      = "#4467A3",  # Imprint blue  — cold anomaly
        mid      = MID_COLOR,
        high     = "#AE3030",  # Imprint red   — warm anomaly
        midpoint = 0,
        guide    = "none"
    ) +
    scale_x_continuous(expand = c(0, 0)) +
    scale_y_continuous(limits = c(0, 2), expand = c(0, 0)) +
    labs(title = title_text) +
    theme_void() +
    theme(
        plot.background = element_rect(fill = PAGE_BG, color = NA),
        plot.title      = element_text(
            color  = INK,
            size   = 12,
            hjust  = 0.5,
            margin = margin(b = 8)
        ),
        plot.margin = margin(t = 20, r = 20, b = 20, l = 20)
    )

# Save
ggsave(
    filename = sprintf("plot-%s.png", THEME),
    plot     = p,
    device   = ragg::agg_png,
    width    = 8,
    height   = 4.5,
    units    = "in",
    dpi      = 400
)

Retrieve this implementation

Runnable source as JSON, for any HTTP client: https://api.anyplot.ai/specs/heatmap-stripes-climate/ggplot2/code. Any spec id and library id listed in llms-full.txt fit the same URL shape; every URL below is complete and callable.

{
  "spec_id": "heatmap-stripes-climate",
  "language": "r",
  "library": "ggplot2",
  "page": "https://anyplot.ai/heatmap-stripes-climate/r/ggplot2",
  "hub": "https://anyplot.ai/heatmap-stripes-climate",
  "code_json": "https://api.anyplot.ai/specs/heatmap-stripes-climate/ggplot2/code",
  "spec_json": "https://api.anyplot.ai/specs/heatmap-stripes-climate",
  "render_light_png": "https://storage.googleapis.com/anyplot-images/plots/heatmap-stripes-climate/r/ggplot2/plot-light.png",
  "render_dark_png": "https://storage.googleapis.com/anyplot-images/plots/heatmap-stripes-climate/r/ggplot2/plot-dark.png",
  "quality_score": 90.0,
  "license": "MIT",
  "guide": "https://anyplot.ai/llms.txt"
}

Part of Climate Warming Stripes on anyplot.ai.

Other implementations