Reputation: 367
I want to combine multiple plot legends with a catplot legend and place the single result in the upper right. I also want to replace the labels on both. Examples - {"avg tip":"average", "Yes":"Smoker","No":"Non smoker"}
My actual work is more complex but here's a nice example of the point stolen from someone else's answer elsewhere.
Example:
tips = sns.load_dataset("tips")
g = sns.catplot(x="day", y="total_bill", hue="smoker", kind="violin", inner='quartile', split=True, data=tips)
legend=g._legend
legend.set(title='')
l1 = plt.axhline(tips.total_bill.mean(), ls='--', color='k', alpha=0.3, zorder=0, label='Avg tip')
l2 = plt.axhline(tips.total_bill.mean()+tips.total_bill.std(), ls='--', color='r', alpha=0.1, zorder=0, label='+1 std')
l2 = plt.axhline(tips.total_bill.mean()-tips.total_bill.std(), ls='--', color='b', alpha=0.1, zorder=0, label='1 std')
legend2 = plt.legend(title='', loc='upper right', handles=[l1,l2,l3])
Upvotes: 1
Views: 526
Reputation: 367
Figured out the answer myself eventually. Answer for posterity so please edit or suggest edits to improve....
Catplot's legend appears not to be the same as the legend of other plots, presumably because catplot is already a combination of other plots from a facetplot call, or some figure level magic or something. I could not add other handles directly to the legend for catplot, but must have the default parameter legend=True for catplot or it doesn't return any legend artist at all. Instead, I took the following approach:
output an artist
g = sns.catplot(x="day", y="total_bill", hue="smoker", kind="violin", inner='quartile', split=True, data=tips)
extract the legend handles
catplot_handles = g._legend.legendHandles
set the legend visibility to False
g._legend.set(visible=False)
add the catplot handles to a list of other artists in an externally created legend, optionally adding a list of all labels in this call. Note, I've explicitly shown this as 2 concatenated lists for clarity only
plt.legend(handles=[l1,l2,l3]+catplot_handles, labels=['label1',label2','label3']+['cat_label1',cat_label2'])
import matplotlib.pyplot as plt
# load data
tips = sns.load_dataset("tips")
# run my primary cateegory plot, assigning the output to 'g'
g = sns.catplot(x="day", y="total_bill", hue="smoker", kind="violin", inner='quartile', split=True, data=tips)
# Run my other assigned plots
l1 = plt.axhline(tips.total_bill.mean(), ls='--', color='k', alpha=0.5, zorder=0)
l2 = plt.axhline(tips.total_bill.mean()+tips.total_bill.std(), ls='--', color='r', alpha=0.3, zorder=0)
l3 = plt.axhline(tips.total_bill.mean()-tips.total_bill.std(), ls='--', color='b', alpha=0.3, zorder=0)
# extract the catplot artist legend handles
catplot_handles = g._legend.legendHandles
# make the in built catplot legend invisible
g._legend.set(visible=False)
# merge all the artist legend handles
legend2 = plt.legend(title='', loc='upper right', handles=[l1,l2,l3]+catplot_handles, labels=['Average', '+1 std', '-1 std', 'Smoker', 'Non-smoker'])
plt.show()
Upvotes: 1