Lesson 08
Count Plots and Bar Plots
Count rows per category with sns.countplot, compare group means with sns.barplot, and read what the thin error bar on each bar tells you.
Seaborn has two bar charts that look alike but answer different questions. countplot asks how many rows each category has. barplot asks what the typical value is in each category: by default the bar is the mean, and a thin line on top shows how certain that mean is.
Count rows with countplot
countplot needs only a category column. The bar heights are the same numbers value_counts prints. order= fixes the bar order.
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
rng = np.random.default_rng(26)
study = pd.DataFrame({
"track": rng.choice(["Python", "Data", "Web"], 120),
"mode": rng.choice(["online", "classroom"], 120),
"week": rng.integers(1, 7, 120),
})
study["hours"] = (rng.uniform(1, 6, 120) + study["week"] * 0.8).round(1)
study["score"] = (35 + study["hours"] * 4.5 + rng.normal(0, 7, 120)).clip(0, 100).round()
sns.countplot(data=study, x="track", order=["Python", "Data", "Web"])
plt.show()
print(study["track"].value_counts())Output:
track
Web 51
Python 35
Data 34
Name: count, dtype: int64Compare means with barplot
barplot needs a category and a number. Each bar is that group's mean, the same value groupby prints, and the black line is a 95% confidence interval for it. Overlapping lines mean the difference may be down to chance.
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
rng = np.random.default_rng(26)
study = pd.DataFrame({
"track": rng.choice(["Python", "Data", "Web"], 120),
"mode": rng.choice(["online", "classroom"], 120),
"week": rng.integers(1, 7, 120),
})
study["hours"] = (rng.uniform(1, 6, 120) + study["week"] * 0.8).round(1)
study["score"] = (35 + study["hours"] * 4.5 + rng.normal(0, 7, 120)).clip(0, 100).round()
sns.barplot(data=study, x="track", y="score", order=["Python", "Data", "Web"])
plt.show()
print(study.groupby("track")["score"].mean().round(1))Output:
track
Data 67.2
Python 64.2
Web 63.2
Name: score, dtype: float64Change the estimator and the error bar
estimator changes what the bar measures, for example "median" or "sum". errorbar="sd" shows the spread of the rows, and errorbar=None removes the line when you only want the summary.
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
rng = np.random.default_rng(26)
study = pd.DataFrame({
"track": rng.choice(["Python", "Data", "Web"], 120),
"mode": rng.choice(["online", "classroom"], 120),
"week": rng.integers(1, 7, 120),
})
study["hours"] = (rng.uniform(1, 6, 120) + study["week"] * 0.8).round(1)
study["score"] = (35 + study["hours"] * 4.5 + rng.normal(0, 7, 120)).clip(0, 100).round()
fig, axes = plt.subplots(1, 2, figsize=(10, 4))
sns.barplot(data=study, x="track", y="score", estimator="median", errorbar=None, ax=axes[0])
axes[0].set_title("median, no error bar")
sns.barplot(data=study, x="track", y="hours", estimator="sum", errorbar=None, ax=axes[1])
axes[1].set_title("total hours")
plt.show()
print(study.groupby("track")["hours"].sum().round(1))Output:
track
Data 238.4
Python 226.9
Web 321.4
Name: hours, dtype: float64A second grouping with hue
hue splits each bar into side-by-side bars. When colouring by the same column as x, pass it to hue too and turn the legend off; Seaborn 0.13 warns if you give a palette without a hue.
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
rng = np.random.default_rng(26)
study = pd.DataFrame({
"track": rng.choice(["Python", "Data", "Web"], 120),
"mode": rng.choice(["online", "classroom"], 120),
"week": rng.integers(1, 7, 120),
})
study["hours"] = (rng.uniform(1, 6, 120) + study["week"] * 0.8).round(1)
study["score"] = (35 + study["hours"] * 4.5 + rng.normal(0, 7, 120)).clip(0, 100).round()
fig, axes = plt.subplots(1, 2, figsize=(11, 4))
sns.barplot(data=study, x="track", y="score", hue="mode", ax=axes[0])
sns.barplot(data=study, x="track", y="score", hue="track", palette="pastel",
legend=False, ax=axes[1])
plt.show()
print(study.pivot_table(index="track", columns="mode", values="score").round(1))Output:
mode classroom online
track
Data 67.1 67.4
Python 64.9 63.7
Web 64.7 62.1Horizontal and sorted
Swap the columns, a category on y and a number on x, and the bars turn sideways, which fits long labels. Sorting by the value makes the ranking obvious.
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
rng = np.random.default_rng(26)
study = pd.DataFrame({
"track": rng.choice(["Python", "Data", "Web"], 120),
"mode": rng.choice(["online", "classroom"], 120),
"week": rng.integers(1, 7, 120),
})
study["hours"] = (rng.uniform(1, 6, 120) + study["week"] * 0.8).round(1)
study["score"] = (35 + study["hours"] * 4.5 + rng.normal(0, 7, 120)).clip(0, 100).round()
ranking = study.groupby("track")["score"].mean().sort_values(ascending=False)
sns.barplot(data=study, y="track", x="score", order=ranking.index, errorbar=None)
plt.show()
print(list(ranking.index))Output:
['Data', 'Python', 'Web']Key takeaways
-
countplot counts rows per category; barplot summarises a number per category
-
barplot's bar is the mean and its line a 95% confidence interval
-
estimator= changes the summary; errorbar= changes or removes the line
-
Pass hue when you pass palette, and put the category on y for sideways bars
-
Next: Box Plots
-
Previous: KDE and ECDF Plots
Loading playground…
Check your understanding
Count Plots and Bar Plots Quiz
What does countplot show?
1 / 10