Seaborn Categorical Plots

One categorical variable vs one numeric variable (or just categories).

πŸ“Š barplot β€” mean + confidence interval per category

sns.barplot(data=df, x="day", y="total_bill")                    # bar height = mean by default
sns.barplot(data=df, x="day", y="total_bill", hue="sex")            # grouped bars
sns.barplot(data=df, x="day", y="total_bill", estimator="median")      # change aggregation
sns.barplot(data=df, x="day", y="total_bill", errorbar=None)              # no error bars

barplot aggregates (mean by default) β€” it does NOT show raw data counts. For counts, use countplot.

πŸ”’ countplot β€” count of rows per category

sns.countplot(data=df, x="day")
sns.countplot(data=df, x="day", hue="sex")

πŸ“¦ boxplot

sns.boxplot(data=df, x="day", y="total_bill")
sns.boxplot(data=df, x="day", y="total_bill", hue="sex")
sns.boxplot(data=df, y="total_bill")            # single box, no category

Shows median, IQR (box), whiskers, outliers (dots).

🎻 violinplot β€” box plot + KDE shape

sns.violinplot(data=df, x="day", y="total_bill")
sns.violinplot(data=df, x="day", y="total_bill", hue="sex")
sns.violinplot(data=df, x="day", y="total_bill", hue="sex", split=True)   # split violin, one half per hue value

split=True only makes sense with exactly 2 hue categories β€” shows both distributions on one violin instead of two side-by-side.

πŸ”΅ stripplot β€” raw points, jittered

sns.stripplot(data=df, x="day", y="total_bill")
sns.stripplot(data=df, x="day", y="total_bill", hue="sex", dodge=True)
sns.stripplot(data=df, x="day", y="total_bill", jitter=0.2)

🐝 swarmplot β€” raw points, non-overlapping

sns.swarmplot(data=df, x="day", y="total_bill")

swarmplot doesn't scale to large datasets (thousands of points) β€” points get squeezed and rendering slows down. Use stripplot or a violin/box plot instead for big data.

🧩 Combining points on top of a box/violin

sns.boxplot(data=df, x="day", y="total_bill", color="lightgray")
sns.stripplot(data=df, x="day", y="total_bill", color="black", alpha=0.5, jitter=True)

Layering raw points over a summary plot (box/violin) gives both the statistical summary AND the actual data density β€” a very common, genuinely useful combo.

🎯 catplot β€” figure-level wrapper

sns.catplot(data=df, x="day", y="total_bill", kind="box")
sns.catplot(data=df, x="day", y="total_bill", kind="bar", col="sex")     # facet by category
sns.catplot(data=df, x="day", y="total_bill", kind="violin", hue="sex")
kind=Same as
"strip" (default)stripplot
"swarm"swarmplot
"box"boxplot
"violin"violinplot
"bar"barplot
"count"countplot
"point"pointplot

πŸ”— Next

Seaborn Regression Plots Β· Seaborn Statistical Estimation & Data Handling