Search code examples
pythonpandasseaborn

FacetGrid shows no legend for histplot


Let's say, I have the following Pandas dataframe:

import pandas as pd
import seaborn as sns
import numpy as np

df1 = pd.DataFrame({
    "kind": "used",
    "val1": np.random.rand(100),
    "val2": np.random.rand(100),
})

df1.loc[0:50, "kind"] = "unused"

df_melt = pd.melt(df1, id_vars="kind", value_vars=["val1", "val2"])

The dataframe df_melt should now end up in FacetGrid where each plot is a histogram of one of the values (i.e. val1 and val2). Within the plot, the kind column should be used as hue, so that we get two groups (the used and unused elements).

These groups should be shown in a legend somewhere in the plot.

g = sns.FacetGrid(df_melt, col="variable")
g.map_dataframe(sns.histplot, x="value", log_scale=True, hue="kind", legend=True)

which yields:

plot of the data of df_melt

However, as you can see, there is no legend being plotted. g._legend_data is also empty.

How do I get Seaborn to show a legend for my plot?


Solution

  • Seaborn's FacetGrid documentation contains a warning in a colored box:

    When using seaborn functions that infer semantic mappings from a dataset, care must be taken to synchronize those mappings across facets (e.g., by defining the hue mapping with a palette dict or setting the data type of the variables to category). In most cases, it will be better to use a figure-level function (e.g. relplot() or catplot()) than to use FacetGrid directly.

    For histograms you can use sns.displot to create a grid. It combines most parameters of sns.FacetGrid and sns.histplot.

    import matplotlib.pyplot as plt
    import seaborn as sns
    import pandas as pd
    import numpy as np
    
    df1 = pd.DataFrame({
        "kind": "used",
        "val1": np.random.rand(100),
        "val2": np.random.rand(100),
    })
    
    df1.loc[0:50, "kind"] = "unused"
    
    df_melt = pd.melt(df1, id_vars="kind", value_vars=["val1", "val2"])
    
    sns.displot(data=df_melt, kind='hist', x="value", col="variable", log_scale=True, hue="kind", legend=True)
    
    plt.show()
    

    sns.displot instead of sns.FacetGrid