Styles and rcParams
Decide how your charts look once, in one place
plt.rcParamsplt.style.useplt.style.contextrc_context.mplstyleplt.rcdefaultsWatch it happen
Play it through, or step back and forth yourself.
len(plt.rcParams)about a thousand of themplt.rcParams["lines.linewidth"]2.0 hereplt.rcParams["figure.dpi"]110 hereplt.rcParams["font.size"]10plt.rcParams["axes.prop_cycle"]the paletteEvery 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 11Which 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 stockStyle 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 onWorth 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 hereplt.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 outsideA 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: Falseplt.style.use("chai.mplstyle")
plt.style.use(["seaborn-v0_8-white", "chai.mplstyle"]) # layered, in orderOne 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:
- The style sheet — the project-wide baseline.
- Your rcParams — this notebook is different.
- 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 gradedAlready 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.
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.
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.
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].
