Folo Molo
Folo Molo

Reputation: 35

How to center "hue" coloring using seaborn stripplot

This is my plot: Plot

I would like the coloring to be centered at 0 within the plot. While I managed to have the legend centered at 0, this does not apply to the dots in the plot (i.e. I would expect them to be gray at the zero value).

This is my code which generates the plots:

import matplotlib.colors as mcolors
import matplotlib.cm as cm
import seaborn as sns

def plot_jitter(df):

    plot = sns.stripplot(x='category', y='overall_margin', hue='overall_margin', data=df, 
                  palette='coolwarm_r', 
                  jitter=True, edgecolor='none', alpha=.60)
    plot.get_legend().set_visible(False)
    sns.despine()
    plt.axhline(0, 0,1,color='grey').set_linestyle("--")

    #Drawing the side color bar
    normalize = mcolors.TwoSlopeNorm(vcenter=0, vmin=df['overall_margin'].min(), vmax=df['overall_margin'].max())
    colormap = cm.coolwarm_r
    
    [plt.plot(color=colormap(normalize(x))) for x in df['overall_margin']]

    scalarmappaple = cm.ScalarMappable(norm=normalize, cmap=colormap)
    scalarmappaple.set_array(df['overall_margin'])
    plt.colorbar(scalarmappaple)

Upvotes: 1

Views: 2029

Answers (1)

Alex
Alex

Reputation: 7045

By using sns.scatterplot instead of sns.stripplot you can use the c, norm and cmap parameters like so.

# Load demo data, scale `total_bill` to be in the range [0, 1]
tips = sns.load_dataset("tips")
tips["total_bill"] = tips["total_bill"].div(100)

Building the plot:

fig, ax = plt.subplots()

# Get/set params for the colour mapping
vcenter = 0.15
vmin, vmax = tips["total_bill"].min(), tips["total_bill"].max()
normalize = mcolors.TwoSlopeNorm(vcenter=vcenter, vmin=vmin, vmax=vmax)
colormap = cm.coolwarm_r

# plot with:
#  - `c`: array of floats for colour mapping
#  - `cmap`: the colourmap you want
#  - `norm`: to scale the data from `c`
sns.scatterplot(
    x="day",
    y="total_bill",
    data=tips,
    c=tips["total_bill"],
    norm=normalize,
    cmap=colormap,
    ax=ax,
)
ax.axhline(vcenter, color="grey", ls="--")

# Tweak the points to mimic `sns.stripplot`
pts = ax.collections[0]
pts.set_offsets(pts.get_offsets() + np.c_[np.random.uniform(-.1, .1, len(tips)), np.zeros(len(tips))])
ax.margins(x=0.15)

scalarmappaple = cm.ScalarMappable(norm=normalize, cmap=colormap)
scalarmappaple.set_array(tips["total_bill"])
fig.colorbar(scalarmappaple)

Which produces:

enter image description here

The code to mimic stripplot is from seaborn's github issues

Upvotes: 4

Related Questions