Hue and shared x-axis not working Seaborn facet grid

Viewed 394

I'm aiming to plot a stacked chart that displays normalised values from a pandas df. Using below, each unique value in Item has it's own row. I then aim to plot a stacked chart containing normalised values from Label, with Num along the x-axis.

However, hue seems to pass a different set of colours for each individual Item. They aren't consistent, for ex, A in Up is blue, while A in Right is green.

I'm also hoping to share the x-axis for Num is consistent for each Item. The values aren't aligned with the respective x-axis.

import pandas as pd
import numpy as np

df = pd.DataFrame({      
    'Num' : [1,2,1,2,3,2,1,3,2,2,1,2,3,3,1,3],
    'Label' : ['A','B','C','B','B','C','C','B','B','A','C','A','B','A','C','A'],   
    'Item' : ['Up','Left','Up','Left','Down','Right','Up','Down','Right','Down','Right','Up','Up','Right','Down','Left'],        
   })

g = sns.FacetGrid(df, 
                  row = 'Item', 
                  row_order = ['Up','Right','Down','Left'],                           
                  aspect = 2, 
                  height = 4, 
                  sharex = True,
                  legend_out = True
                  )

g.map_dataframe(sns.histplot, x = 'Num', hue = 'Label', multiple = 'fill', shrink = 0.8, binwidth = 1)
g.add_legend()
1 Answers

Using FacetGrid directly can be tricky; it is basically doing a groupb-by and for loop over the axes, and it does not track any function-specific state that would be needed to make sure that the answer to questions like "what order should be used for each hue level" is the same in each facet. So you would need to supply that information somehow (i.e. hue_order or passing a palette dictionary). In fact, there is a warning in the documentation to this effect.

But you generally don't need to use FacetGrid directly; you can use one of the figure-level functions, which do all of the bookkeeping for you to make sure that information is aligned across facets. Here you would use displot:

sns.displot(
    data=df, x="Num", hue="Label",
    row='Item', row_order=['Up','Right','Down','Left'],
    multiple="fill", shrink=.8, discrete=True,
    aspect=4, height=2,
)

enter image description here

Note that I've made one other change to your code here, which is to use discrete=True instead of binwidth=1, which is what I think you want.

Related