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.

Improve multiple semantic legend titles

See original GitHub issue

Currently the legends for lineplot (#1285) and scatterplot (#1436) don’t indicate what variable each of the levels represent. I punted on this but it needs a solution. One option is to cram everything into the legend title but that’s not ideal. I think doing something with legend entries that have invisible handles and and then bumping the legend text so it looks centered would work:

f, ax = plt.subplots()

h1 = ax.scatter([], [], s=0, label="Title 1")
h2 = ax.scatter([], [], label="level 1")
h3 = ax.scatter([], [], s=0, label="Title 2")
h4 = ax.scatter([], [], label="level 2")

legend = ax.legend()
for t in legend.get_texts()[::2]:
    xfm = transforms.offset_copy(t.get_transform(), ax.figure, x=-10, units="points")
    t.set_transform(xfm)

image

But getting this to be really robust is going to be tricky.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:24 (24 by maintainers)

github_iconTop GitHub Comments

1reaction
mwaskomcommented, Jun 28, 2018

Why not?

f, ax = plt.subplots()
ax.scatter(1, 1, visible=False)

image

1reaction
CRiddlercommented, Jun 15, 2018

Ah I just saw your comment as I was coming to post this. I think checking on the legend artist visibility wouldn’t be too hard and be a more appropriate proxy than alpha because we can set the visibility of the handle afterwards. What I was just thinking is that instead of even adding the subtitles to the Axes at all (right now, we’re calling ax.scatter([], [], label="title 1") solely for the label) we don’t really want anything to do with the scatter what if we had the user supply the ordering in a wrapper around ax.legend()? Sorry for throwing a billion ideas at you!

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

def subtitle_legend(ax, legend_format):
    new_handles = []
    
    handles, labels = ax.get_legend_handles_labels()
    label_dict = dict(zip(labels, handles))
    
    #Means 2 labels were the same
    if len(label_dict) != len(labels):
        raise ValueError("Can not have repeated levels in labels!")
    
    for subtitle, level_order in legend_format.items():
        #Roll a blank handle to add in the subtitle
        blank_handle = matplotlib.patches.Patch(visible=False, label=subtitle)
        new_handles.append(blank_handle)
        
        for level in level_order:
            handle = label_dict[level]
            new_handles.append(handle)

    #Labels are populated from handle.get_label() when we only supply handles as an arg
    legend = ax.legend(handles=new_handles)

    #Turn off DrawingArea visibility to left justify the text if it contains a subtitle
    for draw_area in legend.findobj(matplotlib.offsetbox.DrawingArea):
        for handle in draw_area.get_children():
            if handle.get_label() in legend_format:
                draw_area.set_visible(False)

    return legend


def seaborn_scatter():
    sns.set()
    
    tips = sns.load_dataset('tips')
    ax = sns.scatterplot(x="total_bill", y="tip",
                         hue="sex", style="smoker", size="size",
                         data=tips)

    #nice and explicit call to reorder the legend
    legend_format = {'Sex (hue)': ['Male', 'Female'],
                     'Group Size (size)': ['0', '2', '4', '6'],
                     'Smoker (shape)': ['Yes', 'No']
                    }

    # Use this instead of `ax.legend()`
    #   this returns the legend as well for further tweaking
    #   can also set it up to take kwargs to pass onto `ax.legend` call
    subtitle_legend(ax, legend_format=legend_format)

    plt.show()

seaborn_scatter()

figure_1

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to change legend title in R using ggplot ? - GeeksforGeeks
Method 1: Using scale_colour_discrete() To change the legend title using this method, simply provide the required title as the value to its  ......
Read more >
Multiple titles in legend in matplotlib - python - Stack Overflow
After visiting dozens of questions here I came to this solution that works perfectly for me, but maybe there was a better way...
Read more >
Legend guide — Matplotlib 3.6.2 documentation
Legend guide# · Controlling the legend entries# · Creating artists specifically for adding to the legend (aka. Proxy artists)# · Legend location# ·...
Read more >
The Field Set Legend element - HTML - MDN Web Docs
<fieldset>. 2. <legend>Choose your favorite monster</legend>. 3. ​. 4. <input type="radio" id="kraken" name="monster" value="K">.
Read more >
Semantic Highlight Guide | Visual Studio Code Extension API
Themes can opt in to use semantic tokens to improve and refine the syntax ... names the types and modifiers it's going to...
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