jakebrinkmann jakebrinkmann - 4 months ago 33
Python Question

How to use multiple colormaps in seaborn on same plot

I have some test data:

import numpy as np
x_data = np.arange(10)
y = np.random.rand(len(x_data))


With different properties

ix1 = x_data < 5
ix2 = x_data >= 5


I want to investigate the differences visually, but am messing the plot up:

import matplotlib.pyplot as plt
import seaborn as sns
sns.set_context('poster')

fig, ax = plt.subplots(figsize=(4, 4))
for i, x in enumerate(x_data):
if ix1[i]:
sns.set_palette('rainbow', sum(ix1))
if ix2[i]:
sns.set_palette('coolwarm', sum(ix2))
plt.plot(x, y[i], 'o', label='{}'.format(x))
plt.legend(loc='best', prop={'size': 6})
plt.show()


The result should be points 0-4 are rainbow (red-violet) and points 5-9 are coolwarm (blue-white-red), but instead:

seaborn output

So, two questions:


  1. Is it ok to call
    sns.set_palette()
    after calling
    plt.subplots
    ?

  2. Is there a way to set the palette more than once?


Answer

No, because of the way matplotlib works, the color palette is a property of the Axes object and so whatever the currently set palette is at the time an Axes is created is what it's going to use. This is possible to get around if you want to hack on private attributes (see here), but I wouldn't really recommend that.

Here's what I could come up with in your case, using a somewhat different approach that might not be broadly applicable:

pal1 = sns.color_palette('rainbow', sum(ix1))
pal2 = sns.color_palette('coolwarm', sum(ix2))

fig, ax = plt.subplots(figsize=(4, 4))
ax.scatter(x_data[ix1], y[ix1], c=pal1, s=60, label="smaller")
ax.scatter(x_data[ix2], y[ix2], c=pal2, s=60, label="larger")
ax.legend(loc="lower right", scatterpoints=5)

enter image description here

FWIW, this visualization feels pretty complex and hard to process (and the two palettes you've chosen overlap a fair amount and aren't really appropriate for these data) so it might be worth starting with something simpler.