Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jointplot doesn't return handles and labels #2677

Closed
ISipi opened this issue Oct 13, 2021 · 5 comments
Closed

Jointplot doesn't return handles and labels #2677

ISipi opened this issue Oct 13, 2021 · 5 comments
Labels

Comments

@ISipi
Copy link

ISipi commented Oct 13, 2021

I noticed that when using

g = sns.jointplot(data=data, x="X", y="Y", hue="Group", kind="kde")

we don't get handles or labels when using
print(g.ax_joint.get_legend_handles_labels())

However, removing the "kind" keyword does print handles and labels - it doesn't matter what you insert as the input to "kind", but it always seems to override the handles and labels from "hue". Is there an easy fix for this?

@mwaskom
Copy link
Owner

mwaskom commented Oct 13, 2021

Could you please provide a reproducible example? Thanks.

@ISipi
Copy link
Author

ISipi commented Oct 14, 2021

Could you please provide a reproducible example? Thanks.

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd


df = pd.DataFrame()
df['x'] = np.random.normal(2, 0.5, 200)
df['y'] = np.linspace(0, 1, 200)
df['group'] = np.random.choice(3, size=200)


g = sns.jointplot(data=df, x='x', y='y', hue='group')
print(g.ax_joint.get_legend_handles_labels())

g = sns.jointplot(data=df, x='x', y='y', hue='group', kind='kde')
print(g.ax_joint.get_legend_handles_labels())

@mwaskom
Copy link
Owner

mwaskom commented Oct 14, 2021

I assume you want this data because you want to move the legend. (It can be helpful when opening an issue to provide context about what you're trying to do beyond the specific operation that isn't working). If that's the case I'd refer you to this issue.

Otherwise, this is not a bug from my perspective (nor does it have anything to do with jointplot, really): kdeplot does not add labeled artists to the axes, and that's what gets used when you specify kind="kde".

If you're trying to do some customization other than moving the legend it may be better to ask on stackoverflow.

@ISipi
Copy link
Author

ISipi commented Oct 14, 2021

I actually wanted to change the labels in the legend for the kde-plot like this:

handles, labels = g.ax_joint.get_legend_handles_labels()
labels[2:] = ["Group 1", "Group 2", "Group 3", "Group 4"]
g.ax_joint.legend(handles=handles, labels=labels, title='Legend', fontsize=16)

In the above, the first two labels in labels are set by g.ax_joint.axhline.

I only managed to do this by not using kind='kde' and opting for

g = sns.jointplot(data=df, x='x', y='y', hue='group')
g.plot_joint(sns.kdeplot)

which does allow me to access the handles and labels for the kde-plot with g.ax_joint.get_legend_handles_labels().

So, an example of a working code in my instance:

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd


df = pd.DataFrame()
df['x'] = np.random.normal(2, 0.5, 200)
df['y'] = np.linspace(0, 1, 200)
df['group'] = np.random.choice(3, size=200)

g = sns.jointplot(data=df, x='x', y='y', hue='group')
g.plot_joint(sns.kdeplot)

print(g.ax_joint.get_legend_handles_labels())

But this is not satisfactory, because it leaves the points from the sns.jointplot in the background.

@mwaskom
Copy link
Owner

mwaskom commented Oct 20, 2021

So, an example of a working code in my instance

I don't think this example is "working", at least not in the way you want, because those are not handles for the KDE plot; they are handles for scatterplot points. See what happens when you try to recreate the legend with them:

g = sns.jointplot(data=df, x='x', y='y', hue='group')
g.plot_joint(sns.kdeplot)
g.ax_joint.legend(*g.ax_joint.get_legend_handles_labels())

image

I actually wanted to change the labels in the legend for the kde-plot like this

The officially-supported way to change the labels that seaborn adds is to send different data into its functions. Or you can manipulate the matplotlib objects after plotting. Unfortunately, the matplotlib legend object is less flexible than the Axes or the Artists that comprise the plot, but you can modify the legend text objects:

texts = g.ax_joint.legend_.texts
for t, label in zip(texts, "ABC"):
    t.set_text(label)

image

Closing as there's no bug here on the seaborn side.

@mwaskom mwaskom closed this as completed Oct 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants