Seaborn is a powerful library that we can use to explore data. Once we have figured out what we want to show, it is time to adapt the plots to our requirements. In this post we explore the options we have for styling our plots.
This post is part of my journey to learn Python. You can find the other parts of this series here. You find the code for this post in my PythonFriday repository on GitHub.
Change the colours
One of the most important changes I like to make is to select a different colour for the plots. Seaborn offers us colour palettes that have predefined colours for our graphs. Unfortunately, I could not find a page that offers a nice list of all pre-defined palettes.
The best thing I found is the post Seaborn Color Palettes and How to Use Them , which offers much more details than Choosing color palettes in the official documentation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import seaborn as sns sns.color_palette() ... sns.color_palette("pastel") ... sns.color_palette("coolwarm") ... sns.color_palette("mako", as_cmap=True) ... sns.color_palette("mako_r", as_cmap=True) |
This gives us a small sample of the colours:
The parameter as_cmap=True in combination with the sequential colormaps “rocket“, “mako“, “flare“, and “crest” gives us a good colour range for numerical values. If we add a “_r” at the end of the name, we get the colour range reversed.
We can use a palette in our graphs with the palette parameter:
1 2 |
penguins = sns.load_dataset("penguins") sns.pairplot(penguins, hue='species', palette='pastel') |
If we want to know what colours are in a palette, we can get their hex codes with this command:
1 |
print(sns.color_palette("pastel").as_hex()) |
[‘#a1c9f4’, ‘#ffb482’, ‘#8de5a1’, ‘#ff9f9b’, ‘#d0bbff’, ‘#debb9b’, ‘#fab0e4’, ‘#cfcfcf’, ‘#fffea3’, ‘#b9f2f0’]
Custom palettes
If we want to use a custom set of colours, we can create our own palette by defining the values we want:
1 2 |
custom = ["#ffaf3c", "#3c5587", "#adb7c4"] sns.pairplot(penguins, hue='species', palette=custom) |
We then can use it with like the pre-defined palettes, but be aware that we need to assign the variable and not a predefined string (so no ” around the name):
Add a title
We can add a title to our graphs with the set() method that we can apply on graphs and legends:
1 2 3 4 5 6 7 8 9 |
g = sns.relplot( data=penguins, x="bill_length_mm", y="bill_depth_mm", hue="body_mass_g", palette="crest" ) g.set(title="Measured Penguins") g.legend.set(title="body mass (g)") |
This allows us to specify one title for the graph as a whole and a specific title for the legend:
If we do not want to see the legend, we can set legend to False:
1 2 3 4 5 6 7 8 |
g = sns.relplot( data=penguins, x="bill_length_mm", y="bill_depth_mm", hue="body_mass_g", palette="crest", legend=False ) |
The gives us a graph without a legend:
Themes
Themes offer a collection of settings that we can apply in one go. We can choose between these themes:
- white (with an empty/white background)
- dark (with a dark background)
- ticks (the white template but with ticks for the values)
- whitegrid (the white template with grid lines)
- darkgrid (the dark template with grid lines)[default]
Important: When we set a template, it will change the settings of all Seaborn and Matplotlib plots.
We can use the template with the set_theme() method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
names = ["A", "B", "C"] values = [1, 3, 2] sns.set_theme() sns.barplot(x=names, y=values).set(title='default theme') ... sns.set_style("darkgrid") sns.barplot(x=names, y=values).set(title='darkgrid') ... sns.set_theme(style="whitegrid") sns.barplot(x=names, y=values).set(title='whitegrid') ... sns.set_theme(style="dark") sns.barplot(x=names, y=values).set(title='dark') ... sns.set_theme(style="white") sns.barplot(x=names, y=values).set(title='white') ... sns.set_theme(style="ticks") sns.barplot(x=names, y=values).set(title='ticks') |
This gives us the same data in plots using different themes:
Set a context
Seaborn offers us another way to change the appearance of our plots. We can choose between one of the 4 pre-defined contexts:
- notebook with optimisations to work on a computer / Jupyter Notebook (the default in Jupyter).
- paper has smaller fonts and a slightly thinner line than notebook.
- talk is for presentations with bigger fonts and stronger lines.
- poster is optimised to show the most important parts from further away.
If we want to change all plots, we can use the method set_context(). In contrast to templates, we can change the context for only one plot and use the method plotting_context() in a with block:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
x = [1, 2, 3, 4] y = [0, 6, 1, 2] sns.set_context("notebook") sns.lineplot(x=x, y=y).set(title="notebook") ... with sns.plotting_context("notebook"): sns.lineplot(x=x, y=y).set(title="notebook") ... with sns.plotting_context("paper"): sns.lineplot(x=x, y=y).set(title="paper") ... with sns.plotting_context("talk"): sns.lineplot(x=x, y=y).set(title="talk") ... with sns.plotting_context("poster"): sns.lineplot(x=x, y=y).set(title="poster") |
This gives us the same graph in 4 different contexts:
If we like a style but want to make a small adjustment, we can use the plotting_context() method to get the settings for the current style:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
sns.plotting_context() {'font.size': 12.0, 'axes.labelsize': 12.0, 'axes.titlesize': 12.0, 'xtick.labelsize': 11.0, 'ytick.labelsize': 11.0, 'legend.fontsize': 11.0, 'legend.title_fontsize': 12.0, 'axes.linewidth': 1.25, 'grid.linewidth': 1.0, 'lines.linewidth': 1.5, 'lines.markersize': 6.0, 'patch.linewidth': 1.0, 'xtick.major.width': 1.25, 'ytick.major.width': 1.25, 'xtick.minor.width': 1.0, 'ytick.minor.width': 1.0, 'xtick.major.size': 6.0, 'ytick.major.size': 6.0, 'xtick.minor.size': 4.0, 'ytick.minor.size': 4.0} |
We then can use the parameter rc with a dictionary of the values we want to change or use the font_scale parameter to change the font size:
1 2 3 4 |
with sns.plotting_context("notebook", font_scale=2, rc={"lines.linewidth": 3.5}): sns.lineplot(x=x, y=y).set(title="custom values") |
This gives us a slightly modified notebook context:
Next
This post only shows you a few of the many ways you can influence how Seaborn creates its graphs. I suggest you try these ones first and then dig deeper into the styling options of Seaborn.
Next week we explore a few advanced tips and tricks for JupyterLab that can help you should you get stuck.