Matplotlib·Lesson 2·11 min·0/3 exercises

plt versus ax

Why half the examples online look nothing like the other half

plt.plotplt.subplotsplt.gcaax.set_titleax.set_xlabelplt.sca

Watch it happen

Play it through, or step back and forth yourself.

import matplotlib.pyplot as plt

plt.plot(days, cups)
plt.title("Cups sold this week")
plt.xlabel("day")
plt.ylabel("cups")
plt.show()
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.plot(days, cups)
ax.set_title("Cups sold this week")
ax.set_xlabel("day")
ax.set_ylabel("cups")
MonTueWedThuFriSatSun050100Cups sold this weekdaycups

Every matplotlib tutorial mixes two APIs, usually without saying so. Both draw the same chart. Only one of them keeps working when you have more than one.

The idea

Search for any matplotlib recipe and you'll get two kinds of answer back, freely mixed and rarely labelled. One starts plt.plot(...); the other starts fig, ax = plt.subplots(). They aren't different libraries and neither is deprecated — they're two interfaces onto the same objects, and knowing which one you're looking at is the difference between copying an example confidently and copying it and hoping.

The pyplot interface

plt.plot(days, delhi)
plt.title("Cups sold this week")
plt.xlabel("day")

None of those mention a Figure or an Axes, so where do they land? On the current axes — a global that matplotlib maintains for you, creating one on demand if nothing exists yet. You can ask for it directly: plt.gca() ("get current axes"), and plt.gcf() for the figure.

This is inherited from MATLAB, and for one quick chart it reads beautifully. Three lines, no ceremony.

The object interface

fig, ax = plt.subplots()
ax.plot(days, delhi)
ax.set_title("Cups sold this week")
ax.set_xlabel("day")

Here plt.subplots() hands you the two objects and every subsequent line says which one it means. Two extra characters per line, and nothing global anywhere.

Where the difference bites

Add a second subplot and the convenience turns into a trap:

fig, axes = plt.subplots(1, 2)
axes[0].plot(days, delhi)
axes[1].bar(days, mumbai)
plt.title("Delhi")      # lands on the RIGHT plot

No error, no warning — the title just appears on the wrong chart. The reason is that plt.subplots(1, 2) creates both Axes and leaves the last one it made as current. Calling axes[0].plot(...) doesn't change that, because Axes methods don't touch the global. So plt.title obeys a piece of state you never set and probably didn't know existed.

axes[0].set_title("Delhi") cannot go wrong. There's no "current" anything to lose track of. That's the whole argument.

Translating between them

The two APIs also spell the same operation differently, which is why examples don't interchange cleanly. The rule is nearly mechanical — the Axes method has set_ in front:

plt.title(...)     ->  ax.set_title(...)
plt.xlabel(...)    ->  ax.set_xlabel(...)
plt.xlim(...)      ->  ax.set_xlim(...)
plt.xticks(...)    ->  ax.set_xticks(...)
plt.yscale("log")  ->  ax.set_yscale("log")
plt.legend()       ->  ax.legend()          # no set_
plt.plot(...)      ->  ax.plot(...)         # no set_

And every getter exists too: ax.get_title(), ax.get_xlim(). Those are how you check what a chart actually ended up with, which is exactly what the exercises below do.

Which to use

Use plt. for the two lines you type to glance at some data, and fig, ax = plt.subplots() for anything you'll keep. The habit worth building is the second one — it costs nothing and it never surprises you.

One useful middle ground: plt.subplots() is itself a pyplot function. It's normal, and correct, to use pyplot to make the figure and the object API for everything after.

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 plt.title(...) for axes[0].set_title(...) and re-running.

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.

Make a figure with two side-by-side Axes. Return True or False for whether plt.gca() is the second one.

your answer

Rewrite this in the object API, then return the title you set:
plt.plot(days, delhi) / plt.title("Delhi")
Return ax.get_title().

your answer

Two Axes side by side. Draw on axes[0], then call plt.title("Delhi") — and return a list of both titles, [left, right], to show where it actually went.

your answer