seaborn is matplotlib with the statistics built in: hand it a DataFrame and column names, and it draws the distribution or comparison you meant — with sensible defaults. This lesson covers the three plots that carry most results sections.
Step 1 — A tidy DataFrame
seaborn wants “tidy” data — one row per observation, one column per variable:
import numpy as np
import pandas as pd
rng = np.random.default_rng(7)
df = pd.DataFrame({
"condition": np.repeat(["control", "treated"], 60),
"response": np.concatenate([
rng.normal(10.0, 1.2, 60),
rng.normal(12.4, 1.5, 60),
]),
})
print(df.groupby("condition")["response"].describe())
Step 2 — Compare distributions
A box plot answers “do the groups differ?”; adding the raw points keeps it honest:
import matplotlib.pyplot as plt
import seaborn as sns
sns.boxplot(data=df, x="condition", y="response", width=0.5)
sns.stripplot(data=df, x="condition", y="response",
color="black", size=3, alpha=0.5)
plt.xlabel("")
plt.ylabel("Response")
The strip of points over the box shows the sample size and any outliers a summary shape would hide — reviewers notice.
Step 3 — Or show the full shape
When the distribution’s shape is the story, overlay histograms:
sns.histplot(data=df, x="response", hue="condition",
element="step", stat="density", common_norm=False)
plt.xlabel("Response")
stat="density" with common_norm=False normalises each group separately, so different group sizes still compare fairly.
Step 4 — Regression with its uncertainty
For two continuous variables, regplot scatters the data and draws the fitted line with a confidence band in one call:
df2 = pd.DataFrame({"dose": np.tile(np.arange(1, 11), 6)})
df2["effect"] = 0.8 * df2["dose"] + rng.normal(0, 1.0, len(df2))
sns.regplot(data=df2, x="dose", y="effect",
scatter_kws={"s": 12, "alpha": 0.6})
plt.xlabel("Dose")
plt.ylabel("Effect")
For the fitted numbers themselves (slope, uncertainty), pair this with the scipy lesson — regplot draws the relationship; curve_fit quotes it.
Step 5 — Export or insert
Export / Insert as usual — vector PDF or into the paper with a \label, the script saved as the figure’s source.
Tip: seaborn styles the whole figure the moment you import it. If a plot must match your matplotlib-only figures, set
sns.set_theme(style="ticks")once at the top — closer to matplotlib’s look, minus the grey.