← Matplotlib·Lesson 6·12 min·0/3 exercises

Scatter plots

Do these two columns move together — and how much can you read into that

ax.scatters=c=alphafig.colorbarax.hexbinnp.corrcoef

Watch it happen

Play it through, or step back and forth yourself.

ax.scatter(temp, cups)one point per row
ax.plot(x, y, "o")the same picture, faster
sc.get_offsets()the (n, 2) array of positions

A scatter asks one question: do these two measurements move together? Every point is one row of your data, placed by two of its columns. Nothing is connected, because nothing lies between one order and the next.

The idea

A scatter answers one question: do these two measurements move together? Every point is one row, placed by two of its columns. Nothing is joined up, because nothing lies between one order and the next.

fig, ax = plt.subplots()
sc = ax.scatter(orders["temp"], orders["cups"])
ax.set_xlabel("temperature (°C)")
ax.set_ylabel("cups sold")

The cloud tilts down: hot days sell less chai. You can put a number on that — np.corrcoef(temp, cups)[0, 1] gives −0.768 — but the picture tells you something the number can't, namely whether that slope is one real trend or two separate clumps that happen to line up. A correlation coefficient cannot tell those apart. Always look before you quote it.

Encoding more columns

A flat chart has two positions to spend, but a scatter can carry two more variables in size and colour:

sc = ax.scatter(temp, cups,
                s=wait,          # size  — a third column
                c=wait,          # colour — a fourth
                cmap="viridis",
                alpha=0.6,
                edgecolors="none")
fig.colorbar(sc, ax=ax, label="wait (s)")

Two things to know about s. It's area, in points squared, not diameter — so a value twice as large makes a marker only about 1.4× wider, and readers systematically under-read the difference. And it's per-point, so passing an array of length n is the whole feature.

When c= gets numbers rather than a colour name, matplotlib runs them through a colormap — and then fig.colorbar() is not optional. Without the key the colours mean nothing.

Hand-drawn notes showing a scatter plot carrying four columns at once through position, colour and marker size.

Overplotting

This is the failure mode that matters. Past a few hundred points the middle of the cloud goes solid, and the solid part is exactly the region you wanted to understand. You can't tell fifty points from five thousand.

ax.scatter(x, y, alpha=0.3, s=12, edgecolors="none")

Transparency restores density: dark means many, pale means few. Past roughly ten thousand points even that saturates, and you switch to binning the plane instead:

ax.hexbin(x, y, gridsize=40, cmap="magma")
ax.hist2d(x, y, bins=50)
Hand-drawn notes showing a solid mass of overlapping points becoming readable with transparency, smaller markers, or hexagonal binning.

scatter or plot?

ax.plot(x, y, "o") draws the same picture and is considerably faster, because every marker is identical — one artist, not a collection. Use plot when all the points look the same, and scatter when size or colour varies per point. That's the whole distinction.

The sentence at the end

Chai sales fall as temperature rises. That is association, not cause — the weather also changes who's out walking and when the cold-drink stall opens. The scatter shows you that two columns move together. Everything after that is your argument, and the chart won't back you up on it.

Practice

Write it yourself. The answer is there when you want it.

Putting the kettle on…

Starting up…

Write it yourself

not graded

Scatter temperature against cups for the month, sizing and colouring the points by wait, with some transparency and no edges on them. Attach a labelled colour bar, then label both axes and title it. Print the correlation between temperature and cups, and the shape of the point array. Finish with fig.

Write something and 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.

Scatter temp against cups, then return the shape of sc.get_offsets() as a list — the array of point positions matplotlib is holding.

your answer

Scatter temp against cups, sizing each point by wait and setting alpha=0.5. Return [len(sc.get_sizes()), sc.get_alpha()].

your answer

The scatter shows a downward tilt. Put a number on it: return the correlation between temp and cups, rounded to 3 decimal places.

your answer