Deep dive into seaborn : color palettes
By: Yoann Mocquin
Tags: Python, Plot, Colors, Seaborn

Color spaces

Before stepping into seaborn color palettes, let’s review what are the different color spaces we should know before going on:

the rgb space : a color is defined by a triplet of floating point value between 0 and 1, giving the proportion of red, blue and green. For example (0.1, 0.5, 0.9) would be mostly green, with some blue, and a little bit of red.

would be mostly green, with some blue, and a little bit of red. the hex space : a color is defined by 6 hex-characters #RRGGBB where RR (red), GG (green) and BB (blue) are hexadecimal integers between 00 and FF specifying the intensity of the color. You can see this space as another way of writing the rgb values.

where RR (red), GG (green) and BB (blue) are hexadecimal integers between 00 and FF specifying the intensity of the color. You can see this space as another way of writing the rgb values. the hls space : a color is defined by a triplet of floating point value between 0 and 1, where h maps the different colors, l maps the ligthness (how “bright” is is), and s maps the saturation (how vivid or washed out the color looks).

the husl space : a color is defined by a triplet of floating point value between 0 and 1, where h maps the different colors, l maps the ligthness (how “bright” is is), and s maps the saturation (how vivid or washed out the color looks).

Palette concept

In seaborn, a palette is simply a list of colors. Most of the time, we will handle colors in a rgb space, so a palette is simply a list of 3-uple of floating point values between 0 and 1. For example :

[(0.125, 0.4, 0.705882), (1.0, 0.498, 0.055), (0.17313, 0.6269, 0.1)]

is a palette of 3 colors.

So remember : a palette is a list of colors.

Note that the number of colors (the length of the list) can be any number.

Palettes in seaborn

Let’s import seaborn and load a dataset :

from IPython.display import display

import seaborn as sns

iris_df = sns.load_dataset("iris")

If you want to know more on datasets in seaborn, check out my previous article :

Seaborn uses the concept of palette to predefine the colors of the data you plot. We can see what is the default palette with sns.color_palette :

pal = sns.color_palette()

print(pal)

sns.palplot(pal) [(0.12156862745098039, 0.4666666666666667, 0.7058823529411765), (1.0, 0.4980392156862745, 0.054901960784313725), (0.17254901960784313, 0.6274509803921569, 0.17254901960784313), (0.8392156862745098, 0.15294117647058825, 0.1568627450980392), (0.5803921568627451, 0.403921568627451, 0.7411764705882353), (0.5490196078431373, 0.33725490196078434, 0.29411764705882354), (0.8901960784313725, 0.4666666666666667, 0.7607843137254902), (0.4980392156862745, 0.4980392156862745, 0.4980392156862745), (0.7372549019607844, 0.7411764705882353, 0.13333333333333333), (0.09019607843137255, 0.7450980392156863, 0.8117647058823529)]

Image by Author

There are 3 things we can notice :

calling print on a seaborn color palette will print the list of 3-uple rgb values

on a seaborn color palette will print the list of 3-uple rgb values you can see the palette using sns.palplot . Note that this can also be done with IPython.display.display(pal)

. Note that this can also be done with the default palette has 10 colors

In addition to the default palette, seaborn provides numerous predefined named palettes :

mpl_palette_named_palette = ['Accent', 'Accent_r', 'Blues', 'Blues_r', 'BrBG', 'BrBG_r', 'BuGn', 'BuGn_r', 'BuPu', 'BuPu_r', 'CMRmap', 'CMRmap_r', 'Dark2', 'Dark2_r', 'GnBu', 'GnBu_r', 'Greens', 'Greens_r', 'Greys', 'Greys_r', 'OrRd', 'OrRd_r', 'Oranges', 'Oranges_r', 'PRGn', 'PRGn_r', 'Paired', 'Paired_r', 'Pastel1', 'Pastel1_r', 'Pastel2', 'Pastel2_r', 'PiYG', 'PiYG_r', 'PuBu', 'PuBuGn', 'PuBuGn_r', 'PuBu_r', 'PuOr', 'PuOr_r', 'PuRd', 'PuRd_r', 'Purples', 'Purples_r', 'RdBu', 'RdBu_r', 'RdGy', 'RdGy_r', 'RdPu', 'RdPu_r', 'RdYlBu', 'RdYlBu_r', 'RdYlGn', 'RdYlGn_r', 'Reds', 'Reds_r', 'Set1', 'Set1_r', 'Set2', 'Set2_r', 'Set3', 'Set3_r', 'Spectral', 'Spectral_r', 'Wistia', 'Wistia_r', 'YlGn', 'YlGnBu', 'YlGnBu_r', 'YlGn_r', 'YlOrBr', 'YlOrBr_r', 'YlOrRd', 'YlOrRd_r', 'afmhot', 'afmhot_r', 'autumn', 'autumn_r', 'binary', 'binary_r', 'bone', 'bone_r', 'brg', 'brg_r', 'bwr', 'bwr_r', 'cividis', 'cividis_r', 'cool', 'cool_r', 'coolwarm', 'coolwarm_r', 'copper', 'copper_r', 'crest', 'crest_r', 'cubehelix', 'cubehelix_r', 'flag', 'flag_r', 'flare', 'flare_r', 'gist_earth', 'gist_earth_r', 'gist_gray', 'gist_gray_r', 'gist_heat', 'gist_heat_r', 'gist_ncar', 'gist_ncar_r', 'gist_rainbow', 'gist_rainbow_r', 'gist_stern', 'gist_stern_r', 'gist_yarg', 'gist_yarg_r', 'gnuplot', 'gnuplot2', 'gnuplot2_r', 'gnuplot_r', 'gray', 'gray_r', 'hot', 'hot_r', 'hsv', 'hsv_r', 'icefire', 'icefire_r', 'inferno', 'inferno_r', 'jet', 'jet_r', 'magma', 'magma_r', 'mako', 'mako_r', 'nipy_spectral', 'nipy_spectral_r', 'ocean', 'ocean_r', 'pink', 'pink_r', 'plasma', 'plasma_r', 'prism', 'prism_r', 'rainbow', 'rainbow_r', 'rocket', 'rocket_r', 'seismic', 'seismic_r', 'spring', 'spring_r', 'summer', 'summer_r', 'tab10', 'tab10_r', 'tab20', 'tab20_r', 'tab20b', 'tab20b_r', 'tab20c', 'tab20c_r', 'terrain', 'terrain_r', 'turbo', 'turbo_r', 'twilight', 'twilight_r', 'twilight_shifted', 'twilight_shifted_r', 'viridis', 'viridis_r', 'vlag', 'vlag_r', 'winter', 'winter_r']

sns_named_palettes = ['deep', 'muted', 'bright', 'pastel', 'dark', 'colorblind']



sns.palplot(sns.mpl_palette("Accent"))

Image by Author

We can use the sns.color_palette to introspect other palettes :

# named palette

pal = sns.color_palette("magma")

print(pal)

sns.palplot(pal) [(0.135053, 0.068391, 0.315), (0.372116, 0.092816, 0.499053), (0.594508, 0.175701, 0.501241), (0.828886, 0.262229, 0.430644), (0.973381, 0.46152, 0.361965), (0.997341, 0.733545, 0.505167)]

Image by Author

Notice that by default, the returned palette has length 6.

Remember when we said a color palette is a list of colors ?

Well, that’s not entirely true.

The object returned by sns.color_palette is not really a list of 3-uple :

pal = sns.color_palette("magma")

print(type(pal)) <class 'seaborn.palettes._ColorPalette'>

We don’t need to introspect further what this _ColorPalette object is (especially with the presence of _ meaning the user is not supposed to go this far). So it's not really a list of colors, but it behaves like it !

In addition, color palette can be used with another format : a matplotlib’s colormap. You can tell seaborn to return a matplotlib colormap object with as_cmap=True :

cmap = sns.color_palette("magma", as_cmap=True)

print(type(cmap)) <class 'matplotlib.colors.ListedColormap'>

Plotting with palettes

The very essence of color palettes is to give meaning to your plot. By default, seaborn will use the default palette we saw earlier :

sns.color_palette() sns.scatterplot(

data=iris_df,

x="sepal_length",

y="petal_length",

hue="species",

) <AxesSubplot:xlabel='sepal_length', ylabel='petal_length'>

Image by Author

Notice that the species feature has 3 possible values (setosa, versicolor, and virginica - the "type" of the iris flowers), hence the first 3 colors of the current palette are used.

In all seaborn plotting function, you can use a specific palette for this plot using the palette argument. For example, let's use the named palette "magma" :

# review what the palette looks like

sns.palplot(sns.color_palette("magma"))

Image by Author

sns.scatterplot(

data=iris_df,

x="sepal_length",

y="petal_length",

hue="species",

palette="magma",

) <AxesSubplot:xlabel='sepal_length', ylabel='petal_length'>

Image by Author

Notice that the 3 colors that were used in the plot are not the first 3 colors shown above : in the background seaborn creates a palette of 3 colors based on the magma palette, like this :

sns.palplot(sns.color_palette("magma", n_colors=3))

Image by Author

Set the default palette

Remember, by default, seaborn will use the default palette (unless told otherwise in the plot function call).

To set the default palette, use the sns.set_palette function :

sns.set_palette(

palette="magma",

n_colors=3,

)

Now we can plot the same scatter plot as previously, without using the palette argument :

sns.scatterplot(

data=iris_df,

x="sepal_length",

y="petal_length",

hue="species",

) <AxesSubplot:xlabel='sepal_length', ylabel='petal_length'>

Image by Author

Creating palette

There are many ways to create a palette. We will see the following :

based on a single color using sns.dark_palette and sns.ligth_palette

and based on a list of n colors using sns.blend_palette

based on hsl values using sns.hls_palette

based on husl values using sns.husl_palette

Create a palette from a list of colors

Let’s first create a list of colors :

rgb = [(0.15, 0.25, 0.35), (0.35, 0.55, 0.51), (0.5, 0.95, 0.34)]

We can then create a palette based on these colors using sns.blend_palette :

sns.palplot(sns.blend_palette(rgb))

sns.palplot(sns.blend_palette(rgb, n_colors=10))

Image by Author

Image by Author

Of course, we can use named colors as well :

# create a palette from named colors

sns.palplot(sns.blend_palette(["acid green", "adobe"], n_colors=4, input="xkcd"))

Image by Author

You can use the following syntax to create a blend palette with sns.color_palette :

sns.palplot(sns.color_palette("blend:#31B3F3,#987"))

Image by Author

Create a palette from a single color

Creating a palette from a single color can done in several ways :

color = (0.56, 0.87, 0.34)

We can create a light and dark palette from the rgb values :

sns.palplot(sns.light_palette(color))

sns.palplot(sns.dark_palette(color))

Image by Author

Image by Author

And from a hex code :

sns.palplot(sns.color_palette("light:#124683"))

sns.palplot(sns.color_palette("dark:#124683"))

Image by Author

Create a palette from rgb/hsl/husl values

Many other options are available :

sns.palplot(sns.cubehelix_palette())

sns.palplot(sns.cubehelix_palette(rot=0.2, hue=0.2))

sns.palplot(sns.diverging_palette(0, 189))

sns.palplot(sns.diverging_palette(h_neg=20, h_pos=245))

sns.palplot(sns.diverging_palette(h_neg=20, h_pos=245, l=75))

sns.palplot(sns.hls_palette(h=0.01, s=0.1, l=0.45))

sns.palplot(sns.husl_palette(h=0.1, s=0.5, l=0.45))

Image by Author

Named colors

Instead of using color codes, seaborn allows you to use “named” colors : a named color is simply a string name that maps to a rgb color. You can get a dict of named colors with sns.xkcd_rgb and sns.crayons .

# print(sns.xkcd_rgb)

# print(sns.crayons)

# not shown here to save space

We can then use the sns.crayon_palette and sns.xkcd_palette function to create a palette based on a list of named colors :

p = sns.crayon_palette(["Midnight Blue", "Maroon"])

print(p)

sns.palplot(p)

sns.palplot(sns.xkcd_palette(["acid green", "adobe"])) [(0.10196078431372549, 0.2823529411764706, 0.4627450980392157), (0.7843137254901961, 0.2196078431372549, 0.35294117647058826)]

Image by Author

Bonus : Palette widgets

If you are familiar with jupyter notebooks, seaborn provides simple widgets that wrap seaborn functions, to play around with color palettes :

Gif by author

Gif by author

Gif by author

Wrap up

In this article, we saw :

what is a color palette : basically, a list of colors

how to get the current default palette : with sns.color_palette()

how to define a new default palette : with sns.set_palette(palette="magma")

how to introspect a palette : use print(pal) to get the rgb color list, and sns.palplot(pal) to plot the palette

to get the rgb color list, and to plot the palette that there are many palettes available : used the predefined named palettes, or create your own based on a color with sns.light_palette and sns.dark_palette , based on a color list with sns.blend_palette , or with cubehelix_palette, sns.diverging_palette, sns.hls_palette, sns.husl_palette .

Thanks for reading. Cheers.