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:
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?
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()