使用单个数据帧的多个标签调整图例 Seaborn 联合图

Posted

技术标签:

【中文标题】使用单个数据帧的多个标签调整图例 Seaborn 联合图【英文标题】:Adjust legend Seaborn jointplot with several labels for one single dataframe 【发布时间】:2021-07-24 01:04:12 【问题描述】:

假设我有一个具有这种结构的 pandas 数据框:

Column 1   Column2 Column3
x1         y1       0
x2         y2       0
x3         y3       1
x4         y4       1
x5         y5       1
          ....
x_n-1      y_n-1    5
x_n        y_n      5

我想创建一个联合图,在其中根据 Column3 的值分配不同的颜色。我使用的命令是

h = sns.jointplot(x="Column1", y="Column2", data=data, hue="Column3")

所以我有 6 种不同颜色的所有点。从上一个命令中得出的图例具有标签“0”、“1”、...“5”,这些标签不是解释性的。而不是它们,我想要“label0”、“label1”等等。

我尝试使用以下命令:

h.ax_joint.legend([data.loc[data['Column3'] == 0], data.loc[data['Column3'] == 1], data.loc[data['Column3'] == 2], data.loc[data['Column3'] == 3], data.loc[data['Column3'] == 4], data.loc[data['Column3'] == 5]], ['label0', 'label1', 'label2', 'label3', 'label4', 'label5'])

但是执行它我有以下消息:

A proxy artist may be used instead. See: https://matplotlib.org/users/legend_guide.html#creating-artists-specifically-for-adding-to-the-legend-aka-proxy-artists

当然,它不再绘制任何图例了。我一直在查看建议的文档,但我不知道如何改进它。有人有想法吗?提前致谢!

【问题讨论】:

【参考方案1】:

最简单且最符合 Seaborn 精神的方法是(暂时)重命名色调列的标签:

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

data = pd.DataFrame("Column1": np.random.randn(36) * 10,
                     "Column2": np.arange(36) % 6 + np.random.randn(36) / 4,
                     "Column3": np.arange(36) % 6)
labels = ['label0', 'label1', 'label2', 'label3', 'label4', 'label5']
g = sns.jointplot(data=data.replace("Column3": i: label for i, label in enumerate(labels)),
                  x="Column1", y="Column2", hue="Column3", palette="turbo")
g.ax_joint.invert_yaxis()

另一种选择是再次创建图例并提供新标签。第二个图例将替换默认图例。如果您还想更改其他属性(例如图例的位置或删除其标题),这会很有用:

g = sns.jointplot(x="Column1", y="Column2", data=data, hue="Column3", palette="turbo")
handles, labels = g.ax_joint.get_legend_handles_labels()
g.ax_joint.legend(handles=handles, labels=['label0', 'label1', 'label2', 'label3', 'label4', 'label5'],
                  title="Column3")

PS:这是sns.jointplot(..., kind="kde")的示例:

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

data = pd.DataFrame("Column1": np.random.randn(36) * 10,
                     "Column2": np.arange(36) % 6 + np.random.randn(36) / 4,
                     "Column3": np.arange(36) % 6)
labels = ['label0', 'label1', 'label2', 'label3', 'label4', 'label5']
g = sns.jointplot(data=data.replace("Column3": i: label for i, label in enumerate(labels)),
                  x="Column1", y="Column2", hue="Column3", palette="turbo", kind="kde")
g.ax_joint.invert_yaxis()

【讨论】:

当您设置 hue 参数、使用 kind="kde" 并尝试在绘图中添加带有标签的线条时,这些方法都不起作用,因为无论出于何种原因, kind="kde" 都不起作用返回句柄和标签。 我做了更多的测试,似乎设置“kind”会覆盖“hue”,所以总是返回空的句柄和标签列表。 @kelkka 第一种方法似乎适用于kind="kde"(使用seaborn 0.11.2)。第二种方法不起作用,因为 kdeplot 创建了一个您无法通过 g.ax_joint.get_legend_handles_labels() 访问的自定义图例,尽管您可以改用 handles = g.ax_joint.legend_.legendHandles 我最终没有使用'kind="kde",而是使用了g.plot_joint(sns.kdeplot),然后我可以通过'g.ax_joint.get_legend_handles_labels()'访问图例 @kelkka 很高兴您找到了适合您的方法。图像出了点问题,但代码按描述工作,至少在我的环境中是这样。我现在上传了正确的图片。

以上是关于使用单个数据帧的多个标签调整图例 Seaborn 联合图的主要内容,如果未能解决你的问题,请参考以下文章

如何为图形级功能编辑 seaborn 图例标题和标签

更改 Seaborn 散点图中的图例位置和标签

图例与来自不同数据帧的多个图的交互:如何处理这种交互?

如何将seaborn图例拆分为多列?

如何在 seaborn 散点图中编辑多个图例框?

使用多个变量时更改图例标签