Search code examples
pythonmatplotlibseabornlegendjointplot

Seaborn jointplot legend has gives varying marker size when labels dictated by plt.legend()


Customising the legend of a Seaborn jointplot seems to provoke the markers in the legend vary in size for no apparent reason (see image).

h = sns.jointplot( data = data, x = 'X', y = 'Y', hue = 'Time', palette = cmap) 
plt.legend(title = 't / mins', labels = ['0', '20', '80'], markerscale = 1) 

enter image description here

Is there a way to enforce the same marker size?

Expecting all symbols in the legend to be the same size, which does happen if I don't try to customise using plt.legend().


Solution

  • As seaborn functions usually combine many matplotlib elements, it usually creates custom legend handles. Such legends don't work well together with plt.legend(). Therefore, to change the legend's properties, such as title, location, etc., seaborn introduced sns.move_legend(). To change the marker size for the legend of the jointplot, a marker scale different from 1 would be needed.

    Changing labels is not recommended, as the order can be tricky. It helps to enforce an order via hue_order=. If necessary, one could change the labels by renaming the elements in the hue column.

    sns.jointplot is a figure-level function, creating a JointGrid. You can access the subplot of the main plot via g.ax_joint.

    import matplotlib.pyplot as plt
    import seaborn as sns
    import pandas as pd
    import numpy as np
    
    data = pd.DataFrame({'X': np.random.normal(0.1, 1, (200, 3)).cumsum(axis=0).ravel(),
                         'Y': np.random.normal(0.1, 1, (200, 3)).cumsum(axis=0).ravel(),
                         'Time': np.repeat([0, 20, 80], 200)})
    
    g = sns.jointplot(data=data, x='X', y='Y', hue='Time', hue_order=[0, 20, 80],
                      palette=['limegreen', 'dodgerblue', 'crimson'])
    sns.move_legend(g.ax_joint, title='t / mins', loc='best', markerscale=0.5)
    plt.show()
    

    sns.jointplot with changed legend