本文介绍了seaborn clustermap:subplots_adjust取消彩条重定位的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用seaborn制作带有侧面色条的热图.但是,在我的实际应用程序案例中,我旋转了很长的列名.这需要使用 plt.subplots_adjust ,否则标签不适合图像:

plt.setp(g.ax_heatmap.get_xticklabels(), rotation=90)plt.subplots_adjust(底部=0.5)

使用以下最小示例,我发现这最后一条命令正在取消彩条重定位:

#!/usr/bin/env python3将 seaborn 作为 sns 导入导入matplotlib.pyplot作为pltiris = sns.load_dataset("iris")物种 = iris.pop("物种")#设置长列名称iris.columns = ["____".join(label.split("_")) 用于 iris.columns 中的标签]g = sns.clustermap(iris, col_cluster=False, yticklabels=False)#重新放置侧面的颜色条g.cax.set_position([.15,.2,.03,.45])plt.setp(g.ax_heatmap.get_xticklabels(),旋转= 90)plt.savefig("/tmp/unadjusted.png")plt.cla()g = sns.clustermap(iris,col_cluster = False,yticklabels = False)g.cax.set_position([.15,.2,.03,.45])plt.setp(g.ax_heatmap.get_xticklabels(),旋转= 90)# 调整为不剪掉列标签plt.subplots_adjust(底部=0.5)plt.savefig("/tmp/adjusted.png")

这会产生以下图像:

没有plt.subplots_adjust:

使用 plt.subplots_adjust :

为什么会发生这种情况?

这是一个错误吗?

我该怎么做才能在我想要的位置放置颜色条,并且仍然确保我的旋转颜色标签不会被切割?

解决方案

基于

由于我其实不想要树状图,而只是想要聚类,所以我可以通过使用树状图框放置颜色条来获得更令人满意的结果:

#!/usr/bin/env python3将 seaborn 作为 sns 导入导入matplotlib.pyplot作为pltiris = sns.load_dataset("iris")种= iris.pop(种")#设置长列名iris.columns = ["________".join(label.split("_"))for iris.columns中的标签]g = sns.clustermap(iris, col_cluster=False, yticklabels=False)plt.setp(g.ax_heatmap.get_xticklabels(), 旋转=90)#调整以使列标签不被切掉plt.subplots_adjust(底部=0.5)g.cax.set_position([.15, .2, .03, .45])plt.savefig("/tmp/adjusted_before.png")plt.cla()g = sns.clustermap(iris, col_cluster=False, yticklabels=False)plt.setp(g.ax_heatmap.get_xticklabels(), 旋转=90)# 调整为不剪掉列标签plt.subplots_adjust(底部=0.5)# 删除树状图 (https://stackoverflow.com/a/42418968/1878788)g.ax_row_dendrogram.set_visible(False)#使用树状图框重新定位颜色栏dendro_box = g.ax_row_dendrogram.get_position()dendro_box.x0 =(dendro_box.x0 + 2 * dendro_box.x1)/3g.cax.set_position(dendro_box)# 将刻度线向左移动 (https://stackoverflow.com/a/36939552/1878788)g.cax.yaxis.set_ticks_position("left")# 如果我们给颜色条添加一个标签# (cbar_kws={"label" : "the_label"} 在 clustermap 参数中)#我们还需要移动标签#g.cax.yaxis.set_label_position(左")plt.savefig("/tmp/adjusted_before_using_row_dendrogram_box.png")

这会生成以下图像:

plt.tight_layout 也会出现同样的问题.

进一步开发我的热图时,我想添加带有图例的行颜色(使用

重新定位颜色条后调用plt.tight_layout:

在重新定位颜色条之前调用plt.tight_layout:

I'm trying to make a heatmap with the colour bar on the side using seaborn. However, in my real application case, I have long column names that I rotate. This requires the use of plt.subplots_adjust, otherwise the labels do not fit in the image:

plt.setp(g.ax_heatmap.get_xticklabels(), rotation=90)
plt.subplots_adjust(bottom=0.5)

Using the following minimal example, I found out that this last command was cancelling the colour bar relocation:

#!/usr/bin/env python3

import seaborn as sns
import matplotlib.pyplot as plt

iris = sns.load_dataset("iris")
species = iris.pop("species")
# Make long column names
iris.columns = ["________".join(label.split("_")) for label in iris.columns]


g = sns.clustermap(iris, col_cluster=False, yticklabels=False)
# Relocate colour bar on the side
g.cax.set_position([.15, .2, .03, .45])
plt.setp(g.ax_heatmap.get_xticklabels(), rotation=90)
plt.savefig("/tmp/unadjusted.png")

plt.cla()

g = sns.clustermap(iris, col_cluster=False, yticklabels=False)
g.cax.set_position([.15, .2, .03, .45])
plt.setp(g.ax_heatmap.get_xticklabels(), rotation=90)
# Adjust to have the column labels not cut out
plt.subplots_adjust(bottom=0.5)
plt.savefig("/tmp/adjusted.png")

This results in the following images:

Without plt.subplots_adjust:

With plt.subplots_adjust:

Why does this happen?

Is this a bug?

What can I do to have the colour bar where I want and still be sure that my rotated colour labels will not be cut?

解决方案

Based on a suggestion by @ImportanceOfBeingErnest, I tried to adjust before moving the colour bar. This resulted in the following image:

Since I actually don't want the dendrogram, but just the clustering, I can obtain a more pleasing result by using the dendrogram box to put the colour bar:

#!/usr/bin/env python3

import seaborn as sns
import matplotlib.pyplot as plt

iris = sns.load_dataset("iris")
species = iris.pop("species")
# Make long column names
iris.columns = ["________".join(label.split("_")) for label in iris.columns]

g = sns.clustermap(iris, col_cluster=False, yticklabels=False)
plt.setp(g.ax_heatmap.get_xticklabels(), rotation=90)
# Adjust to have the column labels not cut out
plt.subplots_adjust(bottom=0.5)
g.cax.set_position([.15, .2, .03, .45])
plt.savefig("/tmp/adjusted_before.png")

plt.cla()

g = sns.clustermap(iris, col_cluster=False, yticklabels=False)
plt.setp(g.ax_heatmap.get_xticklabels(), rotation=90)
# Adjust to have the column labels not cut out
plt.subplots_adjust(bottom=0.5)
# Remove the dendrogram (https://stackoverflow.com/a/42418968/1878788)
g.ax_row_dendrogram.set_visible(False)
# Use the dendrogram box to reposition the colour bar
dendro_box = g.ax_row_dendrogram.get_position()
dendro_box.x0 = (dendro_box.x0 + 2 * dendro_box.x1) / 3
g.cax.set_position(dendro_box)
# Move the ticks to the left (https://stackoverflow.com/a/36939552/1878788)
g.cax.yaxis.set_ticks_position("left")
# If we add a label to the colour bar
# (cbar_kws={"label" : "the_label"} in clustermap arguments)
# we also need to move the label
# g.cax.yaxis.set_label_position("left")
plt.savefig("/tmp/adjusted_before_using_row_dendrogram_box.png")

This generates the following image:


Edit: The same issue occurs with plt.tight_layout.

Further developing my heatmap, I wanted to add row colours with legends (using an approach proposed in this answer). In my real application case, the legend takes enough horizontal space to be cut out of the image.

I wanted to use plt.tight_layout to adjust the image. This again interferes with the colour bar relocation (and doesn't even solve the cut legend issue...), as illustrated with the following examples.

#!/usr/bin/env python3

import seaborn as sns
import matplotlib.pyplot as plt

iris = sns.load_dataset("iris")
species = iris.pop("species")
# Make long column names
iris.columns = ["________".join(label.split("_")) for label in iris.columns]


# Associating colours with species
species_list = species.unique()
label_colours = dict(zip(species_list, sns.color_palette("colorblind", len(species_list))))
row_colours = species.map(label_colours)

g = sns.clustermap(iris, col_cluster=False, yticklabels=False, row_colors=row_colours, cbar_kws={"label" : "measure"})
# Adding row colour legend
# https://stackoverflow.com/a/27992943/1878788
for (label, colour) in label_colours.items():
    # Make long label
    g.ax_col_dendrogram.bar(0, 0, color=colour, label="Iris___________________{}".format(label))
g.ax_col_dendrogram.legend(loc="center", ncol=3)
# Rotating column labels
plt.setp(g.ax_heatmap.get_xticklabels(), rotation=90)
# Adjust to have the column labels not cut out
plt.subplots_adjust(bottom=0.5)
# Remove the dendrogram (https://stackoverflow.com/a/42418968/1878788)
g.ax_row_dendrogram.set_visible(False)
# Use the dendrogram box to reposition the colour bar
dendro_box = g.ax_row_dendrogram.get_position()
dendro_box.x0 = (dendro_box.x0 + 2 * dendro_box.x1) / 3
g.cax.set_position(dendro_box)
# Move the ticks and labels to the left (https://stackoverflow.com/a/36939552/1878788)
g.cax.yaxis.set_ticks_position("left")
g.cax.yaxis.set_label_position("left")
plt.savefig("/tmp/with_row_colour_lengend.png")

plt.cla()

g = sns.clustermap(iris, col_cluster=False, yticklabels=False, row_colors=row_colours, cbar_kws={"label" : "measure"})
# Adding row colour legend
# https://stackoverflow.com/a/27992943/1878788
for (label, colour) in label_colours.items():
    # Make long label
    g.ax_col_dendrogram.bar(0, 0, color=colour, label="Iris___________________{}".format(label))
g.ax_col_dendrogram.legend(loc="center", ncol=3)
# Rotating column labels
plt.setp(g.ax_heatmap.get_xticklabels(), rotation=90)
# Adjust to have the column labels not cut out
plt.subplots_adjust(bottom=0.5)
# Remove the dendrogram (https://stackoverflow.com/a/42418968/1878788)
g.ax_row_dendrogram.set_visible(False)
# Use the dendrogram box to reposition the colour bar
dendro_box = g.ax_row_dendrogram.get_position()
dendro_box.x0 = (dendro_box.x0 + 2 * dendro_box.x1) / 3
g.cax.set_position(dendro_box)
# Move the ticks and labels to the left (https://stackoverflow.com/a/36939552/1878788)
g.cax.yaxis.set_ticks_position("left")
g.cax.yaxis.set_label_position("left")
plt.tight_layout()
plt.savefig("/tmp/tight_after.png")

plt.cla()

g = sns.clustermap(iris, col_cluster=False, yticklabels=False, row_colors=row_colours, cbar_kws={"label" : "measure"})
# Adding row colour legend
# https://stackoverflow.com/a/27992943/1878788
for (label, colour) in label_colours.items():
    # Make long label
    g.ax_col_dendrogram.bar(0, 0, color=colour, label="Iris___________________{}".format(label))
g.ax_col_dendrogram.legend(loc="center", ncol=3)
plt.tight_layout()
# Rotating column labels
plt.setp(g.ax_heatmap.get_xticklabels(), rotation=90)
# Adjust to have the column labels not cut out
plt.subplots_adjust(bottom=0.5)
# Remove the dendrogram (https://stackoverflow.com/a/42418968/1878788)
g.ax_row_dendrogram.set_visible(False)
# Use the dendrogram box to reposition the colour bar
dendro_box = g.ax_row_dendrogram.get_position()
dendro_box.x0 = (dendro_box.x0 + 2 * dendro_box.x1) / 3
g.cax.set_position(dendro_box)
# Move the ticks and labels to the left (https://stackoverflow.com/a/36939552/1878788)
g.cax.yaxis.set_ticks_position("left")
g.cax.yaxis.set_label_position("left")
plt.savefig("/tmp/tight_before.png")

This results in the following figures:

Without plt.tight_layout, the right-most label is cut (the species should be "virginica"):

Calling plt.tight_layout after relocating the colour bar:

Calling plt.tight_layout before relocating the colour bar:

这篇关于seaborn clustermap:subplots_adjust取消彩条重定位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 04:12