How to specify the palette in a seaborn figure-level plot

Question:

I’ve learned to not use seaborn if I need to make specific changes or detail oriented visualizations but I feel like I’m not fully utilizing what it has to offer at times.

  • I have a series of 2D slices plotting cluster memberships.
  • Issue is between the cases, the number of clusters present changes which causes seaborn to reset the color palette every case, leading to the same color being used for different clusters.

I’d like to specify the color palette specifically with seaborn. I’m not sure if I’m just missing something or if this is a detail that cannot be addressed when using facetgrid?

df = pd.DataFrame()
df['I'] = np.full(20,1)
df['J'] = np.arange(0,20,1)
df['K'] = [1]*12 + [2]*8
df['CM_Hard'] = [1]*10 + [2] + [0] + [2]*8 
df['Realization'] = ['p25']*10 + ['p50']*9 + ['p75']

for layer in df['K'].unique():
    layer_data_slice = df.groupby('K').get_group(layer)

    g = sns.FacetGrid(layer_data_slice, col="Realization",hue="CM_Hard")
    g.map_dataframe(sns.scatterplot, x="I", y="J", s=50, marker='+', palette='deep')
    g.add_legend()

    g.fig.suptitle("Training Realizations, Layer: {}".format(int(layer)), size=16, y=1.05)
    figure_title = 'Training_Layer_{}'.format(int(layer))

Link to current plot issue with duplicate color palettes

I’ve attempted to use the following for the palette definition but it does not affect the plots:

palette = {0:"tab:cyan", 1:"tab:orange", 2:"tab:purple"}

This has been attempted with "tab:color", "color" and the RGB reference with no luck. There is no error it simply doesn’t do anything when changed.

Asked By: Jaynkumz

||

Answers:

  • Update to seaborn 0.11.2. Using FacetGrid directly is not recommended. Use seaborn.relplot with kind='scatter' for a figure-level plot.
  • The keys in palette must match the unique values from the column passed to hue.
  • Tested in python 3.8.12, pandas 1.3.4, matplotlib 3.4.3, seaborn 0.11.2
import seaborn as sns

# load the data - this is a pandas.DataFrame
tips = sns.load_dataset('tips')

# set the hue palette as a dict for custom mapping
palette = {'Lunch': "tab:cyan", 'Dinner':"tab:purple"}

# plot
p = sns.relplot(kind='scatter', data=tips, col='smoker', x='total_bill', y='tip', hue='time', palette=palette)

enter image description here

  • Using new sample data added to OP
  • If the 'K' column is renamed to 'Layer', then the subplot title will match your example: df = df.rename({'K': 'Layer'}, axis=1)
p = sns.relplot(data=df, x='I', y='J', s=50, marker='+', row='Layer', col='Realization', hue='CM_Hard', palette=palette, height=4)
p.fig.suptitle('Training Realizations', y=1.05, size=16)

enter image description here

FacetGrid

  • Note that palette is in the FacetGrid call, not map_dataframe
for layer in df['K'].unique():
    layer_data_slice = df.groupby('K').get_group(layer)

    g = sns.FacetGrid(layer_data_slice, col="Realization",hue="CM_Hard", palette=palette)
    g.map_dataframe(sns.scatterplot, x="I", y="J", s=50, marker='+')
    g.add_legend()

    g.fig.suptitle("Training Realizations, Layer: {}".format(int(layer)), size=16, y=1.05)
    figure_title = 'Training_Layer_{}'.format(int(layer))

enter image description here

Answered By: Trenton McKinney