A box plot shows the median, quartiles, and whiskers. Outliers are points beyond the whiskers. sns.boxplot is the seaborn version.
Goal
Compare units across cities, then split each city by product.
One grouping
rng = np.random.default_rng(0)
rows = []
for city, loc in [("Nairobi", 12), ("Mombasa", 8), ("Kisumu", 15)]:
rows.append(
pd.DataFrame({"city": city, "units": rng.normal(loc, 3, size=30)})
)
df = pd.concat(rows, ignore_index=True)
sns.boxplot(data=df, x="city", y="units")
plt.title("Units by city")
plt.show()The line in the box is the median, not the mean.
Hue
rng = np.random.default_rng(0)
rows = []
for city in ["Nairobi", "Mombasa", "Kisumu"]:
for product, loc in [("A", 10), ("B", 14)]:
rows.append(
pd.DataFrame(
{
"city": city,
"product": product,
"units": rng.normal(loc, 2.5, size=20),
}
)
)
df = pd.concat(rows, ignore_index=True)
sns.boxplot(data=df, x="city", y="units", hue="product")
plt.title("City × product")
plt.show()Horizontal
rng = np.random.default_rng(1)
df = pd.DataFrame(
{
"city": rng.choice(["Nairobi", "Mombasa", "Kisumu", "Nakuru"], size=80),
"revenue": rng.normal(120, 40, size=80).clip(20),
}
)
sns.boxplot(data=df, x="revenue", y="city")
plt.title("Revenue (horizontal)")
plt.show()Swap x and y when category names are long.
You should see
If you also want the shape of the distribution, use a violin plot.