为一个数据框调整具有多个标签的图例 Seaborn jointplot

Adjust legend Seaborn jointplot with several labels for one single dataframe

假设我有一个具有以下结构的 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

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

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

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()