Python Charts

Python plotting and visualization demystified

Overlaying a Scatter (Swarm) Plot on top of a Box Plot in Seaborn

Overlay a swarm (scatter) plot on a Seaborn box plot to show every point alongside the summary.

A box plot summarizes a distribution, but it hides the raw points behind quartiles and whiskers. A swarm plot restores them, so you see both the summary and every individual value on the same chart.

Quick Example

Create the boxplot and the swarmplot on the same axes, sharing the same x and y.

import matplotlib.pyplot as plt
import seaborn as sns

fig, ax = plt.subplots()
sns.boxplot(data=df, x="method", y="score", color="#d5dbdb", ax=ax)
sns.swarmplot(data=df, x="method", y="score", color="#2a9d8f", size=4, ax=ax)

The box plot draws its summary first, then the swarm lays the points inside it without overlap. Use gray for the boxes so the colored points stay the focus.

Why overlay a swarm

A box plot condenses a distribution to median, quartiles, and outliers. That is useful, but it hides the shape and lets you miss gaps or a very bimodal set of values. A swarm plot places each raw observation as a point, offset so points do not collide. Together they give the clean summary and the full detail in one figure.

sns.boxplot(data=df, x="method", y="score", color="#d5dbdb", ax=ax)
sns.swarmplot(data=df, x="method", y="score", color="#2a9d8f", size=4, ax=ax)

Seaborn box plot overlaid with a swarm plot of individual score points

Align hue groups with dodge

When you add a hue to both plots, the groups must line up. boxplot dodges its groups by default, but swarmplot needs dodge=True so its points shift to the same positions.

sns.boxplot(data=df, x="method", y="score", hue="cohort",
            palette=["#4c78a8", "#e45756"], width=0.5, ax=ax)
sns.swarmplot(data=df, x="method", y="score", hue="cohort",
              palette=["#4c78a8", "#e45756"], dodge=True, size=3, ax=ax)

Seaborn box and swarm plots with hue groups aligned using dodge

Forget dodge=True and the swarm points pile into the middle instead of sitting over their own boxes. Sharing the same palette keeps the boxes and points color-consistent.

Style the overlay

A few options keep the combined chart readable.

sns.boxplot(data=df, x="method", y="score", width=0.6,
            color="#d5dbdb", fliersize=0, ax=ax)
sns.swarmplot(data=df, x="method", y="score", size=4,
              color="#1f77b4", edgecolor="white", linewidth=1.0, ax=ax)
  • sns.boxplot(width=0.5) narrows the boxes so they do not swallow the points.
  • fliersize=0 hides the box's own outlier markers, since the swarm already shows every point.
  • size, edgecolor, and linewidth shape the points; white edges separate overlapping dots.

Styled Seaborn box plot with narrow boxes and white-edged swarm points

Use a stripplot for jitter instead

Swarm points sit exactly on their values, which can push dots wide with some data. stripplot adds random jitter instead, which keeps the points compact when a category has many observations.

sns.boxplot(data=df, x="method", y="score", color="#d5dbdb", ax=ax)
sns.stripplot(data=df, x="method", y="score", jitter=0.3,
              size=4, color="#8e44ad", alpha=0.7, ax=ax)

Seaborn box plot overlaid with a jittered strip plot

Use jitter (0 to 1) to control the spread. The strip plot is a lighter-weight alternative when exact point positions or overlaps do not matter.

Practical Tips

  • Plot the box first and the swarm second so the points draw on top.
  • Use a neutral box color and a distinct point color so the raw data stands out.
  • Set dodge=True on the swarm when you use a hue.
  • Narrow the boxes with width and hide box fliers since the swarm shows all points.
  • Turn to stripplot with jitter when a category has so many points that the swarm gets too wide.

Similar Topics