Sos
Sos

Reputation: 1949

Hue, colorbar, or scatterplot colors do not match in seaborn.scatterplot

Using an example from another post, I'm adding a color bar to a scatter plot. The idea is that both dot hue, and colorbar hue, should conform to the maximum and minimum possible, so that the colorbar can reflect the range of values in the hue:

x= [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200]
y= [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200]
z= [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 255]

df = pd.DataFrame(list(zip(x, y, z)), columns =['x', 'y', 'z']) 


colormap=matplotlib.cm.viridis
#A continuous color bar needs to be added independently
norm = plt.Normalize(df.z.min(), df.z.max())
sm = plt.cm.ScalarMappable(cmap=colormap, norm=norm)
sm.set_array([])

fig = plt.figure(figsize = (10,8), dpi=300)
ax = fig.add_subplot(1,1,1) 
sb.scatterplot(x="x", y="y",
                 hue="z", 
                 hue_norm=(0,255),
                 data=df,
                 palette=colormap,
                 ax=ax
                 )
ax.legend(bbox_to_anchor=(0, 1), loc=2, borderaxespad=0., title='hue from sb.scatterplot')
ax.figure.colorbar(sm).set_label('hue from sm')

plt.xlim(0,255)
plt.ylim(0,255)
plt.show()

enter image description here

Note how the hue from the scatterplot, even with hue_norm, ranges up to 300. In turn, the hue from the colorbar ranges from 0 to 255. From experimenting with values in hue_norm, it seems that matplotlib always rounds it off so that you have a "good" (even?) number of intervals.

My questions are:

  1. Is which one is showing an incorrect range: the scatterplot, the scatterplot legend, or the colorbar? And how to correct it?
  2. How could you retrieve min and max hue from the scatterplot (in this case 0 and 300, respectively), in order to set them as maximum and minimum of the colorbar?

Upvotes: 0

Views: 3152

Answers (1)

Diziet Asahi
Diziet Asahi

Reputation: 40667

Do you really need to use seaborn's scatterplot(). Using a numerical hue is always quite messy.

The following code is much simpler and yields an unambiguous output

fig, ax = plt.subplots()
g = ax.scatter(df['x'],df['y'], c=df['z'], cmap=colormap)
fig.colorbar(g)

enter image description here

Upvotes: 2

Related Questions