seaborn Themes and Palettes
In one line:
sns.set_theme()once at the top of a script styles every plot — including your raw matplotlib ones.
set_theme
sns.set_theme(
style="whitegrid", # darkgrid | whitegrid | dark | white | ticks
context="paper", # paper | notebook | talk | poster
palette="colorblind",
font="Arial",
font_scale=1.0,
rc={"figure.figsize": (5, 3.5), "pdf.fonttype": 42},
)
This writes into matplotlib's rcParams, so it affects everything, not just seaborn calls. See rcParams and Style Sheets.
Styles
| style | Look |
|---|---|
darkgrid |
grey background, white grid (seaborn's default) |
whitegrid |
white background, grey grid |
dark |
grey background, no grid |
white |
white background, no grid |
ticks |
white, no grid, tick marks — closest to journal convention |
For publication, ticks or whitegrid with sns.despine():
sns.set_theme(style="ticks")
sns.despine() # remove top and right spines
sns.despine(trim=True, offset=5) # trim to data range, detach
sns.despine(fig=fig, left=True) # whole figure
offset=5 detaching the axes from the plot area is a small touch that reads as deliberate design.
Context
sns.set_context("paper") # smallest — journal figures
sns.set_context("notebook") # default
sns.set_context("talk") # slides
sns.set_context("poster") # largest
sns.set_context("talk", font_scale=1.2, rc={"lines.linewidth": 2.5})
Context scales all font sizes, line widths and marker sizes together. Converting a paper figure to a talk figure is one changed word, not fifteen changed numbers.
Palettes
sns.color_palette() # current default
sns.color_palette("colorblind", 8)
sns.color_palette("deep") # seaborn's default
sns.color_palette("muted"); sns.color_palette("pastel")
sns.color_palette("Set2", 6) # ColorBrewer qualitative
sns.color_palette("husl", 8) # evenly spaced hues
sns.color_palette("rocket", as_cmap=True) # sequential
sns.color_palette("mako", as_cmap=True)
sns.cubehelix_palette(8, start=.5, rot=-.75) # greyscale-safe sequential
sns.diverging_palette(240, 10, as_cmap=True) # custom diverging
sns.light_palette("seagreen", as_cmap=True)
sns.dark_palette("#69d", reverse=True)
sns.set_palette("colorblind") # set globally
sns.color_palette("colorblind") # display in a notebook
rocket, mako, flare, crest, vlag, icefire are seaborn's own perceptually uniform maps and are all good defaults. vlag is the diverging one you want for correlation and z-score heatmaps.
Explicit category colours
The habit that makes a multi-panel figure coherent:
CONDITION_COLORS = {
"control": "#4C72B0",
"treated": "#DD8452",
"drug": "#55A868",
}
sns.scatterplot(data=df, x="a", y="b", hue="condition", palette=CONDITION_COLORS)
sns.boxplot(data=long, x="condition", y="expr", palette=CONDITION_COLORS)
sns.lineplot(data=ts, x="t", y="v", hue="condition", palette=CONDITION_COLORS)
Without an explicit mapping, seaborn assigns colours in the order categories appear in each subset — so "treated" can be blue in panel A and orange in panel B if panel B happens to lack the control group. Define the dict once. See Colormaps and Color.
Category order
sns.boxplot(data=long, x="condition", y="expr",
order=["control", "low", "high"],
hue_order=["male", "female"])
Or better, set it once with an ordered categorical, which fixes plot order and sort order and groupby order simultaneously:
long["condition"] = pd.Categorical(
long["condition"], categories=["control", "low", "high"], ordered=True
)
See Categorical dtype.
hue with continuous data
sns.scatterplot(data=df, x="a", y="b", hue="expression",
palette="viridis", hue_norm=(0, 10))
seaborn produces a legend of sample values rather than a colorbar. For a proper colorbar, add one manually:
fig, ax = plt.subplots()
sc = ax.scatter(df["a"], df["b"], c=df["expression"], cmap="viridis", s=10)
fig.colorbar(sc, ax=ax, label="log$_2$ CPM")
Raw matplotlib is the better tool for continuous colour encoding.
Temporary changes
with sns.axes_style("white"):
fig, ax = plt.subplots()
...
with sns.plotting_context("talk"):
...
with sns.color_palette("Set2"):
...
Use these in library code rather than calling set_theme() globally — you should not silently restyle your users' plots.
Inspecting and resetting
sns.axes_style() # current style dict
sns.plotting_context() # current context dict
sns.reset_defaults() # back to matplotlib defaults
sns.reset_orig() # back to matplotlib's original rcParams
A project header
import matplotlib as mpl, matplotlib.pyplot as plt, seaborn as sns
sns.set_theme(style="ticks", context="paper", palette="colorblind",
font="Arial", rc={"figure.figsize": (3.5, 2.6)})
mpl.rcParams.update({
"pdf.fonttype": 42, "ps.fonttype": 42, "svg.fonttype": "none",
"savefig.bbox": "tight", "savefig.dpi": 300,
"axes.titlelocation": "left",
"font.sans-serif": ["Arial", "Helvetica", "DejaVu Sans"],
})
CONDITION_COLORS = {"control": "#4C72B0", "treated": "#DD8452"}
CHROM_ORDER = [f"chr{i}" for i in range(1, 23)] + ["chrX", "chrY", "chrM"]
Put this in a plotstyle.py and import it everywhere in the project. Every figure then matches, and switching the whole paper to a different palette is a one-line change.
Bioinformatics conventions
# expression heatmap: z-scored, diverging, centred
sns.clustermap(mat, z_score=0, cmap="vlag", center=0)
# raw counts heatmap: sequential
sns.heatmap(cpm, cmap="rocket", norm=LogNorm())
# correlation: diverging, symmetric range
sns.heatmap(corr, cmap="vlag", center=0, vmin=-1, vmax=1, square=True)
# categorical sample groups
sns.set_palette("colorblind")
# nucleotides
BASE_COLORS = {"A": "#3DA853", "C": "#4285F4", "G": "#F9AB00", "T": "#EA4335"}
# significance: grey bulk, one accent
sns.scatterplot(data=de, x="log2fc", y="neglog10p", hue="sig",
palette={True: "crimson", False: "lightgrey"},
hue_order=[False, True])
hue_order=[False, True] in the last example matters: it draws the grey non-significant points first, so the crimson hits land on top rather than being buried.
Common mistakes
sns.set()— deprecated alias forset_theme().- Inconsistent category colours across panels.
- Not setting
context="paper"for journal figures, so the fonts are notebook-sized. darkgridin a publication. Grey backgrounds waste ink and reproduce badly.- Global
set_theme()in a library. - Continuous
hueproducing a sample legend instead of a colorbar. - Assuming Arial is installed. Provide fallbacks.
- Forgetting
sns.despine()after choosingstyle="ticks".
See also
Colormaps and Color · rcParams and Style Sheets · Seaborn · Categorical dtype · Saving Figures · Faceting