From Default Python Line Chart to Journal-Quality Infographics

-

Transform boring default Matplotlib line charts into stunning, customized visualizations

Cover, image by the Creator

Everyone who has used Matplotlib knows how ugly the default charts appear like. On this series of posts, I’ll share some tricks to make your visualizations stand out and reflect your individual style.

We’ll start with an easy line chart, which is widely used. The essential highlight will likely be adding a gradient fill below the plot — a task that’s not entirely straightforward.

So, let’s dive in and walk through all the important thing steps of this transformation!

Let’s make all of the essential imports first.

import pandas as pd
import numpy as np
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from matplotlib import rcParams
from matplotlib.path import Path
from matplotlib.patches import PathPatch

np.random.seed(38)

Now we’d like to generate sample data for our visualization. We are going to create something much like what stock prices appear like.

dates = pd.date_range(start='2024-02-01', periods=100, freq='D')
initial_rate = 75
drift = 0.003
volatility = 0.1
returns = np.random.normal(drift, volatility, len(dates))
rates = initial_rate * np.cumprod(1 + returns)

x, y = dates, rates

Let’s check the way it looks with the default Matplotlib settings.

fix, ax = plt.subplots(figsize=(8, 4))
ax.plot(dates, rates)
ax.xaxis.set_major_locator(mdates.DayLocator(interval=30))
plt.show()
Default plot, image by Creator

Not likely fascination, right? But we are going to steadily make it looking higher.

  • set the title
  • set general chart parameters — size and font
  • placing the Y ticks to the fitting
  • changing the essential line color, style and width
# General parameters
fig, ax = plt.subplots(figsize=(10, 6))
plt.title("Every day visitors", fontsize=18, color="black")
rcParams['font.family'] = 'DejaVu Sans'
rcParams['font.size'] = 14

# Axis Y to the fitting
ax.yaxis.tick_right()
ax.yaxis.set_label_position("right")

# Plotting essential line
ax.plot(dates, rates, color='#268358', linewidth=2)

General params applied, image by Creator

Alright, now it looks a bit cleaner.

Now we’d prefer to add minimalistic grid to the background, remove borders for a cleaner look and take away ticks from the Y axis.

# Grid
ax.grid(color="gray", linestyle=(0, (10, 10)), linewidth=0.5, alpha=0.6)
ax.tick_params(axis="x", colours="black")
ax.tick_params(axis="y", left=False, labelleft=False)

# Borders
ax.spines["top"].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines["bottom"].set_color("black")
ax.spines['left'].set_color('white')
ax.spines['left'].set_linewidth(1)

# Remove ticks from axis Y
ax.tick_params(axis='y', length=0)

Grid added, image by Creator

Now we’re adding a tine esthetic detail — 12 months near the primary tick on the axis X. Also we make the font color of tick labels more pale.

# Add 12 months to the primary date on the axis
def custom_date_formatter(t, pos, dates, x_interval):
date = dates[pos*x_interval]
if pos == 0:
return date.strftime('%d %b '%y')
else:
return date.strftime('%d %b')
ax.xaxis.set_major_formatter(ticker.FuncFormatter((lambda x, pos: custom_date_formatter(x, pos, dates=dates, x_interval=x_interval))))

# Ticks label color
[t.set_color('#808079') for t in ax.yaxis.get_ticklabels()]
[t.set_color('#808079') for t in ax.xaxis.get_ticklabels()]

Yr near first date, image by Creator

And we’re getting closer to the trickiest moment — learn how to create a gradient under the curve. Actually there isn’t any such option in Matplotlib, but we are able to simulate it making a gradient image after which clipping it with the chart.

# Gradient
numeric_x = np.array([i for i in range(len(x))])
numeric_x_patch = np.append(numeric_x, max(numeric_x))
numeric_x_patch = np.append(numeric_x_patch[0], numeric_x_patch)
y_patch = np.append(y, 0)
y_patch = np.append(0, y_patch)

path = Path(np.array([numeric_x_patch, y_patch]).transpose())
patch = PathPatch(path, facecolor='none')
plt.gca().add_patch(patch)

ax.imshow(numeric_x.reshape(len(numeric_x), 1), interpolation="bicubic",
cmap=plt.cm.Greens,
origin='lower',
alpha=0.3,
extent=[min(numeric_x), max(numeric_x), min(y_patch), max(y_patch) * 1.2],
aspect="auto", clip_path=patch, clip_on=True)

Gradient added, image by Creator

Now it looks clean and nice. We just must add several details using any editor (I prefer Google Slides) — title, round border corners and a few numeric indicators.

Final visualization, image by Creator

The total code to breed the visualization is below:

ASK DUKE

What are your thoughts on this topic?
Let us know in the comments below.

0 0 votes
Article Rating
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

Share this article

Recent posts

0
Would love your thoughts, please comment.x
()
x