将Seaborn传奇分成两个不同的盒子

时间:2019-06-05 08:38:33

标签: python matplotlib seaborn legend

我正在使用Seaborn生成多种类型的图,但是这里将基于包含的数据集仅使用一个简单的示例进行说明:

import seaborn
tips = seaborn.load_dataset("tips")
axes = seaborn.scatterplot(x="day", y="tip", size="sex", hue="time", data=tips)

enter image description here

在此结果中,单个图例框包含两个标题“时间”和“性”,每个标题都有子元素。

我如何轻松地将图例分成两个框,每个框都有一个标题?即一个用于表示颜色代码的图例框(可以放在左侧),另一个用于指示尺寸代码的图例框(可以放在右侧)。

3 个答案:

答案 0 :(得分:2)

以下代码效果很好,因为时间类别的数量与性别类别相同。如果不是这种情况,则必须计算先验每个“标签”需要多少行图例

fig = plt.figure()
tips = seaborn.load_dataset("tips")
axes = seaborn.scatterplot(x="day", y="tip", size="sex", hue="time", data=tips)
h,l = axes.get_legend_handles_labels()
l1 = axes.legend(h[:int(len(h)/2)],l[:int(len(l)/2)], loc='upper left')
l2 = axes.legend(h[int(len(h)/2):],l[int(len(l)/2):], loc='upper right')
axes.add_artist(l1) # we need this because the 2nd call to legend() erases the first

output graph

答案 1 :(得分:1)

如果您要使用matplotlib而不是seaborn,则

import matplotlib.pyplot as plt
import seaborn
tips = seaborn.load_dataset("tips")

tips["time_int"] = tips["time"].cat.codes
tips["sex_int"] = (tips["sex"].cat.codes*5+5)**2

sc = plt.scatter(x="day", y="tip", s="sex_int", c="time_int", data = tips, cmap="bwr")

leg1 = plt.legend(sc.legend_elements("colors")[0], tips["time"].cat.categories,
                  title="Time", loc="upper right")
leg2 = plt.legend(sc.legend_elements("sizes")[0], tips["sex"].cat.categories,
                  title="Sex", loc="upper left")
plt.gca().add_artist(leg1)
plt.show()

enter image description here

答案 2 :(得分:0)

我拿了Diziet's answer并扩大了它。他提供了我需要的必要语法,但正如他指出的那样,他缺少一种计算拆分图例所需的图例行数的方法。我已经添加了它,并编写了一个完整的脚本:

# Modules #
import seaborn
from matplotlib import pyplot

# Plot #
tips = seaborn.load_dataset("tips")
axes = seaborn.scatterplot(x="day", y="tip", size="sex", hue="time", data=tips)

# Legend split and place outside #
num_of_colors   = len(tips['time'].unique()) + 1
handles, labels = axes.get_legend_handles_labels()
color_hl = handles[:num_of_colors], labels[:num_of_colors]
sizes_hl = handles[num_of_colors:], labels[num_of_colors:]

# Call legend twice #
color_leg = axes.legend(*color_hl,
                        bbox_to_anchor = (1.05, 1),
                        loc            = 'upper left',
                        borderaxespad  = 0.)
sizes_leg = axes.legend(*sizes_hl,
                        bbox_to_anchor = (1.05, 0),
                        loc            = 'lower left',
                        borderaxespad  = 0.)

# We need this because the 2nd call to legend() erases the first #
axes.add_artist(color_leg)

# Adjust #
pyplot.subplots_adjust(right=0.75)

# Display #
pyplot.ion()
pyplot.show()

enter image description here