2
votes

I am trying to generate a figure with 4 subplots, each of which is a Seaborn histplot. The figure definition lines are:

fig,axes=plt.subplots(2,2,figsize=(6.3,7),sharex=True,sharey=True)
(ax1,ax2),(ax3,ax4)=axes
fig.subplots_adjust(wspace=0.1,hspace=0.2)

I would like to define strings for legend entries in each of the subplots. As an example, I am using the following code for the first subplot:

sp1=sns.histplot(df_dn,x="ktau",hue="statind",element="step", stat="density",common_norm=True,fill=False,palette=colvec,ax=ax1)
ax1.set_title(r'$d_n$')
ax1.set_xlabel(r'max($F_{a,max}$)')
ax1.set_ylabel(r'$\tau_{ken}$')
legend_labels,_=ax1.get_legend_handles_labels()
ax1.legend(legend_labels,['dep-','ind-','ind+','dep+'],title='Stat.ind.')

The legend is not showing correctly (legend entries are not plotted and the legend title is the name of the hue variable ("statind"). Please note I have successfully used the same code for other figures in which I used Seaborn relplots instead of histplots.

1

1 Answers

3
votes

The main problem is that ax1.get_legend_handles_labels() returns empty lists (note that the first return value are the handles, the second would be the labels). At least for the current (0.11.1) version of seaborn's histplot().

To get the handles, you can do legend = ax1.get_legend(); handles = legend.legendHandles.

To recreate the legend, first the existing legend needs to be removed. Then, the new legend can be created starting from some handles.

Also note that to be sure of the order of the labels, it helps to set hue_order. Here is some example code to show the ideas:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns

df_dn = pd.DataFrame({'ktau': np.random.randn(4000).cumsum(),
                      'statind': np.repeat([*'abcd'], 1000)})

fig, ax1 = plt.subplots()
sp1 = sns.histplot(df_dn, x="ktau", hue="statind", hue_order=['a', 'b', 'c', 'd'],
                   element="step", stat="density", common_norm=True, fill=False, ax=ax1)
ax1.set_title(r'$d_n$')
ax1.set_xlabel(r'max($F_{a,max}$)')
ax1.set_ylabel(r'$\tau_{ken}$')
legend = ax1.get_legend()
handles = legend.legendHandles
legend.remove()
ax1.legend(handles, ['dep-', 'ind-', 'ind+', 'dep+'], title='Stat.ind.')
plt.show()

example plot