Search code examples
pythonmatplotlibgraphseabornfigure

Remove one of the two legends produced in this Seaborn figure?


I have just started using seaborn to produce my figures. However I can't seem to remove one of the legends produced here.

I am trying to plot two accuracies against each other and draw a line along the diagonal to make it easier to see which has performed better (if anyone has a better way of plotting this data in seaborn - let me know!). The legend I'd like to keep is the one on the left, that shows the different colours for 'N_bands' and different shapes for 'Subject No'

ax1 = sns.relplot(y='y',x='x',data=df,hue='N bands',legend='full',style='Subject No.',markers=['.','^','<','>','8','s','p','*','P','X','D','H','d']).set(ylim=(80,100),xlim=(80,100))
ax2 = sns.lineplot(x=range(80,110),y=range(80,110),legend='full')

enter image description here

I have tried setting the kwarg legend to 'full','brief' and False for both ax1 and ax2 (together and separately) and it only seems to remove the one on the left, or both.

I have also tried to remove the axes using matplotlib

ax1.ax.legend_.remove()
ax2.legend_.remove()

But this results in the same behaviour (left legend dissapearing).

UPDATE: Here is a minimal example you can run yourself:

test_data = np.array([[1.,2.,100.,9.],[2.,1.,100.,8.],[3.,4.,200.,7.]])
test_df = pd.DataFrame(columns=['x','y','p','q'], data=test_data)

sns.set_context("paper")
ax1=sns.relplot(y='y',x='x',data=test_df,hue='p',style='q',markers=['.','^','<','>','8'],legend='full').set(ylim=(0,4),xlim=(0,4))
ax2=sns.lineplot(x=range(0,5),y=range(0,5),legend='full')

enter image description here

Although this doesn't reproduce the error perfectly as the right legend is coloured (I have no idea how to reproduce this error then - does the way my dataframe was created make a difference?). But the essence of the problem remains - how do I remove the legend on the right but keep the one on the left?


Solution

  • You're plotting a lineplot in the (only) axes of a FacetGrid produced via relplot. That's quite unconventional, so strange things might happen.

    One option to remove the legend of the FacetGrid but keeping the one from the lineplot would be

    g._legend.remove()
    

    Full code (where I also corrected for the confusing naming if grids and axes)

    import numpy as np
    import matplotlib.pyplot as plt
    import pandas as pd
    import seaborn as sns
    
    test_data = np.array([[1.,2.,100.,9.],[2.,1.,100.,8.],[3.,4.,200.,7.]])
    test_df = pd.DataFrame(columns=['x','y','p','q'], data=test_data)
    
    sns.set_context("paper")
    g=sns.relplot(y='y',x='x',data=test_df,hue='p',style='q',markers=['.','^','<','>','8'], legend='full')
    
    sns.lineplot(x=range(0,5),y=range(0,5),legend='full', ax=g.axes[0,0])
    
    g._legend.remove()
    
    plt.show()
    

    enter image description here

    Note that this is kind of a hack, and it might break in future seaborn versions.

    The other option is to not use a FacetGrid here, but just plot a scatter and a line plot in one axes,

    ax1 = sns.scatterplot(y='y',x='x',data=test_df,hue='p',style='q',
                          markers=['.','^','<','>','8'], legend='full')
    
    sns.lineplot(x=range(0,5),y=range(0,5), legend='full', ax=ax1)
    
    plt.show()
    

    enter image description here