Quiz: Specialized matplotlib Charts
20 questions. Aim for mastery (18+).
Multiple Choice (10 questions)
1. To display a 2D numpy array as a heatmap, which method do you use?
(a) ax.plot(data)
(b) ax.imshow(data) or ax.pcolormesh(x_edges, y_edges, data)
(c) ax.heatmap(data)
(d) ax.scatter(data)
Answer
**(b)** `ax.imshow(data)` or `ax.pcolormesh(x_edges, y_edges, data)`. matplotlib does not have a built-in `ax.heatmap` method. The standard approach is `ax.imshow` for regular grids (just pass a 2D array) or `ax.pcolormesh` for irregular grids (pass explicit edge coordinates). Both produce heatmap-style output.2. For a heatmap of temperature anomalies (which can be positive or negative from a baseline), the most appropriate colormap type is:
(a) Sequential (e.g., viridis) (b) Diverging (e.g., RdBu_r) (c) Qualitative (e.g., tab10) (d) Rainbow (e.g., jet)
Answer
**(b)** Diverging (e.g., RdBu_r). Diverging colormaps are designed for data with a meaningful midpoint. For anomalies, the midpoint is zero, and values extend in both directions. The neutral color (usually white) aligns with zero, and the two extreme colors represent the extreme positive and negative values. Sequential would hide the bidirectionality. Jet is perceptually broken. Qualitative is for categorical data.3. The difference between ax.contour and ax.contourf is:
(a) contour is for 3D data; contourf is for 2D
(b) contour draws line contours; contourf draws filled regions between contours
(c) They are aliases for the same function
(d) contour is for heatmaps; contourf is for scatter
Answer
**(b)** `contour` draws line contours; `contourf` draws filled regions between contours. `ax.contour(X, Y, Z, levels=N)` draws N contour lines at the specified levels. `ax.contourf(X, Y, Z, levels=N)` fills the regions between contours with colors. Both are used for continuous 2D surfaces; the difference is whether the output is a line drawing or a filled plot.4. To create a polar plot in matplotlib, you pass projection="polar" to:
(a) plt.plot()
(b) fig.add_subplot() or plt.subplots(subplot_kw=...)
(c) ax.plot()
(d) plt.figure()
Answer
**(b)** `fig.add_subplot()` or `plt.subplots(subplot_kw=...)`. `fig.add_subplot(1, 1, 1, projection="polar")` creates an Axes with polar coordinates. Alternatively, `plt.subplots(subplot_kw={"projection": "polar"})` creates a polar-projected figure. The projection is a property of the Axes, not of individual plot methods.5. To make uncertainty visible on a scatter plot, you use:
(a) ax.errorbar(x, y, yerr=errors)
(b) ax.scatter(x, y, error=errors)
(c) ax.plot(x, y, yerr=errors)
(d) You cannot show uncertainty on a scatter
Answer
**(a)** `ax.errorbar(x, y, yerr=errors)`. `ax.errorbar` is the matplotlib method for plotting data with error bars. The `yerr` parameter (or `xerr` for horizontal errors) specifies the error values. It can be a single value, a 1D array, or a 2-element list `[lower, upper]` for asymmetric errors.6. For a line chart with a continuous confidence band around the estimate, which method do you use?
(a) ax.errorbar(x, y, yerr=confidence)
(b) ax.fill_between(x, lower, upper, alpha=0.2) combined with ax.plot(x, y)
(c) ax.plot(x, y, confidence=confidence)
(d) ax.scatter(x, y, s=confidence)
Answer
**(b)** `ax.fill_between(x, lower, upper, alpha=0.2)` combined with `ax.plot(x, y)`. `fill_between` creates a filled region between two y-value arrays, and combined with a central line (`ax.plot`), it produces the "line with shaded confidence band" pattern standard for forecasts and continuous uncertainty. The `alpha=0.2` makes the fill transparent so the central line is still visible.7. For a compass-style polar plot where North is at the top and angles go clockwise, the correct setup is:
(a) ax.set_theta_zero_location("N") and ax.set_theta_direction(-1)
(b) ax.set_theta_zero_location("E") and ax.set_theta_direction(1)
(c) ax.set_rticks([]) and ax.set_yticks([])
(d) ax.invert_xaxis() and ax.invert_yaxis()
Answer
**(a)** `ax.set_theta_zero_location("N")` and `ax.set_theta_direction(-1)`. `set_theta_zero_location("N")` puts zero (the start angle) at the top of the plot. `set_theta_direction(-1)` makes the angles increase clockwise (matching compass and clock conventions). The defaults are East and counterclockwise, which is mathematically natural but not what you want for compass or clock data.8. For a heatmap of diverging data (positive and negative values), you should set vmin and vmax:
(a) To the actual min and max of the data
(b) Symmetrically around zero (e.g., vmin=-abs_max, vmax=abs_max)
(c) Both to zero
(d) To arbitrary values
Answer
**(b)** Symmetrically around zero (e.g., `vmin=-abs_max, vmax=abs_max`). For a diverging colormap to work correctly, the neutral color (usually white) must align with zero in the data. Setting `vmin` and `vmax` symmetrically ensures this alignment. Letting matplotlib autoscale places the neutral color at the data's midpoint, which may not be zero — and the reader reads the wrong value as "neutral."9. ax.fill_between(x, lower, upper, where=(y > 0), color="red") does what?
(a) Fills the entire region between lower and upper in red
(b) Fills only the region where y > 0 between lower and upper
(c) Raises an error because where is not a valid parameter
(d) Fills only where y == 0
Answer
**(b)** Fills only the region where `y > 0` between `lower` and `upper`. The `where` parameter takes a boolean array (or condition) and fills only the regions where the condition is True. This is how you produce warming-stripes-style charts that highlight positive and negative regions in different colors.10. The jet colormap is discouraged because:
(a) It is copyrighted (b) It is perceptually non-uniform, not colorblind-safe, and misleading for sequential data (c) It only works for specific chart types (d) It is too old
Answer
**(b)** It is perceptually non-uniform, not colorblind-safe, and misleading for sequential data. Jet has well-documented perceptual problems: the luminance (brightness) is not monotonic, so equal steps in data do not correspond to equal perceptual changes. It is hard to read for colorblind viewers. And it creates false boundaries that are not in the data. Modern alternatives like viridis, plasma, and cividis were designed specifically to fix these problems. matplotlib 2.0 (Chapter 12 Case Study 2) changed the default from jet to viridis.True / False (5 questions)
11. "Heatmaps and contour plots are the same thing."
Answer
**False.** They are different visualizations for different data shapes. Heatmaps (imshow, pcolormesh) display 2D tabular data as a grid of colored cells — each cell has a discrete value. Contour plots (contour, contourf) display continuous 2D surfaces using level curves, interpolating smoothly between grid points. Use heatmaps for tabular data with discrete cells; use contour plots for smooth continuous functions.12. "Polar plots should be used for any data that looks circular, including year-over-year data wrapped in a loop."
Answer
**False.** Polar plots are for genuinely cyclical data — time of day (which wraps at midnight), day of week (which wraps at Sunday), month of year (which wraps at December), compass direction (which wraps at 360°). Year-over-year data is linear — year 1 and year 10 are not naturally adjacent. Wrapping linear data in a polar plot creates the false impression of continuity and should be avoided.13. "Error bars are optional decoration that can be omitted to make charts look cleaner."
Answer
**False.** Chapter 4 established that hiding uncertainty is a form of visualization dishonesty. Error bars or confidence bands are not optional — they represent the real uncertainty in any measurement or estimate. A chart that shows point estimates without indicating uncertainty implies precision the data does not support. Include error bars or confidence bands whenever the data has meaningful uncertainty (which is almost always).14. "The extend parameter on fig.colorbar adds arrows at the ends of the colorbar to indicate values that are clipped beyond vmin/vmax."
Answer
**True.** `extend="both"`, `extend="min"`, or `extend="max"` adds arrows at the specified ends of the colorbar. This is useful when some data values fall outside the vmin/vmax range and are clipped — the arrows tell the reader that values beyond the displayed range exist.15. "matplotlib has a built-in ax.heatmap() method for creating heatmaps."
Answer
**False.** matplotlib does not have a dedicated `heatmap` method. Heatmaps are produced with `ax.imshow` (for regular grids) or `ax.pcolormesh` (for irregular grids). seaborn has a convenient `sns.heatmap()` wrapper that simplifies the process (including automatic annotation and label positioning) — we will cover seaborn in Part IV.Short Answer (3 questions)
16. In three to four sentences, describe when to use ax.imshow vs. ax.pcolormesh for a heatmap.
Answer
Use `ax.imshow` for regular grids where all cells are the same size. It takes a 2D array and displays it directly as colored cells. It is faster, simpler, and the standard choice for most heatmaps. Use `ax.pcolormesh` when you have an irregular grid (unequal row heights or column widths) and need to specify explicit edge coordinates. `pcolormesh` is more flexible but slightly more verbose. For most data, `imshow` is sufficient.17. Explain what ax.fill_between(x, lower, upper, alpha=0.2, where=(y > 0)) does, parameter by parameter.
Answer
`ax.fill_between(x, lower, upper)` creates a filled region between the `lower` and `upper` arrays at each x-value. `alpha=0.2` makes the fill semi-transparent so elements behind it remain visible. `where=(y > 0)` is a boolean condition that restricts the fill to only the regions where the condition is True — so the filled region appears only where `y > 0`. Combined, this call fills the vertical region between `lower` and `upper` at x-values where `y > 0`, with 20% opacity.18. Describe two specific pitfalls the chapter warns about for polar plots and their fixes.
Answer
**(1) Wrong zero location.** The default is East (0° at the right), which is mathematically natural but wrong for compass and clock data. Fix: `ax.set_theta_zero_location("N")` places zero at the top. **(2) Wrong direction.** The default is counterclockwise (angles increase to the left), which is mathematically natural but wrong for clock-style displays. Fix: `ax.set_theta_direction(-1)` makes angles increase clockwise. Without these adjustments, compass-style polar plots look rotated and flipped.Applied Scenarios (2 questions)
19. You have monthly temperature data for 50 U.S. cities over 10 years (12 × 10 × 50 = 6000 data points). You want to show how temperature patterns vary geographically and across time. Propose a multi-panel layout combining specialized chart types.
Answer
**Layout:** 2 or 3 panels in a figure. **Panel A: a small-multiple heatmap grid.** 50 small heatmaps, one per city, each showing years × months with a diverging colormap (RdBu_r). This lets the reader compare seasonal patterns across cities. Use a 5×10 grid of small heatmaps with shared colorbar. **Panel B: a choropleth map (covered in Chapter 23).** Colors each city's average temperature (e.g., the overall mean for the 10-year period). This shows the geographic pattern. **Panel C: a line chart of national mean over time** with a confidence band showing the year-to-year variation across cities. This gives the aggregate trend. Together, the three panels answer: what are the seasonal patterns for individual cities (A), where are the hot and cold regions (B), and how has the national mean evolved (C). Each specialized chart type serves a specific question that the essentials could not handle alone.20. You are producing a figure for a scientific paper. The figure should show: (a) a correlation matrix of 8 variables, (b) a scatter plot showing the relationship between two specific variables with uncertainty, and (c) a distribution of a key statistic with its confidence interval. Write the matplotlib code skeleton.
Answer
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(14, 5), constrained_layout=True)
gs = fig.add_gridspec(1, 3, width_ratios=[1.2, 1, 1])
# (a) Correlation matrix
ax_a = fig.add_subplot(gs[0, 0])
corr = np.corrcoef(data.T) # data is 8-column
im = ax_a.imshow(corr, cmap="RdBu_r", vmin=-1, vmax=1)
fig.colorbar(im, ax=ax_a, shrink=0.7)
ax_a.set_xticks(range(8))
ax_a.set_xticklabels(variables, rotation=45, ha="right")
ax_a.set_yticks(range(8))
ax_a.set_yticklabels(variables)
ax_a.set_title("(a) Correlation Matrix", loc="left", fontweight="bold")
# (b) Scatter with errorbars
ax_b = fig.add_subplot(gs[0, 1])
ax_b.errorbar(x, y, yerr=y_err, xerr=x_err, fmt="o", color="#1f77b4",
ecolor="gray", capsize=3, markersize=6)
ax_b.set_xlabel("Variable 1")
ax_b.set_ylabel("Variable 2")
ax_b.set_title("(b) Relationship", loc="left", fontweight="bold")
# (c) Distribution with CI
ax_c = fig.add_subplot(gs[0, 2])
ax_c.hist(statistic_samples, bins=30, color="#1f77b4", alpha=0.7, edgecolor="white")
ci_lower, ci_upper = np.percentile(statistic_samples, [2.5, 97.5])
ax_c.axvline(ci_lower, color="gray", linestyle="--", linewidth=1)
ax_c.axvline(ci_upper, color="gray", linestyle="--", linewidth=1)
ax_c.axvline(np.mean(statistic_samples), color="black", linestyle="-", linewidth=1.5)
ax_c.set_xlabel("Statistic value")
ax_c.set_ylabel("Frequency")
ax_c.set_title("(c) Distribution (95% CI)", loc="left", fontweight="bold")
# Declutter
for ax in fig.axes:
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
fig.savefig("figure_2.pdf", dpi=300, bbox_inches="tight")
This combines three specialized chart types — heatmap for the correlation matrix, errorbar for the scatter, histogram with annotated CI for the distribution — in a 1×3 GridSpec layout. Each panel answers a specific aspect of the scientific question, and the consistent styling creates visual unity.
Review against the mastery thresholds. Chapter 15 extends matplotlib into animation and interactivity — the final chapter of Part III.