Skip to main content
MahiDev — Learn. Build. Become AI-ready.

Lesson 16

Histograms

Count how many values fall into each range with plt.hist, and learn why a histogram is a different chart from a bar chart.

Intermediate25 min
Histograms hero Module 25 Lesson 16Histograms hero Module 25 Lesson 16

A histogram answers a question no other chart here answers: how is one measurement spread out? It chops the range of the values into intervals called bins and draws a bar showing how many values landed in each. You hand it the raw values, not counts; the counting is the chart's job.

A histogram of delivery times peaking in the middle binsA histogram of delivery times peaking in the middle bins

Raw values in, counts out

plt.hist(values) takes the measurements themselves. It works out the range, splits it into ten bins by default, counts, and draws. It also returns the counts and the bin edges, which is handy for checking what it decided.

python
import matplotlib.pyplot as plt

minutes = [
    22, 24, 25, 27, 28, 28, 29, 30, 31, 31, 32, 33, 33, 34, 34, 35,
    35, 36, 36, 37, 38, 38, 39, 40, 41, 42, 44, 46, 48, 52,
]

counts, edges, _ = plt.hist(minutes, bins=6, edgecolor="#0F172A")
plt.title("How long deliveries take")
plt.xlabel("minutes")
plt.ylabel("deliveries")
plt.show()

print("counts:", [int(count) for count in counts])
print("edges:", [round(edge, 1) for edge in edges])
print("total counted:", int(sum(counts)), "of", len(minutes))

Output:

text
counts: [3, 7, 9, 6, 3, 2]
edges: [22.0, 27.0, 32.0, 37.0, 42.0, 47.0, 52.0]
total counted: 30 of 30

Not a bar chart

The two look similar and mean different things. A bar chart compares categories you chose, and its bars have gaps because the categories are separate. A histogram counts a continuous measurement, and its bars touch because the ranges are next to each other. The giveaway is the x axis: numbers, not names.

python
import matplotlib.pyplot as plt

ages = [3, 5, 5, 6, 8, 9, 9, 10, 11, 12, 12, 13, 14, 16, 18, 19, 21, 24]
species = ["cats", "dogs", "birds"]
counted = [12, 9, 5]

plt.hist(ages, bins=5, edgecolor="#0F172A", color="#2DD4BF")
plt.title("Histogram: ages, a measurement")
plt.xlabel("age in years")
plt.ylabel("animals")
plt.show()

plt.bar(species, counted, color="#7C3AED")
plt.title("Bar chart: species, a category")
plt.ylabel("animals")
plt.show()

print("histogram x axis holds numbers; bar chart x axis holds names")

Output:

text
histogram x axis holds numbers; bar chart x axis holds names

What the shape tells you

The outline is the point. A single hump in the middle means most values cluster around one typical value. A long tail on one side means a few unusually large values are dragging the average away from the typical case. Two humps often mean two different groups have been mixed together.

python
import matplotlib.pyplot as plt

salaries = [
    28, 29, 30, 31, 31, 32, 32, 33, 34, 34, 35, 36, 37, 38,
    41, 44, 48, 55, 68, 95,
]

plt.hist(salaries, bins=8, edgecolor="#0F172A", color="#F59E0B")
plt.title("A long tail to the right")
plt.xlabel("thousands per year")
plt.ylabel("people")
plt.show()

middle = sorted(salaries)[len(salaries) // 2]
average = sum(salaries) / len(salaries)
print("typical (middle) value:", middle)
print("average:", round(average, 1))
print("the tail pulls the average above the typical case")

Output:

text
typical (middle) value: 35
average: 40.5
the tail pulls the average above the typical case
A histogram with a tall left cluster and a long right tailA histogram with a tall left cluster and a long right tail

Two distributions together

Two hist calls overlay, which only works if you can see through the top one, so pass alpha. Give both the same bins or the comparison is meaningless, because the bars would be counting different ranges.

python
import matplotlib.pyplot as plt

edges = [20, 26, 32, 38, 44, 50, 56]
morning = [22, 25, 27, 28, 30, 31, 33, 34, 35, 36, 38, 41, 44, 48]
evening = [26, 29, 31, 33, 34, 36, 37, 39, 40, 42, 43, 45, 49, 53]

plt.hist(morning, bins=edges, alpha=0.6, label="morning", color="#7C3AED")
plt.hist(evening, bins=edges, alpha=0.6, label="evening", color="#F59E0B")
plt.title("Evening deliveries take longer")
plt.xlabel("minutes")
plt.ylabel("deliveries")
plt.legend()
plt.show()

print("morning average:", round(sum(morning) / len(morning), 1))
print("evening average:", round(sum(evening) / len(evening), 1))

Output:

text
morning average: 33.7
evening average: 38.4

Key takeaways

  • hist takes the raw values and counts them into bins for you

  • Histogram bars touch; bar chart bars have gaps

  • The x axis of a histogram holds numbers, not category names

  • Read the shape: one hump, a long tail, or two groups mixed

  • Next: Choosing Histogram Bins

  • Previous: Colour Maps and Dot Sizes

Loading playground…

Check your understanding

Histograms Quiz

What does a histogram show?

1 / 10