Move seaborn plot legend to a different position
Asked Answered
H

8

97

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?

Hornbeam answered 19/11, 2014 at 14:15 Comment(1)
For seaborn >= 0.11.2 use .move_legend as shown in this answerSettler
A
90

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')
Addieaddiego answered 23/11, 2014 at 0:59 Comment(1)
This generally does not work for seaborn plots.Spotweld
S
52
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

Settler answered 19/8, 2021 at 14:37 Comment(0)
T
22

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

Trafalgar answered 19/11, 2014 at 14:18 Comment(0)
M
21

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

Mythomania answered 6/11, 2018 at 22:49 Comment(1)
This generally does not work with seaborn generated figures.Spotweld
A
9

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.

Aragonite answered 16/7, 2017 at 2:42 Comment(0)
R
4

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))
Roer answered 10/9, 2020 at 23:16 Comment(0)
H
1

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.)
Horbal answered 18/2, 2020 at 10:22 Comment(1)
it seems this creates a new legend. In my code, I have other lines to adjust the legend (title, size, and transparency ..). If I call this to adjust the position, the following lines don't work then...Roer
T
0

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

Tightwad answered 22/9, 2022 at 7:54 Comment(2)
This does not work with current versions of seaborn. Figure-level plots result in an error, and axes-level plots don't result in an error, but the legend does not appear. The correct option is seaborn.move_legendSettler
I just modified my answer. If you pass ax to the argument then it should work just fine.Tightwad

© 2022 - 2024 — McMap. All rights reserved.