7

I am tying to change the location as well as labels of my legend in Seaborn scatterplot. Here is my code:

ax_total_message_ratio=sns.scatterplot(x='total_messages', y='email_messages_ratio',hue='poi',data=df_new)
ax_total_message_ratio.set_title("Email Messages Ratio vs. Total Messages Across Poi",y=1.12,fontsize=20,fontweight='bold')
ax_total_message_ratio.set_ylabel('Email Messages Ratio')
ax_total_message_ratio.set_xlabel('Total Messages')
ax_total_message_ratio.legend.loc("lower right")
put.show()

enter image description here But I am getting following error message; 'function' object has no attribute 'loc'. Can I get some help on how to control legends with Seaborn? Additionally, I also need to replace 0 by No and 1 by Yes in the legend labels. Thanks

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
jay
  • 1,319
  • 6
  • 23
  • 42
  • 2
    Have you tried `ax_total_message_ratio.legend(loc="lower right")`? – William Miller Feb 14 '19 at 02:48
  • @WilliamMiller, Thanks for your clarification. it did help me to fix the location problem.But can I get any guidance on how to change the labels. Help is appreciated – jay Feb 14 '19 at 03:00
  • I'm curious how the 0 and 1 got into the legend in the first place. Which seaborn version are you using? (I'm asking because I am unable to construct a plot like the one above that has numbers in the legend, yet categorical colors) – ImportanceOfBeingErnest Feb 14 '19 at 04:45
  • @ImportanceOfBeingErnest I am using Seaborn heron 0.9.0.Hope it helps – jay Feb 14 '19 at 22:47
  • See also [Edit legend title and labels of Seaborn scatterplot and countplot](https://stackoverflow.com/questions/60350781/edit-legend-title-of-seaborn-scatterplot-and-countplot/74886914#74886914) – JohanC Dec 22 '22 at 10:23

2 Answers2

8

You can use the convenience method get_legend_handles_labels() to get the handles and the text of the labels:

ax=sns.scatterplot(x='total_messages', y='email_messages_ratio',hue='poi',data=df_new)

handles, labels  =  ax.get_legend_handles_labels()

ax.legend(handles, ['Yes', 'No'], loc='lower right')
fotis j
  • 427
  • 1
  • 6
  • 14
7

You can adjust the position using the loc keyword in calling legend(), like

ax_total_message_ratio.legend(loc="lower right")

To include custom labels for your markers you can create a custom legend, i.e.

import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

custom = [Line2D([], [], marker='.', color='b', linestyle='None'),
          Line2D([], [], marker='.', color='r', linestyle='None')]

fig = plt.figure(figsize=(8,5))

plt.legend(custom, ['Yes', 'No'], loc='lower right')
plt.show()

This will give you

Sample plot with custom legend

and should remove the automatically generated legend, leaving only the custom legend.

William Miller
  • 9,839
  • 3
  • 25
  • 46
  • Thanks for your help. It solves my problem.on a side note, the title `poi` is no more visible. But that's minor. I relabeled as `poi` and `non-poi` for the reader's clarity. Highly appreciated. – jay Feb 14 '19 at 22:46
  • @jayant You can add the title as a keyword argument `title="title"` in `plt.legend()` – William Miller Feb 14 '19 at 22:48
  • Thats great. I got that done. one note, it seems we can also use axes object also to use the `legend` properties, i.e. `ax_total_message_ratio.legend(custom,['Non-Poi','Poi'],title="POI")`, similarly as you advised with `plt.legend`. It is helpful to know both of these work. just a note. Great thanks to you. – jay Feb 14 '19 at 22:55
  • @jayant Yes you can call `legend` on an axes object (as I said at the beginning) - I used `plt.legend()` in my example arbitrarily. – William Miller Feb 14 '19 at 22:58
  • Thanks for the notes on the title.. however, I tried `plt.legend(title='')`, `my_plot.legend(title='')` and `my_plot.legend_.set_title('')` ... none works :/ do you have an idea why? – jjrr Feb 02 '20 at 16:27
  • 1
    @jjrr Not without seeing the entire code I'm afraid - do you have a link to the code (e.g. on GitHub) that you're using? If not would perhaps you should open a new question and include the code – William Miller Feb 03 '20 at 00:35