5.4.16 · D4Scientific Computing (Python)

Exercises — 2D plots — line, scatter, bar, histogram, contour, imshow

2,393 words11 min readBack to topic

Levels: L1 RecognitionL2 ApplicationL3 AnalysisL4 SynthesisL5 Mastery.


L1 — Recognition (name the right tool)

Exercise 1.1 — "Which plot?"

For each dataset, name the ONE plot method (plot, scatter, bar, hist, contour, imshow) that best answers the stated question.

  • (a) Daily temperature recorded every hour for one day. Question: "how did it change through the day?"
  • (b) Height and weight of 500 kids. Question: "do taller kids weigh more?"
  • (c) Goals scored by 4 named players. Question: "who scored most?"
  • (d) 10 000 exam scores. Question: "what is the shape of the score distribution?"
  • (e) A grid of pixel brightness values. Question: "show me the picture."
  • (f) sampled on a grid. Question: "where are the ridges and valleys?"
Recall Solution

The key is what each tool assumes about the data (see the decision table in the parent note).

  • (a) plot — x (time) is ordered, points are connected as a series.
  • (b) scatter — independent (x, y) pairs, we ask about correlation.
  • (c) bar — discrete categories (player names).
  • (d) hist — one array of samples, we want the distribution shape.
  • (e) imshow — display the array itself as colored cells.
  • (f) contour — level curves of a scalar field, showing surface shape.

Exercise 1.2 — "Figure vs Axes"

In fig, ax = plt.subplots(), which object is the whole canvas and which is the coordinate system you draw into? On which one do you call .plot(...)?

Recall Solution

fig = the whole canvas (Figure). ax = the coordinate system (Axes). You draw with ax.plot(...) — the plotting methods live on the Axes, never on the Figure.


L2 — Application (compute the plot's internals)

Exercise 2.1 — Bar geometry

You call ax.bar(["A","B","C"], [5,9,3], width=0.6). Matplotlib places category at integer (so A at 0, B at 1, C at 2). For bar B, give the left edge, right edge, and height.

Recall Solution

A bar is a rectangle centred on its category position , spanning to . B sits at , width : height . The gap of between neighbouring bars (right of A at , left of B at ) is what makes categories read as separate.

Exercise 2.2 — Histogram bin width

You histogram data over the range into equal bins. Compute the bin width , and give the interval covered by bin (bins numbered from ).

Recall Solution

Bin covers . For : Note the left edge is included, the right edge excluded — that convention decides which bin a value on the boundary lands in.

Exercise 2.3 — Line resolution

You plot using np.linspace(0, 2π, N). How many straight segments does Matplotlib draw for ? What is the x-spacing between consecutive points?

Recall Solution

linspace(a, b, N) gives points, so there are segments (each joins one point to the next): Spacing between consecutive points: Small is exactly why 200 points look smooth — each segment is too tiny for the eye to see the kink.


L3 — Analysis (why the number comes out that way)

Exercise 3.1 — Density normalization

A histogram uses density=True. Data range , bins, samples with bin counts . Compute the height of bin 1 (the count-60 bin) under density scaling, and verify the total area is 1.

Recall Solution

Bin width . Under density=True the height is (see Probability density functions and normalization): Why divide by ? Area of bar = height . Summing: The total area is 1 — that is what lets you overlay a theoretical PDF on the same axes.

Exercise 3.2 — Why meshgrid, and its shape

You have xs = linspace(-3, 3, 100) and ys = linspace(-3, 3, 80), then X, Y = np.meshgrid(xs, ys). What is the .shape of X? Of Z = np.exp(-(X**2 + Y**2))? Explain in one sentence why contour cannot use the 1D xs, ys directly.

Recall Solution

meshgrid builds a 2D table: rows index , columns index (see NumPy meshgrid and broadcasting). So and Z has the same shape . Why not 1D: a surface needs a value at every pair — a full 2D grid. The 1D arrays only list axis tick positions; they do not say what is at each crossing. meshgrid fills in every crossing.

Exercise 3.3 — Origin flip

An array Z has Z[0, :] = the top row of a math surface where is smallest. You call ax.imshow(Z) with the default origin="upper". Does the smallest- row appear at the top or bottom of the screen? What flag fixes it for a math convention (y increasing upward)?

Recall Solution

With origin="upper" (the default), row 0 is drawn at the top of the screen. So your smallest- row lands at the top — but in math we want smallest at the bottom. Result: the image looks vertically flipped. Fix: origin="lower", which puts row 0 at the bottom, matching y-increases-upward. This is the single most common pixel-coordinate confusion.


L4 — Synthesis (combine tools correctly)

Exercise 4.1 — Histogram + theoretical PDF overlay

You draw samples from a standard normal (mean 0, std 1). You want to overlay the exact Gaussian curve on the histogram. (a) Which hist argument makes the overlay meaningful, and why? (b) Compute the peak value that the curve should reach at .

Recall Solution

(a) Use density=True. Why: without it, bar heights are raw counts (in the thousands) while is a density (area 1). They live on different scales and cannot be overlaid. With density=True both integrate to 1, so they share the y-axis. See Probability density functions and normalization. (b) At : , so Your histogram's tallest bars near 0 should hover around this value — a quick sanity check that normalization worked.

Exercise 4.2 — Contour of a Gaussian bump

For , the contour at level is the set . (a) Show these level sets are circles and give the radius as a function of . (b) What is the radius of the contour?

Recall Solution

(a) Set . Take the natural log of both sides (log undoes exp — that's why we reach for it here, it turns the exponential into the thing in the exponent): This is the equation of a circle centred at the origin with radius Concentric circles = the level curves of a symmetric bump — see the figure. (b) For :

Figure — 2D plots — line, scatter, bar, histogram, contour, imshow

L5 — Mastery (design + debug the whole figure)

Exercise 5.1 — imshow with real coordinates

You display the Gaussian Z (shape , sampled over ) with imshow. You want the axes to read real values, not pixel indices , and a legend mapping color to value. (a) Which two arguments/calls achieve this? (b) With extent=[-3, 3, -3, 3] and 100 columns, what real x-coordinate does the left edge of column 0 map to, and roughly what real x does column 50's centre sit near?

Recall Solution

(a) extent=[xmin, xmax, ymin, ymax] maps array indices to real coordinates; fig.colorbar(...) adds the value↔color legend (colors alone are meaningless without it — see Colormaps and perceptual uniformity (viridis)). (b) extent=[-3,3,-3,3] spreads 100 columns across width . The left edge of the whole image (left edge of column 0) is at . Column centres are evenly spaced; the total span is , so mapping index linearly: For col 50: — essentially the centre , as expected for a bump peaking at the origin.

Exercise 5.2 — Debug the broken script

A student writes:

xs = np.linspace(-3, 3, 100)
ys = np.linspace(-3, 3, 100)
Z = np.exp(-(xs**2 + ys**2))     # <-- line A
plt.contour(xs, ys, Z)           # <-- line B
plt.imshow(Z)                    # <-- line C: image is upside down

Identify the bug on each of lines A, B, C and give the corrected code.

Recall Solution
  • Line A: xs**2 + ys**2 combines two 1D arrays element-wise → a 1D array of length 100, NOT a 2D surface. You need a grid first. Fix:
    X, Y = np.meshgrid(xs, ys)
    Z = np.exp(-(X**2 + Y**2))     # now shape (100, 100)
  • Line B: contour needs the 2D X, Y, Z, not the 1D xs, ys. Fix: plt.contour(X, Y, Z).
  • Line C: default origin="upper" flips a math surface. Fix: plt.imshow(Z, origin="lower", extent=[-3,3,-3,3]).

Because Z here is symmetric under and , the bump itself looks the same flipped — but for any asymmetric field the origin bug is glaring. Always set origin="lower" for maths.

Exercise 5.3 — Choose axes count for a 2×2 dashboard

You want four sub-plots (line, scatter, hist, imshow) in one figure. Write the one line that creates the Figure and a block of Axes, and say how you'd address the top-right Axes.

Recall Solution
fig, axs = plt.subplots(2, 2)

axs is a NumPy array of Axes. Top-right is axs[0, 1] (row 0, column 1). Then e.g. axs[0,1].scatter(...). Using the explicit axs[i,j].method(...) API — never bare plt.plot — is the only reliable way once there are multiple Axes, because plt guesses a hidden "current axes" you may not control. See Matplotlib Figure vs Axes object model.


Recall One-line self-check summary

Points vs segments ::: points draw segments; bins need edges. Density height ::: , chosen so total area . Gaussian contour radius ::: , circles for a symmetric bump. meshgrid shape ::: (len(ys), len(xs)) — rows are y, columns are x. imshow for maths ::: origin="lower" + extent=[...] + colorbar.