在 Python 中对热图的刻度线进行分组

Grouping the tick marks for heatmaps in Python

我有一个看起来像这样的热图(来自:)。

我正在尝试创建一个没有每个值的刻度标签但按范围分组的热图。例如,前三个刻度线未签名但已与一个联合签名 'Apples'.

使用以下命令似乎很容易完全禁用滴答标签:

plt.tick_params(
    axis='x',
    which='both',
    bottom=False,
    top=False,
    labelbottom=False)

或仅选择选定的刻度:

for (i,l) in enumerate(ax.xaxis.get_ticklabels()):
    if i == 0 or i == 4 or i == 5:
        l.set_visible(True)
    else:
        l.set_visible(False) 

但是可以像下面那样做吗?

热图示例代码:

corr = np.corrcoef(np.random.randn(10, 200))
mask = np.zeros_like(corr)
mask[np.triu_indices_from(mask)] = True
with sns.axes_style("white"):
    ax = sns.heatmap(corr, mask=mask, vmax=.3, square=True,  cmap="YlGnBu")
    plt.show()

您可以使用 x 轴变换来放置文本和绘制短线,x 位置使用数据坐标,y 位置使用轴坐标(底部为 0,顶部为 1)。默认情况下,文本不会被轴裁剪,但其他元素会被裁剪,因此它们需要 clip_on=False 才能在主绘图区域外可见。

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

corr = np.corrcoef(np.random.randn(10, 20))
corr[np.triu_indices_from(corr)] = np.nan
sns.set_style("white")
ax = sns.heatmap(corr, vmax=.3, square=True, cmap="YlGnBu",
                 annot=True, fmt='.2f', cbar_kws={'pad': 0})
labels = ['Apples', 'Oranges', 'Pears', 'Bananas']
label_lens = [4, 2, 1, 3]

ax.set_xticks([]) # remove the x ticks
ax.set_yticks([]) # remove the y ticks
pos = 0
for label, label_len in zip(labels, label_lens):
    if pos != 0:
        ax.vlines(pos, pos, len(corr), color='r', lw=2)
        ax.vlines(pos, 0, -0.02, color='r', lw=2,
                  transform=ax.get_xaxis_transform(), clip_on=False)
        ax.hlines(pos, 0, pos, color='r', lw=2)
        ax.hlines(pos, 0, -0.02, color='r', lw=2,
                  transform=ax.get_yaxis_transform(), clip_on=False)
    ax.text(pos + label_len / 2, -0.02, label, ha='center', va='top',
            transform=ax.get_xaxis_transform())
    ax.text(-0.02, pos + label_len / 2, label, ha='right', va='center', rotation=90,
            transform=ax.get_yaxis_transform())
    pos += label_len
plt.tight_layout()
plt.show()