Matplotlib/Seaborn: First and Last Row Cut in Half of Heatmap Plot

matplotlib/seaborn: first and last row cut in half of heatmap plot

Unfortunately matplotlib 3.1.1 broke seaborn heatmaps; and in general inverted axes with fixed ticks.

This is fixed in the current development version; you may hence

  • revert to matplotlib 3.1.0
  • use matplotlib 3.1.2 or higher
  • set the heatmap limits manually (ax.set_ylim(bottom, top) # set the ylim to bottom, top)

Seaborn heatmap top and bottom row are partially truncated

This issue has been raised and closed on the Seaborn github. The solution found there by ResidentMario & MaozGelbart was:

This was a matplotlib regression introduced in 3.1.1 which has been fixed in 3.1.2 (still forthcoming). For now the fix is to downgrade matplotlib to a prior version.

And later,

Matplotlib 3.1.2 has been released (also available for conda users through conda-forge using conda install -c conda-forge matplotlib=3.1.2). This fixes the issue.

Highlight minimum values every row using seaborn heatmap

You could loop through the rows, find the index of the minimum, and draw a rectangle there. Setting clip_on=False prevents that the rectangles would be clipped by the border.

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap

Pe = np.random.rand(5, 5)

fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(10, 4))
sns.set_style('white')

sns.heatmap(Pe, linewidth=0.5, annot=True, ax=ax1)
for ind, row in enumerate(Pe):
min_col = np.argmin(row)
ax1.add_patch(plt.Rectangle((min_col, ind), 1, 1, fc='none', ec='skyblue', lw=5, clip_on=False))

sns.heatmap(Pe, mask=Pe != Pe.min(axis=1, keepdims=True), annot=True, lw=2, linecolor='black', clip_on=False,
cmap=ListedColormap(['skyblue']), cbar=False, ax=ax2)
plt.tight_layout()
plt.show()

sns.heatmap with highlights

PS: To create animations, the Celluloid library is a lightweight option:

import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
import seaborn as sns
import numpy as np
from celluloid import Camera

Pe = np.random.rand(5, 5)

fig, ax1 = plt.subplots()
camera = Camera(fig)
sns.set_style('white')

row_array = np.arange(Pe.shape[0]).reshape(-1, 1)
for row in range(Pe.shape[0]):
sns.heatmap(Pe, mask=(Pe != Pe.min(axis=1, keepdims=True)) | (row < row_array),
annot=True, lw=2, linecolor='black', clip_on=False,
cmap=ListedColormap(['skyblue']), cbar=False, ax=ax1)
camera.snap()

animation = camera.animate(interval=800)
animation.save('animation.gif')
plt.show()

sns.heatmap animation

For more complicated animations, matplotlib's animation API can be considered.



Related Topics



Leave a reply



Submit