<p dir="auto">I have a use case where I only want to have a legend for the style (but not the hue).<br>
Currently, the relational plotters <code class="notranslate">lineplot</code>, <code class="notranslate">scatterplot</code>, etc. only allow to switch on and off the entire legend.<br>
What I would like to have is a possibility to control the display of the groups (style, hue, size) individually.</p>
<p dir="auto">In my case, I would like to use something like <code class="notranslate">sns.lineplot(..., legend="style")</code>.<br>
The parameter could also be a list to only show two groups: <code class="notranslate">sns.lineplot(..., legend=["style", "hue"])</code>.<br>
<code class="notranslate">"brief"</code> could used like this: <code class="notranslate">sns.lineplot(..., legend=["style", "hue_brief"])</code>.<br>
The old usage should also stay possible: <code class="notranslate">sns.lineplot(..., legend="brief")</code>.</p>
<p dir="auto">What do you think? Would this be something that the community could find valuable?</p>
<p dir="auto">Here are some notes about legends, which are an area of future work.</p>
<p dir="auto">Challenges with legends include:</p>
<h2 dir="auto">Multi-variable legends</h2>
<p dir="auto">When multiple semantic mappings exist (currently only possible in the relational plots), the legends use a hack that adds a legend entry with an invisible artist handle to serve as a "subtitle". This is not ideal. Matplotlib legends do not have any concept of a "subtitle". It's possible to add multiple legends to a plot. But it's not possible to add multiple legends that both use <code class="notranslate">loc="best"</code>; they will be placed in the same location. Because <code class="notranslate">loc="best"</code> is determined at draw-time, it's also not possible how to but one legend in the "best" location and then stick the other one next to or under it. It would also be better if it were possible to assign the sub-legends to e.g. different columns). See <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="344976369" data-permission-text="Title is private" data-url="https://github.com/mwaskom/seaborn/issues/1519" data-hovercard-type="pull_request" data-hovercard-url="/mwaskom/seaborn/pull/1519/hovercard" href="https://github.com/mwaskom/seaborn/pull/1519">#1519</a> for some related work.</p>
<h2 dir="auto">Numeric semantic mappings</h2>
<p dir="auto">When using a numeric semantic mapping, a set of handles is added to the legend with evenly-spaced labels. This is intended to act like a "colorbar", but it doesn't look that much like a colorbar, and it's an ongoing source of confusion. Ideally, there would be something that looks like a colorbar inside the legend itself.</p>
<h2 dir="auto">No consistent approach to legend creation</h2>
<p dir="auto">Most plotting functions add proxy artists with label attributes to the axes and then call <code class="notranslate">legend()</code> to pick them up. This has the advantage that <code class="notranslate">legend()</code> can be called again with new kwargs (e.g. a different location) and it will be recreated. But it adds a lot of extraneous artists to the legend, which is confusing when trying to do deep customization. The new distribution plots create proxy artists but just pass them directly to <code class="notranslate">legend()</code>. The disadvantage is that calling <code class="notranslate">legend()</code> again will erase these artists. And in general, this should be predictable, and users should have access to the legends and their handles should they need to modify them.</p>
<h2 dir="auto">Legends are not very customizable</h2>
<p dir="auto">For numeric mappings, there's no way to specify exactly which labels to use. And in general, plotting functions don't take a <code class="notranslate">legend_kws</code> dict, but probably they should.</p>
<h2 dir="auto">Seaborn legend creation is a mess</h2>
<p dir="auto">The code that creates legends in seaborn is distributed and complicated, especially in the case of multi-variable legends in the relational module. While the semantic mappers could own the logic of determining what values to show in the legend, the plotting objects/functions know what artist to use and which attributes to modify.</p>
<h2 dir="auto">Existing legends don't use matplotlib kwargs to show artists</h2>
<p dir="auto">Most of the existing legends represent the semantic mapping, but don't always correspond directly to the artists in the figure. e.g. if you make a scatterplot and pass <code class="notranslate">marker="x"</code>, the legend will still have dots representing the color or size. And not using the linewidth/edgecolor parameters causes problems for how the size variable is represented (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="456547901" data-permission-text="Title is private" data-url="https://github.com/mwaskom/seaborn/issues/1763" data-hovercard-type="issue" data-hovercard-url="/mwaskom/seaborn/issues/1763/hovercard" href="https://github.com/mwaskom/seaborn/issues/1763">#1763</a>, <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="743288319" data-permission-text="Title is private" data-url="https://github.com/mwaskom/seaborn/issues/2355" data-hovercard-type="issue" data-hovercard-url="/mwaskom/seaborn/issues/2355/hovercard" href="https://github.com/mwaskom/seaborn/issues/2355">#2355</a>, <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="1268411904" data-permission-text="Title is private" data-url="https://github.com/mwaskom/seaborn/issues/2852" data-hovercard-type="issue" data-hovercard-url="/mwaskom/seaborn/issues/2852/hovercard" href="https://github.com/mwaskom/seaborn/issues/2852">#2852</a>).</p>
<h2 dir="auto">Matplotlib legend API has limitations</h2>
<p dir="auto">Some of these problems exist because the matplotlib legend API has some limitations, both for users and for seaborn. Some of these problems would be less painful if it were easier to modify a legend after plotting, e.g. to move it or to add new entries to it. Moving a legend seems basically impossible through the public API, adding entries doesn't seem possible either. Some aspects of the legends can be modified in-place, but not through obvious methods. And the legend code uses a lot of private attributes and functions, so extending it (i.e. through subclassing) is not really possible</p>
<p dir="auto">Unclear at this point whether the best path forward is to try and get an enhanced legend API from matplotlib or to fork the legend code and adapt to get what we need in seaborn itself.</p>