A strip plot draws every row as a point. A swarm plot nudges points so they do not overlap. Use them when the table is small enough to show each sale.
Goal
Show every sale as a point, then dodge by product, then try a swarm.
Strip
df = pd.DataFrame(
{
"city": ["Nairobi", "Nairobi", "Mombasa", "Mombasa", "Kisumu", "Kisumu"] * 2,
"product": ["A", "B"] * 6,
"units": [12, 7, 9, 4, 11, 3, 10, 8, 6, 5, 14, 2],
"price": [10.5, 22.0, 10.5, 22.0, 10.5, 22.0] * 2,
}
)
df["revenue"] = df["units"] * df["price"]
sns.stripplot(data=df, x="city", y="revenue", jitter=True)
plt.title("Every row")
plt.show()jitter=True spreads points that would otherwise stack on the same x.
Hue
df = pd.DataFrame(
{
"city": ["Nairobi", "Nairobi", "Mombasa", "Mombasa", "Kisumu", "Kisumu"] * 2,
"product": ["A", "B"] * 6,
"units": [12, 7, 9, 4, 11, 3, 10, 8, 6, 5, 14, 2],
"price": [10.5, 22.0, 10.5, 22.0, 10.5, 22.0] * 2,
}
)
df["revenue"] = df["units"] * df["price"]
sns.stripplot(data=df, x="city", y="revenue", hue="product", dodge=True, jitter=True)
plt.title("Dodge by product")
plt.show()Swarm
rng = np.random.default_rng(0)
df = pd.DataFrame(
{
"city": rng.choice(["Nairobi", "Mombasa", "Kisumu"], size=40),
"units": rng.integers(1, 20, size=40),
}
)
sns.swarmplot(data=df, x="city", y="units")
plt.title("Swarm")
plt.show()Swarm is readable up to a few dozen points per group. Past that, seaborn warns and drops points — switch to a violin or box.
Tip
Overlay a strip on a box: call boxplot first with showfliers=False, then stripplot with color="0.2" and a small size.