在Seaborn热力图中更改刻度标签的旋转方式

86

我正在使用Seaborn绘制热力图。问题是我的图中有太多的方块,因此x和y标签彼此靠得太近而无法使用。所以我创建了一个xticks和yticks列表来使用。然而,将此列表传递给函数会旋转图中的标签。最好让Seaborn自动删除一些刻度,但如果没有这样的功能,我希望能够使yticks竖直。

import pandas as pd
import numpy as np
import seaborn as sns

data = pd.DataFrame(np.random.normal(size=40*40).reshape(40,40))

yticks = data.index
keptticks = yticks[::int(len(yticks)/10)]
yticks = ['' for y in yticks]
yticks[::int(len(yticks)/10)] = keptticks

xticks = data.columns
keptticks = xticks[::int(len(xticks)/10)]
xticks = ['' for y in xticks]
xticks[::int(len(xticks)/10)] = keptticks

sns.heatmap(data,linewidth=0,yticklabels=yticks,xticklabels=xticks)
3个回答

118

seaborn 内部使用 matplotlib,因此您可以使用 matplotlib 函数来修改您的图表。我已经修改了下面的代码,使用plt.yticks函数设置rotation=0来解决问题。

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


data = pd.DataFrame(np.random.normal(size=40*40).reshape(40,40))

yticks = data.index
keptticks = yticks[::int(len(yticks)/10)]
yticks = ['' for y in yticks]
yticks[::int(len(yticks)/10)] = keptticks

xticks = data.columns
keptticks = xticks[::int(len(xticks)/10)]
xticks = ['' for y in xticks]
xticks[::int(len(xticks)/10)] = keptticks

sns.heatmap(data,linewidth=0,yticklabels=yticks,xticklabels=xticks)

# This sets the yticks "upright" with 0, as opposed to sideways with 90.
plt.yticks(rotation=0) 

plt.show()

图表


33
所以实际上唯一需要的部分是 plt.yticks(rotation=0) - Tom
6
@Tom 是的,其余代码是为了让 OP(或其他人)能够复制一个完全可用的图表。我已经在特定的部分进行了注释,说明它与原来的不同以及为什么不同。 - Ffisegydd
对于那些喜欢列表推导式的人,yticks = data.index yticks = [str(x) if i % 10 == 0 else '' for i,x in enumerate(yticks)] - Overdrivr
1
我已经尝试了这个方法,以及@Ryszard Cetnarski建议的解决方案,但两种形式似乎都被忽略了。我已经尝试了matplotlib v3.3.0和v3.3.3,以及Seaborn v0.10和v0.11。(所有8种可能性。)所有旋转指令都被忽略了。然而,最新的matplotlib文档推荐Ffisegydd的方法。我的惊讶到了极点。 - user3897315

55

你也可以调用热力图对象的方法:

    g = sns.heatmap(data,linewidth=0,yticklabels=yticks,xticklabels=xticks)
    g.set_yticklabels(g.get_yticklabels(), rotation = 0, fontsize = 8)

我不确定为什么sns.heatmap的文档中没有涉及到这点,但是这里描述了相同的方法:http://seaborn.pydata.org/generated/seaborn.FacetGrid.html

我相信这些方法适用于每个seaborn图表对象,但是找不到通用的API。


2
如果您使用 matplotlib 的符号约定一致地调用对象,即 ax=sns.heatmap(..); ax.set_yticklabels(),那么问题就会变得更加明显。然后,您可能会更清楚地发现解决方案可以在 matplotlib 文档中找到。 - ImportanceOfBeingErnest
迄今为止最简单的方法;这应该是被接受的答案。 - wordsforthewise

0

对于上面的问题,我发现了一个类似的解决方案,当时我在寻找如何旋转轴上的刻度值。

我遇到的问题是在使用Seaborn和FacetGrid渲染Heatmap时,我可以通过以下方式旋转x轴上的刻度,但无法旋转y轴上的刻度...

for ax in fg.axes.flat: 
    ax.set_xticklabels(ax.get_xticklabels(), rotation=45)
    ax.set_yticklabels(ax.get_yticklabels(), rotation=45)

我发现yticks为空,最终被替换为null列表。这是因为列包裹col_wrap中的最终数据没有yticks,因为我将它们对齐在左侧,所以2x2网格矩阵中的第0个和第2个yticks被第1个和第3个yticks覆盖了。xticks没有这个问题,因为xtick值相反,第0个和第2个xticks为空,而第1个和第3个有值。我通过打印g.get_yticklabels()来发现这个特性:

g = sns.heatmap(d, **kwargs)
print(g.get_yticklabels())
[Text(0, 0.5, '5'), Text(0, 1.5, '8'), Text(0, 2.5, '12'), Text(0, 3.5, '15'), Text(0, 4.5, '19'), Text(0, 5.5, '22'), Text(0, 6.5, '25'), Text(0, 7.5, '26'), Text(0, 8.5, '29'), Text(0, 9.5, '33'), Text(0, 10.5, '34'), Text(0, 11.5, '36'), Text(0, 12.5, '40'), Text(0, 13.5, '43'), Text(0, 14.5, '47')]
[]
[Text(0, 0.5, '1'), Text(0, 1.5, '5'), Text(0, 2.5, '8'), Text(0, 3.5, '12'), Text(0, 4.5, '15'), Text(0, 5.5, '19'), Text(0, 6.5, '22'), Text(0, 7.5, '25'), Text(0, 8.5, '26'), Text(0, 9.5, '29'), Text(0, 10.5, '33'), Text(0, 11.5, '34'), Text(0, 12.5, '36'), Text(0, 13.5, '40'), Text(0, 14.5, '43'), Text(0, 15.5, '47')]
[]

我的解决方法是只有在存在{x,y}tick时才执行旋转操作:

g = sns.heatmap(d, **kwargs)
if g.get_yticklabels():
    g.set_yticklabels(g.get_yticklabels(), rotation=30)
if g.get_xticklabels():
    g.set_xticklabels(g.get_xticklabels(), rotation=45)

这是在循环函数中执行的,然后映射到FacetGrid。这假定所有四个图都具有等效的{x,y}ticks

def draw_heatmap(*args, **kwargs):
    data = kwargs.pop('data')
    d = data.pivot(index=args[1], columns=args[0], values=args[2])
    # High-Low limit values
    hl = args[3]
    lwrbnd, uprbnd = data[args[2]].describe([hl,1-hl]).iloc[[4,6]].values
    g = sns.heatmap(d, **kwargs, vmin=lwrbnd, vmax=uprbnd)
    if g.get_yticklabels():
        g.set_yticklabels(labels=g.get_yticklabels(), rotation=30)
    if g.get_xticklabels():
        g.set_xticklabels(g.get_xticklabels(), rotation=45)

fg = sns.FacetGrid(multidf.groupby(findx).mean().reset_index(), 
                   col_wrap=col_wrp, col=ondx, height=5, sharey=True)
fg.map_dataframe(draw_heatmap, 'col', 'row', toggle, hl, square=True, 
                 cmap="YlGnBu")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接