I like to make my matplotlib
plots aesthetically pleasing. For each new project, I end up creating a fresh “aesthetic setup” for my plots; this causes inconsistencies across my visualizations and unnecessary overhead.
So, I decided to swallow the bitter pill, and learn about customizing matplotlib
the proper way. Thankfully, there is a neat blog explaining this. The recommendation appears to be overriding a dict-like variable matplotlib.rcParams
.
I will use this space to log my most current rcParams
overrides and some rationale behind the design where needed. I expect this to evolve over time, and I will try my best to log details when making changes.
custom_rcParams = {
# Figure
'figure.dpi': 150,
# Font
'font.family': 'serif',
'font.serif': ['cmr10', 'serif'], # NOTE: pass fontfamily='cmb10' for bold
'font.sans-serif': ['cmss10', 'sans-serif'],
'font.size': 13,
'mathtext.fontset': 'cm',
# Axes aesthetics
'axes.titlesize': 18,
'axes.titlepad': 10,
'axes.titleweight': 'bold',
'axes.labelpad': 7.5,
'axes.labelsize': 14,
'axes.grid': True,
'axes.facecolor': '#f5f5f5',
'axes.formatter.use_mathtext': True,
# Tick formatting
'xtick.labelsize': 13,
'ytick.labelsize': 13,
'xtick.major.pad': 7,
'ytick.major.pad': 7,
# Line styling
'lines.linewidth': 2.,
'lines.markersize': 6.5,
# Grid styling
'grid.linestyle': ':', # Dotted line style
'grid.linewidth': 1.0, # Slightly thinner for dotted lines
'grid.color': 'gray',
'grid.alpha': 0.5,
# Color cycles - using a pleasing palette
'axes.prop_cycle': plt.cycler('color', ['#4878d0', '#6acc64', '#d65f5f',
'#956cb4', '#d8882b', '#e27e8d',
'#7f7f7f', '#f1c27d', '#bcbd22',
'#17becf']),
# Legend
'legend.fontsize': 12,
'legend.frameon': True,
'legend.framealpha': 0.8,
'legend.edgecolor': 'lightgray',
'legend.facecolor': '#ffffff',
# Saving figures
'savefig.bbox': 'tight',
'savefig.dpi': 300,
}
Use the above in code before plotting as:
matplotlib.rcParams.update(custom_rcParams)
The comparison will be tracked using this data:
import numpy as np
np.random.seed(15213)
plt.figure()
num_series = 4
x = np.arange(10)
for i in range(num_series):
# Generate random data with some structure
y = np.random.rand(10)
# Add some pattern to make it look more realistic
y = y * 0.5 + 0.5 * np.sin(x/3.0 + i)
# Ensure values stay in 0-1 range
y = np.clip(y, 0, 1)
plt.plot(y, marker="o", label=f"series {i+1}")
plt.title("Random Data")
plt.xlabel("x-axis")
plt.ylabel("y-axis")
plt.legend()
Results
Default | Customized |
---|---|
![]() |
![]() |