Подтвердить что ты не робот

Seaborn boxplot + stripplot: дублированная легенда

Одной из самых крутых вещей, которые вы можете легко сделать в 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.);

boxplot + stripplot

К сожалению, как вы можете видеть выше, это создавало двойную легенду, одну для boxplot, одну для stripplot. Очевидно, это выглядит смешно и излишне. Но я не могу найти способ избавиться от легенды stripplot и оставить легенду boxplot. Вероятно, я могу как-то удалить элементы из plt.legend, но я не могу найти его в документации.

4b9b3361

Ответ 1

Вы можете получить, какие дескрипторы/метки должны существовать в легенде, прежде чем вы на самом деле рисуете легенду. Затем вы рисуете легенду только с теми, которые вы хотите.

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

example plot

Ответ 2

Я хочу добавить, что если вы используете подсюжеты, обработка легенды может быть немного более проблематичной. Приведенный выше код, который, кстати, дает очень хорошую цифру (@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.)

duplicated legend

Оригинальная легенда остается. Чтобы стереть его, вы можете добавить эту строку:

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

corrected legend

Изменение: в последних версиях seaborn (> 0.9.0), это обычно оставляло маленькую белую коробку в углу, как указано в комментариях. Чтобы решить эту проблему, используйте ответ в этом посте:

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