Heatmaps make rectangular numeric data readable by turning each cell into a color-coded value. In Matplotlib, they fit matrices, queue counts, sensor grids, and other two-dimensional measurements where both row and column labels carry meaning.
An Axes.imshow() call draws the matrix as an image, while tick labels identify the columns and rows. Keeping the returned image object lets fig.colorbar() use the same colormap and numeric range as the cells.
Per-cell text labels make small grids easier to inspect, but the label color needs enough contrast against the colormap. A saved PNG with visible row labels, column labels, annotations, and colorbar ticks confirms the heatmap is ready to use outside the Python session.
Related: How to add a colorbar in Matplotlib
Related: How to set a colormap in Matplotlib
Related: How to fix overlapping labels in Matplotlib
from pathlib import Path import matplotlib import matplotlib.pyplot as plt import numpy as np queues = np.array( [ [42, 35, 29, 21, 18], [55, 48, 40, 32, 24], [38, 44, 51, 46, 39], [26, 31, 37, 43, 49], ] ) teams = ["Platform", "Security", "Billing", "Support"] days = ["Mon", "Tue", "Wed", "Thu", "Fri"] output = Path("heatmap-create.png") fig, ax = plt.subplots(figsize=(6.6, 4.2), layout="constrained") image = ax.imshow(queues, cmap="magma", vmin=15, vmax=60) ax.set_title("Open support tickets by team") ax.set_xlabel("Day") ax.set_ylabel("Team") ax.set_xticks(range(len(days)), days) ax.set_yticks(range(len(teams)), teams) colorbar = fig.colorbar(image, ax=ax, label="Open tickets") for row in range(queues.shape[0]): for column in range(queues.shape[1]): value = queues[row, column] text_color = "white" if image.norm(value) < 0.45 else "black" ax.text(column, row, value, ha="center", va="center", color=text_color) fig.savefig(output, dpi=160) plt.close(fig) matplotlib_version = matplotlib.__version__.split("+", 1)[0] print(f"matplotlib {matplotlib_version}") print(f"matrix shape: {queues.shape[0]} rows x {queues.shape[1]} columns") print(f"colorbar label: {colorbar.ax.get_ylabel()}") print(f"saved: {output}") print(f"bytes: {output.stat().st_size}")
image is the AxesImage returned by imshow(). Passing it to fig.colorbar() keeps the colorbar tied to the heatmap colormap and value range.
$ python create_heatmap.py matplotlib 3.10.7 matrix shape: 4 rows x 5 columns colorbar label: Open tickets saved: heatmap-create.png bytes: 55940
The byte count can change with Matplotlib, fonts, backend, or DPI differences. A nonzero byte count confirms that the PNG file was written.
The image should show four team rows, five weekday columns, numeric values inside each cell, and a vertical colorbar labeled Open tickets.
queues = np.array( [ [12, 18, 21], [16, 24, 30], ] ) teams = ["North", "South"] days = ["Mon", "Tue", "Wed"]
The number of row labels must match queues.shape[0], and the number of column labels must match queues.shape[1].
$ rm create_heatmap.py heatmap-create.png