question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Not clear how to reposition seaborn.histplot legend

See original GitHub issue

I was pretty excited about seeing the histplot functionality coming out, and I’m getting beautiful figures with it already.

I’m trying to finetune my figures and reposition the legends - but am running into issues when moving the legend. Below is toy example

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
fig, ax = plt.subplots()
x = np.hstack((np.random.normal(0, 1, 100), np.random.normal(-0.5, 1, 100), np.random.normal(0.5, 1, 100)))
data = pd.DataFrame({'x': x, 'd' : ['a'] * 100 + ['b'] * 100 + ['c'] * 100})
g = sns.histplot(data, x='x', hue="d", element="step", stat="probability", ax=ax)

image

When I move the legend to the upper left, the legend disappears with the warning No handles with labels found to put in legend..

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
fig, ax = plt.subplots()
x = np.hstack((np.random.normal(0, 1, 100), np.random.normal(-0.5, 1, 100), np.random.normal(0.5, 1, 100)))
data = pd.DataFrame({'x': x, 'd' : ['a'] * 100 + ['b'] * 100 + ['c'] * 100})
g = sns.histplot(data, x='x', hue="d", element="step", stat="probability", ax=ax, legend=False)
ax.legend(loc='upper-left')

image

This is interesting, because it doesn’t appear to be an issue with the other plots https://stackoverflow.com/questions/27019079/move-seaborn-plot-legend-to-a-different-position https://stackoverflow.com/questions/53733755/how-to-move-legend-to-outside-of-a-seaborn-scatterplot/53737271

I’m curious if this is unique to histplot (or if I’m overlooking something).

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:13
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

46reactions
mwaskomcommented, Sep 14, 2020

Hi, yes, legends do work a little bit differently in the distribution plots, and they’re also still a little rough around the edges.

In short, seaborn currently has two options: add a bunch of phantom artists to the axes with labels (meaning that calling ax.legend() again will pick them up and replace the existing legend) or pass handles and labels directly to ax.legend (meaning that inspecting or modifying the artists is easier, but “moving” the legend is harder).

IMO the root problem is that matplotlib legend objects lack a public-facing API for modifying them once they exist. I’m pushing on matplotlib to fix this limitation in core, which would be better than implementing a hacky work around in seaborn (thread here).

Here’s also a issue tracking some known ongoing difficulties with legends in seaborn, some (but not all) of which are attributable to the matplotlib-level API: https://github.com/mwaskom/seaborn/issues/2231. Solving some of these will require moving way from “option 1” above.

Right now, your best bet is probably something like this:


def move_legend(ax, new_loc, **kws):
    old_legend = ax.legend_
    handles = old_legend.legendHandles
    labels = [t.get_text() for t in old_legend.get_texts()]
    title = old_legend.get_title().get_text()
    ax.legend(handles, labels, loc=new_loc, title=title, **kws)
    
move_legend(ax, "upper left")
10reactions
mwaskomcommented, Aug 15, 2021

I’m going to consider this closed with #2643, which codifies the move_legend hack as a helper function in seaborn. It doesn’t solve the “histplot works differently from other plots” problem, but I think that’s unlikely to change in the future (or rather, for reasons discussed above, other functions will work more like histplot). Legend inconsistencies / difficulties are otherwise tracked in #2231.

So, official recommendation is to move (and update) the legend, for any seaborn plot, like this:

ax = sns.histplot(data=penguins, x="bill_length_mm", hue="species")
sns.move_legend(ax, "lower center", bbox_to_anchor=(.5, 1), ncol=3, title_fontsize=14)

image

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to Change the Position of Legend in Seaborn
Seaborn plot with default legend position. First, let us make a scatterplot with Seaborn's scatterplot() function with default legend position.
Read more >
Move seaborn plot legend to a different position - Stack Overflow
Building on @user308827's answer: you can use legend=False in factorplot and specify the legend through matplotlib: import seaborn as sns ...
Read more >
seaborn.move_legend — seaborn 0.12.1 documentation
Recreate a plot's legend at a new location. The name is a slight misnomer. Matplotlib legends do not expose public control over their...
Read more >
How to Change the Position of a Legend in Seaborn - Statology
To change the position of a legend in a seaborn plot, you can use the plt.legend() command. ... The default location is “best”...
Read more >
Seaborn plot legend: how to add, change and remove?
Seaborn will display the following warning: No handles with labels found to put in legend. Change Seaborn legend location. Probably the most visible...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found