Understanding a variable's distribution comes before any modeling, and these functions compare groups in one line.
histplot bins values and counts them. Key options:
bins=orbinwidth=; the default picks a sensible bin count.stat=:"count"(default),"density","probability","percent"or"frequency".hue=splits by group, andmultiple=decides how groups combine:"layer"(overlapping, default),"stack","dodge"or"fill"(proportions).common_norm=Falsenormalizes each group separately, essential when groups have very different sizes.kde=Trueoverlays a smooth density curve.
kdeplot draws a smooth estimate of the density. bw_adjust scales the smoothing: below 1 shows more detail (and noise), above 1 smooths more. A KDE can suggest values that are impossible, such as negative prices; cut=0 stops the curve at the data range, and clip= bounds it.
ecdfplot shows, for each value, the proportion of data at or below it. It needs no bins or bandwidth, so it hides nothing, and comparing groups by reading off medians or percentiles is easy.
With both x and y, histplot and kdeplot show bivariate distributions as heatmaps or contours.
displot(kind="hist" | "kde" | "ecdf") is the figure-level version that adds faceting with col= and row=. For one variable in many groups, the categorical plots (boxplot, violinplot) are often more compact.
Example
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
rng = np.random.default_rng(1)
df = pd.DataFrame({
"latency": np.r_[rng.lognormal(3, 0.4, 900), rng.lognormal(3.6, 0.3, 100)],
"region": ["eu"] * 900 + ["us"] * 100,
})
fig, (a, b, c) = plt.subplots(1, 3, figsize=(12, 3.5), layout="constrained")
sns.histplot(data=df, x="latency", hue="region", stat="density",
common_norm=False, ax=a)
sns.kdeplot(data=df, x="latency", hue="region", common_norm=False,
bw_adjust=0.7, cut=0, ax=b)
sns.ecdfplot(data=df, x="latency", hue="region", ax=c)
print(round(df.groupby("region")["latency"].median(), 1).to_dict())
# {'eu': 19.9, 'us': 35.8}
fig.savefig("latency.png")Remember
- histplot for counts, kdeplot for smooth shape, ecdfplot for exact percentiles
- Use
common_norm=Falsewhen comparing groups of different sizes - Bin count and
bw_adjustchange the story; try a few values
Watch out for
- Reading a KDE's tails as real data, for example density below zero for a strictly positive variable.