Move seaborn plot legend to a different position

I'm using factorplot(kind="bar") with seaborn.

The plot is fine except the legend is misplaced: too much to the right, text goes out of the plot's shaded area.

How do I make seaborn place the legend somewhere else, such as in top-left instead of middle-right?

175532 次浏览

Modifying the example here:

You can use legend_out = False

import seaborn as sns
sns.set(style="whitegrid")


titanic = sns.load_dataset("titanic")


g = sns.factorplot("class", "survived", "sex",
data=titanic, kind="bar",
size=6, palette="muted",
legend_out=False)
g.despine(left=True)
g.set_ylabels("survival probability")

enter image description here

Building on @user308827's answer: you can use legend=False in factorplot and specify the legend through matplotlib:

import seaborn as sns
import matplotlib.pyplot as plt
sns.set(style="whitegrid")


titanic = sns.load_dataset("titanic")


g = sns.factorplot("class", "survived", "sex",
data=titanic, kind="bar",
size=6, palette="muted",
legend=False)
g.despine(left=True)
plt.legend(loc='upper left')
g.set_ylabels("survival probability")
  • plt acts on the current axes. To get axes from a FacetGrid use fig.
    • g.fig.get_axes()[0].legend(loc='lower left')

This is how I was able to move the legend to a particular place inside the plot and change the aspect and size of the plot:

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
matplotlib.style.use('ggplot')
import seaborn as sns
sns.set(style="ticks")


figure_name = 'rater_violinplot.png'
figure_output_path = output_path + figure_name


viol_plot = sns.factorplot(x="Rater",
y="Confidence",
hue="Event Type",
data=combo_df,
palette="colorblind",
kind='violin',
size = 10,
aspect = 1.5,
legend=False)


viol_plot.ax.legend(loc=2)
viol_plot.fig.savefig(figure_output_path)

Legend location changed

This worked for me to change the size and aspect of the plot as well as move the legend outside the plot area.

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
matplotlib.style.use('ggplot')
import seaborn as sns
sns.set(style="ticks")




figure_name = 'rater_violinplot.png'
figure_output_path = output_path + figure_name


viol_plot = sns.factorplot(x="Rater",
y="Confidence",
hue="Event Type",
data=combo_df,
palette="colorblind",
kind='violin',
size = 10,
aspect = 1.5,
legend_out=True)


viol_plot.fig.savefig(figure_output_path)

violin plot with changed size, aspect and legend located outside

I figured this out from mwaskom's answer here and Fernando Hernandez's answer here.

Check out the docs here: https://matplotlib.org/users/legend_guide.html#legend-location

adding this simply worked to bring legend out of the plot:

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

If you wish to customize your legend, just use the add_legend method. It takes the same parameters as matplotlib plt.legend.

import seaborn as sns
sns.set(style="whitegrid")


titanic = sns.load_dataset("titanic")


g = sns.factorplot("class", "survived", "sex",
data=titanic, kind="bar",
size=6, palette="muted",
legend_out=False)
g.despine(left=True)
g.set_ylabels("survival probability")
g.add_legend(bbox_to_anchor=(1.05, 0), loc=2, borderaxespad=0.)

it seems you can directly call:

g = sns.factorplot("class", "survived", "sex",
data=titanic, kind="bar",
size=6, palette="muted",
legend_out=False)


g._legend.set_bbox_to_anchor((.7, 1.1))
import matplotlib.pyplot as plt
import seaborn as sns


# load the data
penguins = sns.load_dataset('penguins', cache=False)

Figure Level Plot

g = sns.displot(penguins, x="bill_length_mm", hue="species", col="island", col_wrap=2, height=3)
sns.move_legend(g, "upper left", bbox_to_anchor=(.55, .45), title='Species')
plt.show()

enter image description here

Axes Level Plot

ax = sns.histplot(penguins, x="bill_length_mm", hue="species")
sns.move_legend(ax, "lower center", bbox_to_anchor=(.5, 1), ncol=3, title=None, frameon=False)
plt.show()

enter image description here

Using object oriented API:

fig,ax = plt.subplots(1,1)
sns.someplot(...,ax=ax)
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles, labels,loc="upper left")

source: https://matplotlib.org/stable/tutorials/intermediate/legend_guide.html