matplotlibseabornlegendcatplot

Seaborn catplot legend's background color and border


MWE

from matplotlib import pyplot as plt
import seaborn as sb
df = sb.load_dataset("titanic")
g = sb.catplot(
    data=df, x="who", y="survived", hue="class",
    kind="bar"
)
plt.tight_layout()
plt.savefig('bah.png')

Figure looks bad because the legend is transparent. How do I change its opacity and how can I add a black border around the legend?


Solution

  • For figure-level plots such as sns.catplot(), which create a grid with one or more subplots, seaborn creates a figure legend. For figure-level plots with only one subplot, you can use the axes-level equivalent, which here would be sns.barplot(). These have more standard legend, by default, inside the subplot.

    To change the properties of a seaborn legend, it is recommended to use sns.move_legend(). A minor inconvenience is that move_legend() needs you to explicitly set a position. To get a border, frameon=True and edgecolor=... is needed.

    Unfortunately, plt.tight_layout() doesn't take the figure legend into account. You can call plt.subplots_adjust(right=...) to again create space such that the legend doesn't overlap with the rightmost subplot.

    Here is some example code:

    from matplotlib import pyplot as plt
    import seaborn as sns
    
    df = sns.load_dataset("titanic")
    g = sns.catplot(
        data=df, x="who", y="survived", hue="class",
        kind="bar"
    )
    sns.move_legend(g, frameon=True, facecolor='lightgrey', edgecolor='black',
                    loc='center right', bbox_to_anchor=(1, 0.5))
    plt.tight_layout()
    plt.subplots_adjust(right=0.8) # mitigate overlapping legend due to tight_layout 
    plt.show()
    

    change legend frame and background color in sns.catplot

    PS: Using the standard shortening for seaborn helps to match your code with the documentation and makes it easier to find similar examples on sites such as StackOverflow.