Quick Reference · statistical data visualization in Python

seaborn cheat sheet

Seaborn is declarative: you name the roles your columns play — x, y, hue, col — and it handles the drawing, the color mapping, and the statistics for you. Learn one distinction — figure-level functions (that build a whole FacetGrid) vs axes-level functions (that draw on one matplotlib Axes) — and the whole library falls into place.

setup / theme / data relational distributions categorical grids · regression · matrix objects · style · save gotcha most common

Verified 2026-08-26 against Seaborn 0.13.2 (current; in maintenance) · cross-checked across: seaborn.pydata.org · introduction · overview of plotting functions · API reference · objects-interface tutorial · aesthetics & FAQ · KDnuggets · Towards Data Science

The shape of the library — one dispatcher per module, over its axes-level drawers
tidy DataFrame → data= roles: x · y · hue · size · style · col · row RELATIONAL relplot(kind=…) figure-level → FacetGrid axes-level → Axes scatterplot() lineplot() DISTRIBUTIONS displot(kind=…) figure-level → FacetGrid axes-level → Axes histplot() kdeplot() ecdfplot() rugplot() CATEGORICAL catplot(kind=…) figure-level → FacetGrid axes-level → Axes stripplot · swarmplot scatter boxplot · violinplot · boxenplot distribution pointplot · barplot · countplot estimate every figure-level function manages a FacetGrid — add col= / row= for free small-multiple panels outside the 3-module scheme (multiple plot kinds at once): jointplot · pairplot  ·  lmplot / regplot (regression)  ·  heatmap / clustermap (matrix)
01Setup & Themeimport · style · scale
02The Data Modelroles, not coordinates
03Relationalrelplot · numeric vs numeric
04Distributionsdisplot · shape of the data
05Categorical · pointscatplot · category vs number
06Categorical · spreadbox · violin · boxen
07Categorical · estimatesbar · count · point
08Regressionfit a trend line
09Matrix plotsheatmap · clustermap
10Multi-plot gridsjoint · pair · FacetGrid
11Color & palettesthe seaborn superpower
12Objects interfaceimport seaborn.objects as so
13Styling the plotreach the matplotlib layer
14Save & Showget it out of the notebook
15Figure-level vs Axes-levelthe one big idea ★
16Gotchasthe usual traps

Four ideas worth a picture

The taxonomy above shows what exists. These show the four ideas that make seaborn feel effortless once they click: the two function levels, the data shape it wants, how columns become visuals, and the grammar of the objects interface.

figure-level vs axes-level

The same plot, in a different container. This one distinction explains most seaborn surprises.

axes-level sns.histplot(…) one Axes legend inside returns Axes accepts ax= figure-level sns.displot(…) FacetGrid · col= returns FacetGrid ignores ax= kind= turns one into the other

long-form vs wide-form data

Seaborn is happiest with tidy data: one row per observation, one column per variable, referred to by name.

long-form (tidy) day bill sex Sun16.9F Sun10.3M Mon21.0M Mon23.7F x="bill", y="day", hue="sex" columns → roles, by name wide-form (matrix)   A B C r1372 r2518 r3469 r4235 pass the frame; index & columns become the axes both work — but long-form unlocks hue / col / row reshape with df.melt() to go wide → long

one column → many visual channels

The declarative core: assign a variable to a channel and seaborn does the encoding — color, size, shape, or a whole panel.

a column "species" hue= color size= area style= marker col= / row= panels you pick the channel; seaborn builds the legend

the objects grammar

The so interface builds a plot as layers. Each layer is a Mark, plus an optional Stat and Move — composed, not configured.

so.Plot(df, x, y) .add( Bar() Mark Agg() Stat Dodge() Move .add( so.Text() ) ← another layer .scale().label().save()

Worth memorizing

fig-level vs axes-levelown FacetGrid vs draws on one Axes
relplot·displot·catplotthe 3 figure-level dispatchers, one per module
kind=picks the axes-level drawer: displot(kind="kde")kdeplot()
hue / size / stylesemantic channels · col/row = facet panels
data=tidy long-form DataFrame; name columns as strings
set_theme()call once — it edits global matplotlib rcParams
palette needs hueno hue= → nothing to color
height & aspectsize figure-level plots, not figsize
fill=Trueshade a KDE (the old shade= was removed)
import …objects as sogrammar-of-graphics: Plot + add(Mark, Stat, Move)