9

In the Seaborn's FacetGrid based lineplot, would like to change the label title. It seemed like a simple thing, but it turned out to be a hairy task

tips = sns.load_dataset("tips")
g = sns.FacetGrid(tips, col= 'day', legend_out= True,)
g.map(sns.lineplot, 'total_bill', 'tip', 'sex', 'time',
     ci = False)    
g.fig.legend()

legend title 'sex'

I wanted to change the label title to 'gender' from 'sex' by adding 'title' argument. But it turns out that become a headline on top the existing title

g.add_legend(title = 'Gender')

legend title 'sex' with headline 'Gender'

I also tried to access the fig.legend to change the text, but now it shows multiple legends, probably due to the multi-faceted plots.

l = g.fig.legend()
l.texts[0].set_text('Gender')

legend title 'Gender', however, with multiple legends

I am sure there may be a 'hacky' way to change the name by changing the variable names in the data or so, but I am wondering whether there is a way to simply replace the Seabron FacetGrid's legend title or, if it is not possible, add the title through 'fig.legend' while showing single relevant legend. Many thanks!

jameskim
  • 95
  • 2
  • 5
  • You can access the `FacetGrid` legend using g._legend. I got the idea from [this post](https://stackoverflow.com/a/45211976/11542679). I think referring to the [matplotlib tutorial](https://matplotlib.org/tutorials/intermediate/legend_guide.html) after that should help you sort this out. – Hawklaz Dec 08 '20 at 01:43

2 Answers2

1

Why not replace the name of the "sex" columns with "Gender"?

import matplotlib.pyplot as plt
import seaborn as sns

tips = sns.load_dataset("tips")
tips.columns = [n if n != "sex" else "Gender" for n in tips.columns]

g = sns.FacetGrid(tips, col= 'day')
g.map(sns.lineplot, 'total_bill', 'tip', 'Gender', 'time',
     ci = False)    
g.add_legend()

plt.show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • 1
    Thanks for the answer. I am sure that's one of the ways to do it. However, since I am planning to produce similar graphs for a number of different datasets, arbitrary changing the variable name may not be a long-term solution. – jameskim Aug 23 '19 at 23:20
  • It's the cleanest solution you can have. Any other solution would require to mess around with the legend texts themselves. – ImportanceOfBeingErnest Aug 23 '19 at 23:23
  • I do agree with your opinion. It surely is the cleanest solution for this particular dataset. I am just hoping to have a reasonable solution to apply to multiple different datasets with multiple different types of variables. – jameskim Aug 24 '19 at 00:29
  • That's precisely the point. If you have multiple datasets, you would sometimes need to replace the first legend entry, sometimes the third, etc. That's pretty cumbersome. If instead you pass a dataset where you have replaced the name of the column, you don't need to care about anything else any more. And replacing a column is easy enough to automate for different datasets. – ImportanceOfBeingErnest Aug 24 '19 at 00:32
  • 1
    While I agree this is the way to go, this doesn't answer the question asked :/ – nlhnt Jan 09 '22 at 23:30
1

After adding the legend using the FacetGrid.add_legend() method, you can then directly access the underlying matplotlib.legend.Legend object to reset the text by chaining the get_text() (which in this case is the first of the six elements and hence indexed as 0, but you could likewise change the 'time' label using index 3) and set_text() methods:

tips = sns.load_dataset("tips")
g = sns.FacetGrid(tips, col= 'day')
g.map(sns.lineplot, 'total_bill', 'tip', 'sex', 'time',
     errorbar=('ci', False))
g.add_legend()
g.legend.get_texts()[0].set_text('Gender')
plt.show()

enter image description here

freesoup
  • 65
  • 6
  • If `g.legend.get_texts()[0]` is referencing the first category in your legend (and not the title), try `g.legend.set_title('Legend Title')`. – jglad Feb 08 '23 at 06:45