Skip to main content
v2026.11,858 entries · CC-BY 4.0

Heatmap in Matplotlib: imshow, Labels and Cell Values

Draw a heatmap in Matplotlib with imshow: tick labels, colorbar, cell values, fixed color scale, and fixes for flipped rows and blurry cells.

Written and maintained by CASRAI Editorial Board

Last updated

A heatmap in Matplotlib is a color-coded image of a two-dimensional array, and Axes.imshow is the quickest way to draw one. The official Matplotlib gallery describes it this way: data that depends on two independent variables is shown “as a color coded image plot. This is often referred to as a heatmap,” and imshow makes producing such plots “particularly easy.” Most wrong-looking heatmaps come from five defaults, not from the drawing call: the origin, the tick labels, the color scale, the cell shape and the interpolation. This guide covers those first, then the steps.

What a Matplotlib heatmap is used for in research

Matplotlib heatmaps (also written “matplotlib heatmap” or “heatmap matplotlib”) show one value per cell of a grid, so they suit any result that is naturally a matrix: a correlation matrix between variables, counts per category pair, a confusion matrix, or a measurement taken at every combination of two conditions. The Matplotlib documentation’s own examples include a harvest table (vegetables by farmers) and a correlation matrix. If you work in seaborn rather than plain Matplotlib, see heatmap in seaborn; for the surrounding workflow see Python for exploratory data analysis.

Install or access

Matplotlib is installed from the Python package ecosystem; the official installation page lists the pip, conda, pixi and uv commands and shows how to check the installed version with matplotlib.__version__. The examples below follow the Matplotlib 3.11.2 documentation and use NumPy for the array. The import convention is explained in import matplotlib.pyplot as plt.

import numpy as np
import matplotlib.pyplot as plt

Step-by-step: draw a heatmap with imshow

1. Draw the matrix

Pass a 2D array to ax.imshow. Using the object-oriented interface (fig, ax = plt.subplots()) keeps later steps simple.

fig, ax = plt.subplots()
im = ax.imshow(harvest)

By default the colormap covers the full range of your data and uses the viridis colormap (the image.cmap setting). Choose another with cmap="YlGn", for example.

2. Label the rows and columns

Set tick locations and tick labels together. The Matplotlib gallery states that “it is important to set both, the tick locations (set_xticks) as well as the tick labels (set_xticklabels), otherwise they would become out of sync.” The gallery does both in one call with the labels keyword:

ax.set_xticks(range(len(farmers)), labels=farmers, rotation=45, rotation_mode="xtick")
ax.set_yticks(range(len(vegetables)), labels=vegetables)

3. Add a colorbar

A heatmap without a legend for the color scale cannot be read quantitatively. Call ax.figure.colorbar(im, ax=ax) and label it with cbar.ax.set_ylabel(...). Placement, size and label options are covered in colorbar in Matplotlib.

4. Write the values inside the cells

The gallery labels the data by “creating a Text within each cell”, with a double loop. Note that j is the column (x) and i the row (y), so the call is text(j, i, ...):

for i in range(len(vegetables)):
    for j in range(len(farmers)):
        ax.text(j, i, harvest[i, j], ha="center", va="center", color="w")

White text is unreadable on light cells. The gallery’s annotate_heatmap helper takes textcolors=("black", "white") (the colors used below and above a threshold) and, when no threshold is given, switches colors at half of the maximum on the image’s norm. It formats values with valfmt="{x:.2f}" by default; the gallery example uses valfmt="{x:.1f} t" to add a unit.

5. Fix the color scale with vmin and vmax

By default the colormap spans the data range of that one array, so the same color can mean different values in two figures. Set vmin and vmax explicitly to make figures comparable. The gallery’s correlation-matrix example uses vmin=-1, vmax=1, which puts the midpoint of a diverging colormap at zero correlation. Do not combine vmin/vmax with a norm instance; Matplotlib raises an error for that (a string norm name such as "log" together with vmin/vmax is allowed).

6. Use pcolormesh when the grid is uneven

imshow assumes equally spaced cells. The pcolormesh documentation notes that “if X and Y are each equidistant, imshow can be a faster alternative”, and that pcolormesh is preferred in most cases over the older pcolor. Use ax.pcolormesh(X, Y, C) when your columns or rows sit at uneven coordinates (for example, unevenly spaced doses or times).

Output and how to read it

Each cell is one array element. Row 0 is drawn at the top because the default origin is 'upper', which the documentation describes as typical for matrices and images, and cell centres sit at integer coordinates (the default extent runs from -0.5 to the number of columns minus 0.5). Read color against the colorbar, not against neighboring cells. Choose the colormap to match the data: a sequential map for values from low to high, a diverging map for data with a meaningful midpoint such as zero (see seaborn color palettes for palette types and designing effective scientific figures for accessibility).

Comparison of the main drawing functions

Function Use it when Source behavior
Axes.imshow Equal-sized cells from a plain array Default aspect is 'equal' (square cells); origin='upper' puts row 0 at the top
Axes.pcolormesh Cells at uneven X/Y coordinates Takes [X, Y,] C; returns a QuadMesh; shading default is 'auto'

Troubleshooting

Tick labels do not match the cells

You set labels without setting tick positions, or the reverse. Set both in the same call, as in step 2.

The rows appear in reverse order

This is the default origin='upper': row 0 is at the top. Pass origin="lower" if you want the first row at the bottom, and check that your tick labels follow the same order.

The cells look blurry or blended

The default interpolation is 'auto', which uses 'nearest' when the image is upsampled by a factor of three or more, and otherwise applies 'hanning' anti-aliasing (except when the upsampling is exactly a factor of one or two). For crisp cells, pass interpolation="nearest".

The cells are not square

The default aspect is 'equal'. With aspect="auto" the cells are stretched to fill the Axes (“non-square pixels”).

TypeError from pcolormesh with flat shading

With shading='flat', X and Y must have one more entry than C in each dimension (cell edges, not centres). Use 'nearest' or 'gouraud' when X and Y have the same dimensions as C. With the default 'auto', Matplotlib picks flat if X and Y are one larger and nearest if the dimensions match.

Free alternatives

Tool What it does
seaborn heatmap A higher-level function built on Matplotlib (seaborn imports as sns); see heatmap in seaborn
Matplotlib pcolormesh Same library, for uneven grids (step 6)

FAQ

How do I make a heatmap in Matplotlib?

Create a 2D NumPy array, call ax.imshow(array), then add tick labels and a colorbar. No extra package is needed.

How do I show values inside the heatmap cells?

Loop over the array and call ax.text(j, i, value, ha="center", va="center") for each cell, where j is the column and i the row. Choose the text color per cell so it contrasts with the background.

How do I change the colors of a Matplotlib heatmap?

Pass cmap to imshow (for example cmap="YlGn"), and set vmin and vmax if the scale must be shared across figures.

Should I use Matplotlib or seaborn for heatmaps?

Use Matplotlib when you need full control or an uneven grid; seaborn builds on Matplotlib and is covered in the seaborn guide linked above.

Sources

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about Heatmap in Matplotlib: imshow, Labels and Cell Values

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →

Ask CASRAI · Regulatory Radar

Research-admin question? Get an answer that links its sources.

An AI assistant specialized in research administration. Every answer links its sources to check before you act. 2 questions free, no account. $29/month after.

  • Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.
  • Every answer numbers its sources and links each one, so you can check the source yourself.