Seaborn聚类图:subplots_adjust取消颜色条重新定位

4

我正在尝试使用seaborn制作一个具有侧边色条的热力图。然而,在我的实际应用中,我有很长的列名需要旋转。这需要使用plt.subplots_adjust,否则标签将无法适应图片:

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

使用以下简单示例,我发现最后一个命令取消了颜色条的重新定位:
#!/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")

这将导致以下图像:
没有 plt.subplots_adjustunadjustedplt.subplots_adjustadjusted 为什么会这样?
这是一个 bug 吗?
我该怎么做才能让我的颜色栏在我想要的位置,同时又确保我的旋转颜色标签不会被切断?

1
subplots_adjust 调整子图位置,正如其名称所示,这是可以预期的。难道你不只是想先调整子图,然后再设置条形图的位置吗?改变命令的顺序应该会得到所需的结果。 - ImportanceOfBeingErnest
谢谢,那很有帮助。不过我必须使用另一种方法来定位颜色条。我会将此作为答案发布。 - bli
1个回答

3

根据@ImportanceOfBeingErnest的建议,在移动颜色条之前,我尝试进行了调整。这导致了以下图片:

adjusted_before

由于我实际上不需要树状图,只需要聚类结果,因此我可以通过使用树状图框来放置颜色条而获得更好的结果:

#!/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://dev59.com/2lgQ5IYBdhLWcg3wqFoF#42418968)
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://dev59.com/KVoU5IYBdhLWcg3w7aGP#36939552)
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")

这将生成以下图片:

使用行树状图盒子之前进行调整


编辑:使用plt.tight_layout也会出现同样的问题。

在进一步开发我的热力图时,我想要添加带有图例的行颜色(使用此答案中提出的方法)。在我的实际应用中,图例需要足够的水平空间才能从图像中剪切出来。

我想使用plt.tight_layout来调整图像。这又干扰了颜色条的重新定位(甚至没有解决剪切图例的问题...),如下面的示例所示。

#!/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://dev59.com/Cl4c5IYBdhLWcg3wXZcC#27992943
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://dev59.com/2lgQ5IYBdhLWcg3wqFoF#42418968)
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://dev59.com/KVoU5IYBdhLWcg3w7aGP#36939552)
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://dev59.com/Cl4c5IYBdhLWcg3wXZcC#27992943
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://dev59.com/2lgQ5IYBdhLWcg3wqFoF#42418968)
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://dev59.com/KVoU5IYBdhLWcg3w7aGP#36939552)
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://dev59.com/Cl4c5IYBdhLWcg3wXZcC#27992943
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://dev59.com/2lgQ5IYBdhLWcg3wqFoF#42418968)
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://dev59.com/KVoU5IYBdhLWcg3w7aGP#36939552)
g.cax.yaxis.set_ticks_position("left")
g.cax.yaxis.set_label_position("left")
plt.savefig("/tmp/tight_before.png")

这导致以下几个图表:
没有使用plt.tight_layout,右侧的标签被截断 (物种应该是 "virginica"): large_row_colour_legend 在重新定位色条之后调用plt.tight_layouttight_after 在重新定位色条之前调用plt.tight_layouttight_before

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