如何使用遮罩创建自定义热图注释

问题描述 投票:0回答:1

我只想在热图上标记最高值,但只显示第一个数字。我不知道为什么。缩小字体似乎不起作用。在写这篇文章时,我想忽略注释变量并添加文本可能会起作用,但我无法为子图解决这个问题:cryingface:

你可以看到我在这里得到的内容:

玩具数据生成

np.random.seed(42)
n_rows = 10**6
n_ids = 1000
n_groups = 3

times = np.random.normal(12, 2.5, n_rows).round().astype(int) + np.random.choice([0,24,48,72,96,120,144], size=n_rows, p=[0.2,0.2,0.2,0.2,0.15,0.04,0.01])
timeslots= np.arange(168)

id_list = np.random.randint(low=1000, high=5000, size=1000)
ID_probabilities = np.random.normal(10, 1, n_ids-1)
ID_probabilities = ID_probabilities/ID_probabilities.sum()
final = 1 - ID_probabilities.sum()
ID_probabilities = np.append(ID_probabilities,final)
id_col = np.random.choice(id_list, size=n_rows, p=ID_probabilities)

data = pd.DataFrame(times[:,None]==timeslots, index=id_col)
n_ids = data.index.nunique()
data = data.groupby(id_col).sum()

data['grp'] = np.random.choice(range(n_groups), n_ids)
data

复制玩具数据的面食样本:

        0   1   2   3   4   5   6   7   8   9   ... 159 160 161 162 163 164 165 166 167 grp
1011    0   0   0   0   0   0   2   3   15  21  ... 1   1   0   0   0   0   0   0   0   1
1016    0   0   0   0   0   0   4   3   18  41  ... 2   0   0   0   0   0   0   0   0   2
1020    0   0   0   0   0   1   1   2   6   16  ... 1   1   0   0   0   0   0   0   0   0
1024    0   0   0   0   0   0   2   3   7   13  ... 0   1   1   0   0   0   0   0   0   0
1029    0   0   0   0   0   0   1   5   3   14  ... 1   0   1   0   0   0   0   0   0   1
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
4965    0   0   0   0   0   2   4   2   10  9   ... 0   1   0   0   0   0   0   0   0   1
4984    0   0   0   0   0   1   0   6   10  12  ... 0   0   0   0   0   0   0   0   0   2
4989    0   0   0   0   0   1   3   4   7   16  ... 1   1   0   0   0   0   0   0   0   0
4995    0   0   0   0   2   0   2   2   2   23  ... 0   1   0   0   0   0   0   0   0   0
4999    0   0   0   0   0   1   1   7   9   11  ... 0   0   0   0   0   0   0   0   0   2

我的生成图表的代码

import seaborn as sns
import matplotlib.pyplot as plt

rows = 1 
cols = n_groups
# profiles['grp'] = results
grpr = data.groupby('grp')

actual_values = []
fig, axs = plt.subplots(rows, cols, figsize=(cols*3, rows*3), sharey=True, sharex=True)
for grp, df in grpr:
    plt.subplot(rows,cols,grp+1)
    annot_labels = np.empty_like(df[range(168)].sum(), dtype=str)
    annot_mask = df[range(168)].sum() == df[range(168)].sum().max()
    actual_values.append(df[range(168)].max().max())
    annot_labels[annot_mask] = str(df[range(168)].max().max())
    sns.heatmap(df[range(168)].sum().values.reshape(7,-1), cbar=False, annot=annot_labels.reshape(7,-1), annot_kws={'rotation':90, 'fontsize':'x-small'}, fmt='')
    ppl = df.shape[0]
    journs = int(df.sum().sum()/1000)
    plt.title(f'{grp}: {ppl:,} people, {journs:,}k trips')
for ax in axs.flat:
    ax.set(xlabel='Hour', ylabel='Day')
    ax.set_yticklabels(['M','T','W','T','F','S','S'], rotation=90)
# Hide x labels and tick labels for top plots and y ticks for right plots.
for ax in axs.flat:
    ax.label_outer()
score_ch = ordered_scores['calinski_harbasz'][p]
score_si = ordered_scores['silhouette'][p]
plt.suptitle(f"Why don't these labels work? Actual values = {actual_values}")
plt.tight_layout()
plt.show()

python matplotlib seaborn heatmap plot-annotations
1个回答
0
投票

感谢@TrentonMcKinney 的评论和这篇关于 numpy 数组固定长度字符串的文章我有一个简单的解决方案。像这样创建空结构会产生长度为 1 个字符的字符串数组:

annot_labels = np.empty_like(df[range(168)].sum(), dtype=str)

更改数据类型可以解决问题。

np.empty_like(a, dtype='U5')
创建一个包含 5 个 unicode 字符的数组

© www.soinside.com 2019 - 2024. All rights reserved.