seaborn.heatmap with varying cell sizes

Question:

I have a heatmap with ticks which have non equal deltas between themselves:
enter image description here

For example, in the attached image, the deltas are between 0.015 to 0.13. The current scale doesn’t show the real scenario, since all cell sizes are equal.

Is there a way to place the ticks in their realistic positions, such that cell sizes would also change accordingly?
Alternatively, is there another method to generate this figure such that it would provide a realistic representation of the tick values?

Asked By: user7738429

||

Answers:

As mentioned in the comments, a Seaborn heatmap uses categorical labels. However, the underlying structure is a pcolormesh, which can have different sizes for each cell.

Also mentioned in the comments, is that updating the private attributes of the pcolormesh isn’t recommended. Moreover, the heatmap can be directly created calling pcolormesh.

Note that if there are N cells, there will be N+1 boundaries. The example code below supposes you have x-positions for the centers of the cells. It then calculates boundaries in the middle between successive cells. The first and the last distance is repeated.

The ticks and tick labels for x and y axis can be set from the given x-values. The example code supposes the original values indicate the centers of the cells.

import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

sns.set()
N = 10
xs = np.random.uniform(0.015, 0.13, 10).cumsum().round(3)  # some random x values
values = np.random.rand(N, N)  # a random matrix

# set bounds in the middle of successive cells, add extra bounds at start and end
bounds = (xs[:-1] + xs[1:]) / 2
bounds = np.concatenate([[2 * bounds[0] - bounds[1]], bounds, [2 * bounds[-1] - bounds[-2]]])

fig, ax = plt.subplots()
ax.pcolormesh(bounds, bounds, values)

ax.set_xticks(xs)
ax.set_xticklabels(xs, rotation=90)
ax.set_yticks(xs)
ax.set_yticklabels(xs, rotation=0)
plt.tight_layout()
plt.show()

example heatmap

PS: In case the ticks are mean to be the boundaries, the code can be simplified. One extra boundary is needed, for example a zero at the start.`

bounds = np.concatenate([[0], xs])
ax.tick_params(bottom=True, left=True)

example with ticks between the cells

Answered By: JohanC
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.