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

Styles and rcParams

Decide how your charts look once, in one place

plt.rcParamsplt.style.useplt.style.contextrc_context.mplstyleplt.rcdefaults

Watch it happen

Play it through, or step back and forth yourself.

050100
len(plt.rcParams)about a thousand of them
plt.rcParams["lines.linewidth"]2.0 here
plt.rcParams["figure.dpi"]110 here
plt.rcParams["font.size"]10
plt.rcParams["axes.prop_cycle"]the palette

Every colour, font size, line width and grid setting comes from rcParams — a dict of about a thousand defaults matplotlib consults as it draws. Nothing is hardcoded; you're always overriding something.

The idea

Every colour, font size, line width, tick length and grid setting matplotlib uses comes from rcParams — a dict of roughly a thousand defaults it consults as it draws. Nothing about a chart's appearance is hardcoded; you are always overriding something.

plt.rcParams["lines.linewidth"]     # 2.0 in this lab
plt.rcParams["figure.dpi"]           # 110
plt.rcParams["font.size"]            # 10
plt.rcParams["axes.prop_cycle"]      # the palette from lesson 11

Which means styling belongs in one place, set once, rather than repeated as keyword arguments on every call. plt.rcParams["axes.grid"] = True at the top of a notebook beats ax.grid(True) forty times, and it can't drift out of sync with itself.

plt.rcParams.update({
    "axes.spines.top": False,
    "axes.spines.right": False,
    "axes.titlelocation": "left",
    "legend.frameon": False,
    "figure.figsize": (7, 4),
})

plt.rcdefaults()      # back to matplotlib stock

Style sheets

A style sheet is a named bundle of rcParams. Twenty-six ship with matplotlib:

plt.style.available          # 26 names
plt.style.use("ggplot")       # global — everything from here on

Worth knowing by name: ggplot and seaborn-v0_8-* (grey panel, white grid), fivethirtyeight (bold, thick lines, for slides), grayscale (for print), and tableau-colorblind10 (a safer palette, from lesson 11).

Prefer the scoped form

with plt.style.context("ggplot"):
    fig, ax = plt.subplots()
    ax.plot(days, delhi)
# everything is back to normal here

plt.style.use is global mutable state. Set it in cell 3 and wonder in cell 40 why your colours changed — that's a real afternoon. The context manager scopes it to the block. There's also mpl.rc_context({...}) for individual parameters:

import matplotlib as mpl
with mpl.rc_context({"lines.linewidth": 5}):
    ...     # thick lines in here, 2.0 again outside

A house style

For anything ongoing, write your own .mplstyle file and put it in version control:

# chai.mplstyle
figure.figsize: 7, 4
figure.dpi: 110
axes.prop_cycle: cycler('color', ['ff7d0c', '66aaf9', '74dfa2'])
axes.spines.top: False
axes.spines.right: False
axes.titlelocation: left
axes.grid: True
grid.alpha: 0.25
font.size: 10
legend.frameon: False
plt.style.use("chai.mplstyle")
plt.style.use(["seaborn-v0_8-white", "chai.mplstyle"])   # layered, in order

One file now decides how every chart in the project looks. Changing the brand colour is a one-line diff instead of a search through nine notebooks, and every chart in the report matches without anyone having to remember to make it match.

The order things win in

Three layers, and later beats earlier:

  1. The style sheet — the project-wide baseline.
  2. Your rcParams — this notebook is different.
  3. The keyword argument on the call — this one line is the point.

That's why color= on a single call always wins, and why it should be reserved for the series you're actually talking about. If you find yourself passing the same color= to every call, that belongs one layer up.

Fonts

plt.rcParams["font.family"] = "DejaVu Sans". Two things bite here: a font that exists on your laptop may not exist on the server, and matplotlib falls back silently with only a warning. And PDF or SVG output embeds the font, so a figure that renders correctly for you may not for a reader — which is one more reason to test the actual saved file rather than the on-screen preview.

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.

trywrapping the plotting block in plt.style.context("fivethirtyeight") instead.

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.

How many style sheets ship with matplotlib, ignoring the private ones that start with _? Return the count.

your answer

Read plt.rcParams["axes.facecolor"] inside a ggplot style context and after it, and return the two values as a list — the point being that the context puts things back.

your answer

Using mpl.rc_context, draw one line with lines.linewidth set to 5 and another outside the block at the default. Return [inside_width, outside_width].

your answer