Matplotlib
Overview
Matplotlib is Python's foundational visualization library for creating static, animated, and interactive plots. This skill provides guidance on using matplotlib effectively, covering both the pyplot interface (MATLAB-style) and the object-oriented API (Figure/Axes), along with best practices for creating publication-quality visualizations.
When to Use This Skill
This skill should be used when:
-
Creating any type of plot or chart (line, scatter, bar, histogram, heatmap, contour, etc.)
-
Generating scientific or statistical visualizations
-
Customizing plot appearance (colors, styles, labels, legends)
-
Creating multi-panel figures with subplots
-
Exporting visualizations to various formats (PNG, PDF, SVG, etc.)
-
Building interactive plots or animations
-
Working with 3D visualizations
-
Integrating plots into Jupyter notebooks or GUI applications
Core Concepts
The Matplotlib Hierarchy
Matplotlib uses a hierarchical structure of objects:
-
Figure - The top-level container for all plot elements
-
Axes - The actual plotting area where data is displayed (one Figure can contain multiple Axes)
-
Artist - Everything visible on the figure (lines, text, ticks, etc.)
-
Axis - The number line objects (x-axis, y-axis) that handle ticks and labels
Two Interfaces
- pyplot Interface (Implicit, MATLAB-style)
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4]) plt.ylabel('some numbers') plt.show()
-
Convenient for quick, simple plots
-
Maintains state automatically
-
Good for interactive work and simple scripts
- Object-Oriented Interface (Explicit)
import matplotlib.pyplot as plt
fig, ax = plt.subplots() ax.plot([1, 2, 3, 4]) ax.set_ylabel('some numbers') plt.show()
-
Recommended for most use cases
-
More explicit control over figure and axes
-
Better for complex figures with multiple subplots
-
Easier to maintain and debug
Common Workflows
- Basic Plot Creation
Single plot workflow:
import matplotlib.pyplot as plt import numpy as np
Create figure and axes (OO interface - RECOMMENDED)
fig, ax = plt.subplots(figsize=(10, 6))
Generate and plot data
x = np.linspace(0, 2*np.pi, 100) ax.plot(x, np.sin(x), label='sin(x)') ax.plot(x, np.cos(x), label='cos(x)')
Customize
ax.set_xlabel('x') ax.set_ylabel('y') ax.set_title('Trigonometric Functions') ax.legend() ax.grid(True, alpha=0.3)
Save and/or display
plt.savefig('plot.png', dpi=300, bbox_inches='tight') plt.show()
- Multiple Subplots
Creating subplot layouts:
Method 1: Regular grid
fig, axes = plt.subplots(2, 2, figsize=(12, 10)) axes[0, 0].plot(x, y1) axes[0, 1].scatter(x, y2) axes[1, 0].bar(categories, values) axes[1, 1].hist(data, bins=30)
Method 2: Mosaic layout (more flexible)
fig, axes = plt.subplot_mosaic([['left', 'right_top'], ['left', 'right_bottom']], figsize=(10, 8)) axes['left'].plot(x, y) axes['right_top'].scatter(x, y) axes['right_bottom'].hist(data)
Method 3: GridSpec (maximum control)
from matplotlib.gridspec import GridSpec fig = plt.figure(figsize=(12, 8)) gs = GridSpec(3, 3, figure=fig) ax1 = fig.add_subplot(gs[0, :]) # Top row, all columns ax2 = fig.add_subplot(gs[1:, 0]) # Bottom two rows, first column ax3 = fig.add_subplot(gs[1:, 1:]) # Bottom two rows, last two columns
- Plot Types and Use Cases
Line plots - Time series, continuous data, trends
ax.plot(x, y, linewidth=2, linestyle='--', marker='o', color='blue')
Scatter plots - Relationships between variables, correlations
ax.scatter(x, y, s=sizes, c=colors, alpha=0.6, cmap='viridis')
Bar charts - Categorical comparisons
ax.bar(categories, values, color='steelblue', edgecolor='black')
For horizontal bars:
ax.barh(categories, values)
Histograms - Distributions
ax.hist(data, bins=30, edgecolor='black', alpha=0.7)
Heatmaps - Matrix data, correlations
im = ax.imshow(matrix, cmap='coolwarm', aspect='auto') plt.colorbar(im, ax=ax)
Contour plots - 3D data on 2D plane
contour = ax.contour(X, Y, Z, levels=10) ax.clabel(contour, inline=True, fontsize=8)
Box plots - Statistical distributions
ax.boxplot([data1, data2, data3], labels=['A', 'B', 'C'])
Violin plots - Distribution densities
ax.violinplot([data1, data2, data3], positions=[1, 2, 3])
For comprehensive plot type examples and variations, refer to references/plot_types.md .
- Styling and Customization
Color specification methods:
-
Named colors: 'red' , 'blue' , 'steelblue'
-
Hex codes: '#FF5733'
-
RGB tuples: (0.1, 0.2, 0.3)
-
Colormaps: cmap='viridis' , cmap='plasma' , cmap='coolwarm'
Using style sheets:
plt.style.use('seaborn-v0_8-darkgrid') # Apply predefined style
Available styles: 'ggplot', 'bmh', 'fivethirtyeight', etc.
print(plt.style.available) # List all available styles
Customizing with rcParams:
plt.rcParams['font.size'] = 12 plt.rcParams['axes.labelsize'] = 14 plt.rcParams['axes.titlesize'] = 16 plt.rcParams['xtick.labelsize'] = 10 plt.rcParams['ytick.labelsize'] = 10 plt.rcParams['legend.fontsize'] = 12 plt.rcParams['figure.titlesize'] = 18
Text and annotations:
ax.text(x, y, 'annotation', fontsize=12, ha='center') ax.annotate('important point', xy=(x, y), xytext=(x+1, y+1), arrowprops=dict(arrowstyle='->', color='red'))
For detailed styling options and colormap guidelines, see references/styling_guide.md .
- Saving Figures
Export to various formats:
High-resolution PNG for presentations/papers
plt.savefig('figure.png', dpi=300, bbox_inches='tight', facecolor='white')
Vector format for publications (scalable)
plt.savefig('figure.pdf', bbox_inches='tight') plt.savefig('figure.svg', bbox_inches='tight')
Transparent background
plt.savefig('figure.png', dpi=300, bbox_inches='tight', transparent=True)
Important parameters:
-
dpi : Resolution (300 for publications, 150 for web, 72 for screen)
-
bbox_inches='tight' : Removes excess whitespace
-
facecolor='white' : Ensures white background (useful for transparent themes)
-
transparent=True : Transparent background
- Working with 3D Plots
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(111, projection='3d')
Surface plot
ax.plot_surface(X, Y, Z, cmap='viridis')
3D scatter
ax.scatter(x, y, z, c=colors, marker='o')
3D line plot
ax.plot(x, y, z, linewidth=2)
Labels
ax.set_xlabel('X Label') ax.set_ylabel('Y Label') ax.set_zlabel('Z Label')
Best Practices
- Interface Selection
-
Use the object-oriented interface (fig, ax = plt.subplots()) for production code
-
Reserve pyplot interface for quick interactive exploration only
-
Always create figures explicitly rather than relying on implicit state
- Figure Size and DPI
-
Set figsize at creation: fig, ax = plt.subplots(figsize=(10, 6))
-
Use appropriate DPI for output medium:
-
Screen/notebook: 72-100 dpi
-
Web: 150 dpi
-
Print/publications: 300 dpi
- Layout Management
-
Use constrained_layout=True or tight_layout() to prevent overlapping elements
-
fig, ax = plt.subplots(constrained_layout=True) is recommended for automatic spacing
- Colormap Selection
-
Sequential (viridis, plasma, inferno): Ordered data with consistent progression
-
Diverging (coolwarm, RdBu): Data with meaningful center point (e.g., zero)
-
Qualitative (tab10, Set3): Categorical/nominal data
-
Avoid rainbow colormaps (jet) - they are not perceptually uniform
- Accessibility
-
Use colorblind-friendly colormaps (viridis, cividis)
-
Add patterns/hatching for bar charts in addition to colors
-
Ensure sufficient contrast between elements
-
Include descriptive labels and legends
- Performance
-
For large datasets, use rasterized=True in plot calls to reduce file size
-
Use appropriate data reduction before plotting (e.g., downsample dense time series)
-
For animations, use blitting for better performance
- Code Organization
Good practice: Clear structure
def create_analysis_plot(data, title): """Create standardized analysis plot.""" fig, ax = plt.subplots(figsize=(10, 6), constrained_layout=True)
# Plot data
ax.plot(data['x'], data['y'], linewidth=2)
# Customize
ax.set_xlabel('X Axis Label', fontsize=12)
ax.set_ylabel('Y Axis Label', fontsize=12)
ax.set_title(title, fontsize=14, fontweight='bold')
ax.grid(True, alpha=0.3)
return fig, ax
Use the function
fig, ax = create_analysis_plot(my_data, 'My Analysis') plt.savefig('analysis.png', dpi=300, bbox_inches='tight')
Quick Reference Scripts
This skill includes helper scripts in the scripts/ directory:
plot_template.py
Template script demonstrating various plot types with best practices. Use this as a starting point for creating new visualizations.
Usage:
python scripts/plot_template.py
style_configurator.py
Interactive utility to configure matplotlib style preferences and generate custom style sheets.
Usage:
python scripts/style_configurator.py
Detailed References
For comprehensive information, consult the reference documents:
-
references/plot_types.md
-
Complete catalog of plot types with code examples and use cases
-
references/styling_guide.md
-
Detailed styling options, colormaps, and customization
-
references/api_reference.md
-
Core classes and methods reference
-
references/common_issues.md
-
Troubleshooting guide for common problems
Integration with Other Tools
Matplotlib integrates well with:
-
NumPy/Pandas - Direct plotting from arrays and DataFrames
-
Seaborn - High-level statistical visualizations built on matplotlib
-
Jupyter - Interactive plotting with %matplotlib inline or %matplotlib widget
-
GUI frameworks - Embedding in Tkinter, Qt, wxPython applications
Common Gotchas
-
Overlapping elements: Use constrained_layout=True or tight_layout()
-
State confusion: Use OO interface to avoid pyplot state machine issues
-
Memory issues with many figures: Close figures explicitly with plt.close(fig)
-
Font warnings: Install fonts or suppress warnings with plt.rcParams['font.sans-serif']
-
DPI confusion: Remember that figsize is in inches, not pixels: pixels = dpi * inches
Additional Resources
-
Official documentation: https://matplotlib.org/
-
Cheatsheets: https://matplotlib.org/cheatsheets/
-
Tutorials: https://matplotlib.org/stable/tutorials/index.html