Written and maintained by CASRAI Editorial Board
Last updated
A heatmap in seaborn is drawn with seaborn.heatmap(): you pass a rectangular dataset (a pandas DataFrame or a 2-D array) and each cell is coloured by its value. The function is axes-level, returns the matplotlib Axes it drew on, and is most often used to show a correlation matrix. The settings that decide whether the figure can be read correctly are annot, fmt, center, vmin/vmax and mask, and this guide walks through them in that order. The same function is what people mean when they search “seaborn heatmap” or “heatmap seaborn”.
What a seaborn heatmap is used for in research
Researchers use a heatmap to see a whole table of numbers at once: pairwise correlations between variables, a confusion matrix, or a grid of measurements across conditions. In seaborn’s own gallery the standard example is a lower-triangle correlation heatmap of many pairwise correlations. The function accepts rectangular data, writes values into the cells when asked, and puts a colour bar beside the grid by default (cbar=True).
If your goal is the statistics behind the colours, start with the CASRAI guides on the formula for correlation analysis and how to calculate Spearman correlation. For colour choices outside heatmaps see seaborn colour palettes. The same chart in R is covered in heatmap in R.
Install or access seaborn
Seaborn is installed from the Python Package Index with pip install seaborn. According to the official installation page, it requires Python 3.8 or newer and the mandatory dependencies numpy, pandas and matplotlib. SciPy is optional but is needed “for clustering matrices and some advanced options”, which matters if you later move from heatmap to clustermap.
pip install seaborn
Step by step: draw a heatmap in seaborn
1. Know the signature
The documented signature (seaborn 0.13.2) is:
seaborn.heatmap(data, *, vmin=None, vmax=None, cmap=None, center=None, robust=False, annot=None, fmt='.2g', annot_kws=None, linewidths=0, linecolor='white', cbar=True, cbar_kws=None, cbar_ax=None, square=False, xticklabels='auto', yticklabels='auto', mask=None, ax=None, **kwargs)
Extra keyword arguments are passed to matplotlib’s pcolormesh. The function returns the Axes object that holds the heatmap, and it draws on the current Axes unless you pass ax.
2. Build the matrix and draw the basic heatmap
For a correlation heatmap, compute the matrix with pandas and pass it in. numeric_only=True is needed when the DataFrame has non-numeric columns, because the pandas default is numeric_only=False.
import seaborn as snsandimport matplotlib.pyplot as pltcorr = df.corr(numeric_only=True)wheredfis your DataFramesns.heatmap(corr)plt.show()
3. Write the values in the cells (annot and fmt)
Setting annot=True writes the data value in each cell. The number format is controlled by fmt, which defaults to '.2g'; use fmt='.2f' for two decimals. You can also pass an array-like of the same shape as data to annot to print different text from the values that set the colours.
sns.heatmap(corr, annot=True, fmt='.2f')
4. Fix the colour scale (center, vmin, vmax)
vmin and vmax anchor the colormap; if you leave them out, they are inferred from the data and the other keyword arguments. For correlations, which run from -1 to 1, set both limits and set center=0 so zero sits at the neutral middle of a diverging colormap. Setting center also changes the default cmap. Setting the same limits on every figure in a paper means the same colour always stands for the same correlation.
cmap = sns.diverging_palette(230, 20, as_cmap=True)
sns.heatmap(corr, annot=True, fmt='.2f', cmap=cmap, vmin=-1, vmax=1, center=0)
robust=True uses robust quantiles instead of the extremes when vmin and vmax are not given, which stops one outlier cell from washing out the rest of the scale.
5. Hide the redundant half (mask) and square the cells
A correlation matrix is symmetric, so half of it repeats the other half. The official seaborn gallery example masks the upper triangle: mask hides cells where the mask is True, and square=True sets the Axes aspect to equal so each cell is square.
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
corr = df.corr(numeric_only=True)
mask = np.triu(np.ones_like(corr, dtype=bool))
f, ax = plt.subplots(figsize=(11, 9))
cmap = sns.diverging_palette(230, 20, as_cmap=True)
sns.heatmap(corr, mask=mask, cmap=cmap, vmax=.3, center=0,
square=True, linewidths=.5, cbar_kws={"shrink": .5})
This is the gallery’s “many pairwise correlations” recipe; it uses vmax=.3 because that dataset’s correlations are small. For general reporting use vmin=-1, vmax=1 as in step 4.
Output and how to read it
- Colour bar: the bar beside the grid is the only key to what each colour means, which is why fixing
vmin,vmaxandcentermatters. - Blank cells are missing, not zero. Seaborn automatically masks cells with missing values. Masked cells (from
mask) are blank as well, so a blank cell can mean either a mask you set or a NaN. - What a correlation cell contains.
DataFrame.corr(method='pearson', min_periods=1, numeric_only=False)supports Pearson, Kendall and Spearman. Pearson, Kendall and Spearman are computed using pairwise complete observations, and a pair with fewer thanmin_periodsvalid pairs gives NaN. Different cells can therefore rest on different numbers of rows. - For a paper: state the method (
pearson,spearmanorkendall), how missing values were handled, and the colour limits used. Those three details are what let a reader reproduce the figure. If strong correlations between predictors appear, see perfect multicollinearity.
Troubleshooting
The heatmap has blank cells
Either the cell was masked with mask, or the value is missing. Check corr.isna(); with min_periods set, pairs with too few valid observations become NaN.
corr() raises an error about non-numeric columns
The pandas default is numeric_only=False (changed in pandas 2.0.0), so a DataFrame with text columns raises an error. Pass numeric_only=True or select the numeric columns first.
The colours look wrong or inconsistent between figures
Without vmin/vmax the scale is inferred from each dataset. Set them explicitly and add center for diverging data.
The numbers in the cells are cut or too long
Set fmt (for example '.2f'). The default '.2g' uses two significant digits.
The cells are not square
Pass square=True. The default is False.
I want the rows and columns reordered by similarity
heatmap draws the data in the order given. The seaborn documentation points to clustermap for clustered heatmaps; it relies on SciPy.
Free alternatives
| Option | What it does | Source |
|---|---|---|
seaborn.clustermap |
Heatmap with clustering of rows and columns; listed as the “see also” for heatmap. SciPy is needed for clustering matrices. |
seaborn.pydata.org |
matplotlib pcolormesh |
The matplotlib function that receives the extra keyword arguments you pass to sns.heatmap. |
seaborn.pydata.org |
| Heatmap in R | The same type of chart in R; see the CASRAI guide heatmap in R. | CASRAI |
FAQ
Is “heatmap seaborn” different from “seaborn heatmap”?
No. Both refer to seaborn.heatmap(), called as sns.heatmap() after import seaborn as sns.
How do I show the numbers in each cell?
Use annot=True, and set fmt to control the number format.
How do I show only half of a correlation heatmap?
Build a boolean array with np.triu(np.ones_like(corr, dtype=bool)) and pass it as mask, as in the official gallery example.
What does center do?
It sets the data value at which the colormap is centred, for divergent data, and it changes the default cmap.
Does seaborn need SciPy for a heatmap?
The installation page lists SciPy as optional, needed for clustering matrices and some advanced options. The mandatory dependencies are numpy, pandas and matplotlib.
Sources
- seaborn documentation, seaborn.heatmap (v0.13.2), checked 2026-10-29.
- seaborn documentation, Installing seaborn, checked 2026-10-29.
- seaborn gallery, many pairwise correlations example (0.13.2), checked 2026-10-29.
- pandas documentation, DataFrame.corr, checked 2026-10-29.








