Heatmap Recipe

Heatmap of life expectancy by country and year with values inside colored cells
Observed discrete cells with continuous color and centered labels.

Pre-gridded flow

Runnable: install ggaction and provide the named data array as plain row objects.

import { chart } from "ggaction";

const program = chart()
  .createCanvas({ margin: { right: 120 } })
  .createData({ values: cells })
  .createHeatmap({
    x: { field: "column", fieldType: "ordinal" },
    y: { field: "row", fieldType: "nominal" },
    color: {
      field: "value",
      fieldType: "quantitative",
      scale: { type: "sequential", palette: "viridis" }
    }
  });

Raw-row binned flow

Runnable: install ggaction and provide the named data array as plain row objects.

import { chart } from "ggaction";

const program = chart()
  .createCanvas({ margin: { right: 120 } })
  .createData({ values: observations })
  .createHeatmap({
    x: "weight",
    y: "economy",
    bin: { bins: { x: 10, y: 8 } },
    color: { scale: { palette: "blues" } }
  });

This mode derives rectangular x/y bounds and a count for each cell. It emits the complete grid by default, including zero-count cells.

You must decide

The library infers

In binned mode, the library instead infers quantitative position scales from the resolved bin extents, a continuous count scale, source-facing axis titles, and a Count legend. It disables separate chart grid lines unless requested.

Use rect: { opacity, stroke, strokeWidth } for cell appearance. Cell fill is owned by the required color encoding. To show values, chain a text layer after the heatmap:

const labeled = program
  .createTextMark({ align: "center", baseline: "middle" })
  .encodeText({ field: "value", format: ".0f" });

Continue

Basic Charts · Rectangular 2D bins · Rect marks · Continuous color scales