When a heatmap is the right choice, when another chart reads better, and how to pick colors that tell the truth. The same rules hold in every chart library. For picking between chart types in general, see Choosing a chart, and for color, the Color guideline.
What it is for
A heatmap shows one number for every pair of two things as a grid of colored cells: activity per weekday and hour, rating per season and episode, count per range of two measures. Color shows where the values are high and low, so the reader sees the pattern before any single value.
When to use
The reader looks for a pattern across two dimensions, such as busy hours in a week or slow pages per region.
The data is a calendar: one value per day, laid out by week and weekday.
A scatterplot has so many points they cover each other. Count them per cell with a binned grid or hexagons.
A value is measured over a surface, such as wind speed on a map. Use contours.
Use something else when
The reader needs to compare exact values. Use a bar chart, since color is read far less accurately than length or position.
One dimension is time and the trend matters. Use a line chart, with one line per row if there are only a few.
There are only a few rows and columns. Use a table, with the values written out.
There are few enough points to see each one. Use a scatterplot.
The values are parts of a whole. Use a stacked bar chart.
How it reads
Each cell's value is encoded as color, usually lightness: light for low, dark for high. People read lightness as order, but not as an amount. They see which cells are higher, not by how much. That is why a heatmap shows patterns well and exact values poorly.
Contours and density charts work the same way on a continuous surface. Each line or band joins places with the same value, like the height lines on a hiking map.
Do it well
Use a sequential scale for magnitude: one hue, light to dark, where darker means more.
Use a diverging scale only when the data has a real midpoint, such as zero change or a target. Put the neutral color on that midpoint.
Use five to seven color steps. Steps are easier to match to the legend than a smooth ramp.
Always show a legend with the unit and the step boundaries.
Give empty or missing cells their own neutral color, different from the lowest step, so "no data" does not read as "zero".
Print the value in each cell when the cells are large enough, and switch the text to a light color on dark cells.
Order the rows and columns in a meaningful way, such as weekdays in order or rows sorted by total, so patterns can form.
Pitfalls
A rainbow scale. Its hues have no order, and its bright bands create edges that are not in the data. Use one hue.
A diverging scale on data with no midpoint, such as a count. It makes the middle values look like a boundary.
Red against green to mean bad and good. Many readers cannot tell them apart. Use a scale that changes in lightness.
Steps cut at round numbers that split the data badly, so most cells share one color. Check how many cells land in each step.
Too many cells to read on a small screen. Aggregate to weeks or ranges, or let the reader zoom.
Variants
Matrix: categories on both axes, one cell per pair.
Calendar: one cell per day, columns for weeks and rows for weekdays.
Binned grid: a scatterplot counted into rectangular cells.
Hexbin: the same with hexagons, which follow round clusters better.
Density contours: lines around the areas where points cluster, with no cells at all.
Filled contours: bands of a value measured over a surface.
Vector field: an arrow per position for a direction and a speed, such as wind.
Compared with similar charts
Against a table: a heatmap shows the pattern at a glance, a table gives the exact values. A labeled heatmap gives both.
Against a scatterplot: a scatterplot shows every point, a binned heatmap or hexbin shows how many points sit in each area.
Against a line chart: a line chart compares the values of a few rows over time. A heatmap shows the pattern of many rows at once, with less detail per value.
Against a choropleth map: a map places cells by geography. Use it only when location is the point.