使用单个数据帧的多个标签调整图例 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 联合图的主要内容,如果未能解决你的问题,请参考以下文章