The world’s leading publication for data science, AI, and ML professionals.

3 Key Tweaks That Will Make Your Matplotlib Charts Publication Ready

Matplotlib charts are an eyesore by default – here's what to do about it.

Article thumbnail (image by author)
Article thumbnail (image by author)

Data visualization offers much deeper insights than looking at raw, numerical data.

However, creating appealing Charts takes time and effort. Matplotlib is a de facto standard library for data visualization in Python. It’s simple, has been used for decades, and anything you’re looking for is one web search away.

But it’s not all sunshine and rainbows. Matplotlib visualizations look horrendous by default, and you as a data professional will have to turn many cogs to get something usable. Getting you there is the goal of today’s article.

By the end, you’ll have a code snippet you can stick to any Jupyter Notebook.

What’s Wrong with Matplotlib’s Default Styles?

You won’t need to download any dataset to follow along. You’ll create a synthetic time series dataset with increasing trend and repeatable seasonal patterns:

import numpy as np
import pandas as pd
import Matplotlib.pyplot as plt

# Single season multiplier factors - for seasonality effect
seasonal_multipliers = [1.1, 1.3, 1.2, 1.5, 1.9, 2.3, 2.1, 2.8, 2.0, 1.7, 1.5, 1.2]
# Immitate 10 years of data
xs = np.arange(1, 121)

time_series = []
# Split to 10 chunks - 1 year each
for chunk in np.split(xs, 10):
    for i, val in enumerate(chunk):
        # Multiply value with seasonal scalar
        time_series.append(float(val * seasonal_multipliers[i]))

x = pd.date_range(start="2015-01-01", freq="MS", periods=120)
y = time_series      

print(x[-10:])
print(y[-10:])
Image 1 - Time series data (image by author)
Image 1 – Time series data (image by author)

Since the dataset has dates for an index, and float values for the only attribute, you can plot the entire thing directly via plt.plot():

Python">plt.figure(figsize=(9, 6))
plt.plot(x, y)
plt.show()
Image 2 - Default matplotlib chart (image by author)
Image 2 – Default matplotlib chart (image by author)

Everything about it screams 2002. Low resolution. The surrounding box. The font size.

Nothing a couple of tweaks can’t fix.

Tweak #1 – Adjust rcParams to Set the Overall Theme

Tweaking every chart by hand is a sure way to waste your time.

After all, most charts you make will have an underlying theme. It makes sense to declare it once and reuse it everywhere. That’s the role of rcParams.

The following code snippet changes a whole bunch of them and ensure your charts are rendered as SVGs. This last bit won’t matter if you explicitly save your charts to disk, but it will make a huge difference in a notebook environment:

import matplotlib_inline
matplotlib_inline.backend_inline.set_matplotlib_formats("svg")

plt.rcParams.update({
    "figure.figsize": (9, 6),
    "axes.spines.top": False,
    "axes.spines.right": False,
    "font.size": 14,
    "figure.titlesize": "xx-large",
    "xtick.labelsize": "medium",
    "ytick.labelsize": "medium",
    "axes.axisbelow": True
})

And now, when you repeat the call to plt.plot(), the chart will look somewhat presentable:

plt.plot(x, y)
plt.title("Sales Over Time")
plt.xlabel("Time Period")
plt.ylabel("Sales in 000")
plt.show()
Image 3 - Adjusting chart theme (image by author)
Image 3 – Adjusting chart theme (image by author)

Not quite there yet, but the idea was just to set an underlying theme. You shouldn’t include chart-specific instructions in rcParams.

Tweak #2 – Bring the Font to the 21st Century

Another thing you can change in rcParams is the font.

You can download any TTF font from the internet, and load it via Matplotlib’s font_manager. I’ll use Roboto Condensed, but feel free to go with anything you like:

import matplotlib.font_manager as font_manager

font_dir = ["/path/to/Roboto_Condensed"]
for font in font_manager.findSystemFonts(font_dir):
    font_manager.fontManager.addfont(font)

plt.rcParams.update({
    "font.family": "Roboto Condensed"
})

To verify the font has changed, simply rerun the plotting snippet from earlier:

plt.plot(x, y)
plt.title("Sales Over Time")
plt.xlabel("Time Period")
plt.ylabel("Sales in 000")
plt.show()
Image 4 - Changing the font (image by author)
Image 4 – Changing the font (image by author)

And that’s about all we’ll discuss regarding overall theme changes. Up next, let’s get specific.

Tweak #3 – Make Micro Adjustment Specific to Your Chart Type

Different chart types will have different go-to approaches when it comes to fine-tuning.

For line charts, you can change the line color and width, and potentially even add a filled area section to make the chart look more dashboardy.

The other changes made in the below snippet are purely cosmetic – title location and y-axis limit:

# 1. Line color and width
plt.plot(x, y, color="#1C3041", linewidth=2)
# 2. Add shaded area below the line
plt.fill_between(x, y, color="#1C3041", alpha=0.3)
# 3. Change title location and font weight
plt.title("Sales Over Time", loc="left", fontdict={"weight": "bold"}, y=1.06)

plt.xlabel("Time Period")
plt.ylabel("Sales in 000")
plt.show()
Image 5 - Finalized chart (image by author)
Image 5 – Finalized chart (image by author)

Now this is almost a publication-ready visualization!

A couple of specific made all the difference, but that wouldn’t be possible without setting a strong foundation.

Wrapping Up

Many data professionals disregard Matplotlib entirely because of how it looks by default.

They think "It’s blurry and awful, I can’t send a visual like this to my boss." The reality couldn’t be further away from the truth. You can change a bunch of parameters and end up with a code block you can bring anywhere – to every script, notebook, and environment.

I encourage you to play around with the parameters to further personalize the overall look and feel, and share your preferences in the comment section below.


Looking to level-up your data visualization game? Join thousands of like-minded people on my Substack for expert tips and exclusive content.

Data Doodles with Python | Dario Radecic | Substack

Originally published at https://darioradecic.substack.com.


Related Articles