Seaborn boxplot + stripplot:重复图例

Seaborn boxplot + stripplot: duplicate legend

您可以在 seaborn 中轻松制作的最酷的东西之一是 boxplot + stripplot 组合:

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

tips = sns.load_dataset("tips")

sns.stripplot(x="day", y="total_bill", hue="smoker",
data=tips, jitter=True,
palette="Set2", split=True,linewidth=1,edgecolor='gray')

sns.boxplot(x="day", y="total_bill", hue="smoker",
data=tips,palette="Set2",fliersize=0)

plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.);

不幸的是,正如您在上面看到的,它产生了双图例,一个用于箱线图,一个用于条带图。显然,这看起来很荒谬和多余。但我似乎无法找到摆脱 stripplot 传奇而只留下 boxplot 传奇的方法。也许,我可以以某种方式从 plt.legend 中删除项目,但我在文档中找不到它。

您可以 get what handles/labels should exist 在实际绘制图例本身之前在图例中。然后你只用你想要的特定的来绘制图例。

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

tips = sns.load_dataset("tips")

sns.stripplot(x="day", y="total_bill", hue="smoker",
data=tips, jitter=True,
palette="Set2", split=True,linewidth=1,edgecolor='gray')

# Get the ax object to use later.
ax = sns.boxplot(x="day", y="total_bill", hue="smoker",
data=tips,palette="Set2",fliersize=0)

# Get the handles and labels. For this example it'll be 2 tuples
# of length 4 each.
handles, labels = ax.get_legend_handles_labels()

# When creating the legend, only use the first two elements
# to effectively remove the last two.
l = plt.legend(handles[0:2], labels[0:2], bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)

我想补充一点,如果您使用子图,图例处理可能会有点问题。上面的代码(@Sergey Antopolskiy 和@Ffisegydd)给出了一个非常好的图形,不会在子图中重新定位图例,它一直非常顽固地出现。请参阅上面适用于子图的代码:

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

tips = sns.load_dataset("tips")

fig, axes = sns.plt.subplots(2,2)

sns.stripplot(x="day", y="total_bill", hue="smoker",
              data=tips, jitter=True, palette="Set2", 
              split=True,linewidth=1,edgecolor='gray', ax = axes[0,0])

ax = sns.boxplot(x="day", y="total_bill", hue="smoker",
                 data=tips,palette="Set2",fliersize=0, ax = axes[0,0])

handles, labels = ax.get_legend_handles_labels()

l = plt.legend(handles[0:2], labels[0:2], bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)

原来的传说还在。为了擦除它,你可以添加这一行:

axes[0,0].legend(handles[:0], labels[:0])

编辑:在最新版本的 seaborn (>0.9.0) 中,这曾经在评论中指出的角落留下一个小白框。要解决它,请使用 the answer in this post:

axes[0,0].get_legend().remove()