Matplotlib·Lesson 7·12 min·0/3 exercises

Bar charts

Sort them, turn them sideways, and never cut the baseline

ax.barax.barhbottom=ax.bar_labelax.containersnp.argsort

Watch it happen

Play it through, or step back and forth yourself.

ax.bar(items, sold)vertical bars
width=0.8the default — leaves a gap
color="#66aaf9"one colour, unless colour means something
b.get_height()read a bar back

Bars are for comparing amounts across categories — five tea flavours, four regions, twelve months. The eye compares lengths well, which is exactly what a bar chart asks it to do.

The idea

Bars compare amounts across categories — five flavours, four regions, twelve months. The eye compares lengths well, which is exactly the task a bar chart sets it.

fig, ax = plt.subplots()
bars = ax.bar(items, sold)
ax.set_ylabel("cups sold")

ax.bar hands back a BarContainer — a list-like of Rectangle artists you can read and restyle, and the thing ax.bar_label wants. Each call adds one entry to ax.containers.

Sort them

Unless the categories carry their own order — months, sizes, a 1–5 rating — sort by value. The chart exists to show the ranking; leaving it in menu order makes the reader do the sorting themselves.

order = np.argsort(sold)[::-1]              # biggest first
ax.bar([items[i] for i in order], [sold[i] for i in order])

And remember to reorder both — labels and values. Sorting one and not the other is a silent, plausible-looking wrong chart, and nothing will warn you.

Turn it sideways

When the labels are words, use ax.barh. Horizontal bars give each label a full line, so nothing needs rotating to 45° and squinting at.

order = np.argsort(sold)                    # ASCENDING for barh
ax.barh([items[i] for i in order], [sold[i] for i in order])

Note the flip: the y axis counts upwards from the bottom, so ascending order puts the biggest bar on top where the eye starts. Get this backwards and your chart reads upside-down.

Two series

Grouped — side by side, for comparing the pairs. You place them yourself:

x = np.arange(len(days))
ax.bar(x - 0.2, delhi, width=0.4, label="Delhi")
ax.bar(x + 0.2, mumbai, width=0.4, label="Mumbai")
ax.set_xticks(x, days)      # put the words back

Stackedbottom=, for when the total is the point:

ax.bar(days, delhi, label="Delhi")
ax.bar(days, mumbai, bottom=delhi, label="Mumbai")

Stacking shows the total honestly and the bottom segment honestly. Everything above starts at a different height, so comparing those segments across bars is genuinely hard — that's the trade, and it's worth it only when the total is what you're arguing about. Past three segments, stop.

The baseline is not a style choice

A bar encodes its value as a length. Cut the axis and you change the length without changing the number:

ax.set_ylim(280, 320)   # 312 vs 288 now looks like 3x

This is the most common misleading chart there is, and it takes one line to make by accident. Bars start at zero. If the differences are too small to see at zero, that's the finding — say so, or plot the difference itself, or use a line chart, which encodes position rather than length and may be zoomed freely.

Label the bars, delete the furniture

bars = ax.barh(items, sold)
ax.bar_label(bars, padding=3)

ax.set_xticks([])
for side in ("top", "right", "bottom"):
    ax.spines[side].set_visible(False)

Once every bar carries its number, the axis and the gridlines are duplicated effort. Fewer things on the page, more of them actually read.

Not a pie chart

ax.pie() exists. It asks the eye to compare angles and areas, which it does badly, and it can only show parts of one whole. A sorted barh answers the same question and can be read exactly. Two or three slices with very different sizes is about the only case a pie survives.

See it run

The lesson's code, ready to run and to fiddle with.

Putting the kettle on…

Starting up…

Worked example

not graded

Already written and ready to go — press Run to see what it does, then change a number, a column name, anything, and run it again.

tryswapping argsort(sold) for argsort(sold)[::-1] and seeing the chart read upside-down.

Press Run — the output appears here.

Your turn

3 exercises. Write the code yourself, then press Check — a nudge and the answer are there if you want them.

Draw a bar chart of items against sold, then read the bars back: return [round(b.get_height()) for b in bars].

your answer

Sort the menu by sales, biggest first, and return the item names in that order as a list.

your answer

Stack mumbai on top of delhi over days using bottom=, then return len(ax.containers) — one per bar() call.

your answer