When to Use
Use this skill when:
- Creating any type of plot or chart (line, scatter, bar, histogram, heatmap, contour, box, violin, 3D surface, etc.)
- Generating scientific or statistical visualizations
- Customizing plot appearance (colors, styles, labels, legends, annotations)
- Creating multi-panel figures with subplots, mosaic layouts, or GridSpec
- Exporting visualizations to PNG, PDF, SVG, or other formats
- Building interactive plots or animations
- Working with 3D visualizations
- Integrating plots into Jupyter notebooks or GUI applications
Trigger keywords: plot, chart, figure, axes, subplot, matplotlib, pyplot, visualization, heatmap, contour, histogram, scatter, bar chart, savefig, rcParams, colormap.
Prerequisites
- Python 3.8+ installed and available on
PATH
- Matplotlib installed:
pip install matplotlib (NumPy is a required dependency and installs automatically)
- For Jupyter integration:
pip install jupyter and run %matplotlib inline or %matplotlib widget in a notebook cell
- Windows host is primary (PowerShell). Use
python (not python3) in PowerShell commands.
Procedure
1. Choose the Interface
Object-Oriented (RECOMMENDED for all production code):
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([1, 2, 3, 4])
ax.set_ylabel('some numbers')
plt.show()
- Explicit control over Figure and Axes objects
- Better for complex figures with multiple subplots
- Easier to maintain and debug
pyplot (MATLAB-style — quick exploration only):
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')
plt.show()
- Stateful; convenient for simple scripts
- Avoid in production code due to implicit state confusion
2. Create a Basic Plot (OO Interface)
import matplotlib.pyplot as plt
import numpy as np
# Create figure and axes with explicit size
fig, ax = plt.subplots(figsize=(10, 6), constrained_layout=True)
# 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()
3. Create Multi-Panel Figures
Regular grid:
fig, axes = plt.subplots(2, 2, figsize=(12, 10), constrained_layout=True)
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)
Mosaic layout (flexible, label-based):
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)
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
4. Select Plot Types
| Plot Type |
Use Case |
Example Call |
| Line |
Time series, trends |
ax.plot(x, y, linewidth=2, linestyle='--', marker='o', color='blue') |
| Scatter |
Correlations |
ax.scatter(x, y, s=sizes, c=colors, alpha=0.6, cmap='viridis') |
| Bar |
Categorical comparisons |
ax.bar(categories, values, color='steelblue', edgecolor='black') |
| Horizontal bar |
Long labels |
ax.barh(categories, values) |
| Histogram |
Distributions |
ax.hist(data, bins=30, edgecolor='black', alpha=0.7) |
| Heatmap |
Matrix data |
im = ax.imshow(matrix, cmap='coolwarm', aspect='auto') then plt.colorbar(im, ax=ax) |
| Contour |
3D data on 2D |
contour = ax.contour(X, Y, Z, levels=10) then ax.clabel(contour, inline=True, fontsize=8) |
| Box |
Statistical distributions |
ax.boxplot([data1, data2, data3], labels=['A', 'B', 'C']) |
| Violin |
Distribution densities |
ax.violinplot([data1, data2, data3], positions=[1, 2, 3]) |
For specialized plot types beyond the table, use the official gallery: https://matplotlib.org/stable/gallery/index.html
5. Apply 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'
Style sheets:
plt.style.use('seaborn-v0_8-darkgrid')
print(plt.style.available) # List all available styles
# Common: 'ggplot', 'bmh', 'fivethirtyeight', 'seaborn-v0_8-darkgrid'
rcParams for global defaults:
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 colormap and style-sheet options, prefer perceptually uniform maps (viridis, plasma, cividis) and the official cheatsheets: https://matplotlib.org/cheatsheets/
6. Save and Export Figures
# 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)
Key parameters:
| Parameter |
Purpose |
Recommended Value |
dpi |
Resolution |
300 for publications, 150 for web, 72 for screen |
bbox_inches='tight' |
Remove excess whitespace |
Always use |
facecolor='white' |
Ensure white background |
Use with dark themes |
transparent=True |
Transparent background |
For overlays |
7. Create 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)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
8. Confirm Unfamiliar APIs
Look up method signatures on the Matplotlib API index (https://matplotlib.org/stable/api/index.html) rather than guessing Axes/Figure parameters. Gallery examples at https://matplotlib.org/stable/gallery/index.html cover specialized plot types.
9. Organize Reusable Plot Code
def create_analysis_plot(data, title):
"""Create standardized analysis plot."""
fig, ax = plt.subplots(figsize=(10, 6), constrained_layout=True)
ax.plot(data['x'], data['y'], linewidth=2)
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
fig, ax = create_analysis_plot(my_data, 'My Analysis')
plt.savefig('analysis.png', dpi=300, bbox_inches='tight')
Pitfalls
- Overlapping elements — Use
constrained_layout=True at figure creation or call fig.tight_layout() before saving. Do not use both together.
- State confusion with pyplot interface — The pyplot state machine tracks the "current" figure/axes implicitly. Use the OO interface (
fig, ax = plt.subplots()) to avoid ambiguity in production code.
- Memory leaks with many figures — Always close figures explicitly with
plt.close(fig) when generating many plots in a loop. Unclosed figures accumulate in memory.
- Font warnings — If fonts are missing, suppress warnings by setting
plt.rcParams['font.sans-serif'] = ['DejaVu Sans'] or install the required font package.
- DPI confusion —
figsize is in inches, not pixels. Final pixel dimensions: pixels = dpi * inches. A (10, 6) figure at 300 dpi produces a 3000×1800 image.
- Rainbow colormaps (jet) — Not perceptually uniform; can misrepresent data. Use
viridis, plasma, inferno, or cividis instead.
- Large dataset file size — For scatter/line plots with many points, pass
rasterized=True to reduce PDF/SVG file size. Downsample dense time series before plotting.
show() blocks in scripts — plt.show() blocks execution in non-interactive scripts. Call savefig() before show() to ensure the file is written.
- Style name changes — Seaborn styles were renamed in matplotlib 3.6+ (e.g.,
'seaborn-darkgrid' → 'seaborn-v0_8-darkgrid'). Use plt.style.available to check valid names.
Verification
Check Installation
python -c "import matplotlib; print(matplotlib.__version__)"
Expected output (version may differ):
3.9.0
Verify a Plot Renders and Saves
python -c "import matplotlib.pyplot as plt; fig, ax = plt.subplots(); ax.plot([1,2,3,4]); plt.savefig('test_plot.png', dpi=150, bbox_inches='tight'); print('OK')"
Expected output:
OK
Verify the file exists:
Test-Path .\test_plot.png
Expected output:
True
Verify Available Styles
python -c "import matplotlib.pyplot as plt; print(plt.style.available)"
Verify Backend (Non-Interactive / Headless)
python -c "import matplotlib; matplotlib.use('Agg'); import matplotlib.pyplot as plt; print(matplotlib.get_backend())"
Expected output:
Agg
Related Skills
- numpy — Array generation and numerical data feeding into plots
- pandas — DataFrame-based plotting and data manipulation
- seaborn — High-level statistical visualizations built on matplotlib
Additional Resources
Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
1---2name: matplotlib3description: Builds Matplotlib figures with the OO Axes API: subplots, mosaic, GridSpec, rcParams, and savefig to PNG/PDF/SVG. Use for pyplot line, scatter, bar, hist, heatmap, contour, or 3D work in Python. Never route Seaborn estimators or Plotly Dash apps through this chair.4license: https://github.com/matplotlib/matplotlib/tree/main/LICENSE5---6
7## When to Use
8
9Use this skill when:
10
11- Creating any type of plot or chart (line, scatter, bar, histogram, heatmap, contour, box, violin, 3D surface, etc.)
12- Generating scientific or statistical visualizations
13- Customizing plot appearance (colors, styles, labels, legends, annotations)
14- Creating multi-panel figures with subplots, mosaic layouts, or GridSpec
15- Exporting visualizations to PNG, PDF, SVG, or other formats
16- Building interactive plots or animations
17- Working with 3D visualizations
18- Integrating plots into Jupyter notebooks or GUI applications
19
20**Trigger keywords:** plot, chart, figure, axes, subplot, matplotlib, pyplot, visualization, heatmap, contour, histogram, scatter, bar chart, savefig, rcParams, colormap.
21
22## Prerequisites
23
24- Python 3.8+ installed and available on `PATH`
25- Matplotlib installed: `pip install matplotlib` (NumPy is a required dependency and installs automatically)
26- For Jupyter integration: `pip install jupyter` and run `%matplotlib inline` or `%matplotlib widget` in a notebook cell
27- Windows host is primary (PowerShell). Use `python` (not `python3`) in PowerShell commands.
28
29## Procedure
30
31### 1. Choose the Interface
32
33**Object-Oriented (RECOMMENDED for all production code):**
34
35```python
36import matplotlib.pyplot as plt
37
38fig, ax = plt.subplots()
39ax.plot([1, 2, 3, 4])
40ax.set_ylabel('some numbers')
41plt.show()
42```
43
44- Explicit control over Figure and Axes objects
45- Better for complex figures with multiple subplots
46- Easier to maintain and debug
47
48**pyplot (MATLAB-style — quick exploration only):**
49
50```python
51import matplotlib.pyplot as plt
52
53plt.plot([1, 2, 3, 4])
54plt.ylabel('some numbers')
55plt.show()
56```
57
58- Stateful; convenient for simple scripts
59- Avoid in production code due to implicit state confusion
60
61### 2. Create a Basic Plot (OO Interface)
62
63```python
64import matplotlib.pyplot as plt
65import numpy as np
66
67# Create figure and axes with explicit size
68fig, ax = plt.subplots(figsize=(10, 6), constrained_layout=True)
69
70# Generate and plot data
71x = np.linspace(0, 2*np.pi, 100)
72ax.plot(x, np.sin(x), label='sin(x)')
73ax.plot(x, np.cos(x), label='cos(x)')
74
75# Customize
76ax.set_xlabel('x')
77ax.set_ylabel('y')
78ax.set_title('Trigonometric Functions')
79ax.legend()
80ax.grid(True, alpha=0.3)
81
82# Save and/or display
83plt.savefig('plot.png', dpi=300, bbox_inches='tight')
84plt.show()
85```
86
87### 3. Create Multi-Panel Figures
88
89**Regular grid:**
90
91```python
92fig, axes = plt.subplots(2, 2, figsize=(12, 10), constrained_layout=True)
93axes[0, 0].plot(x, y1)
94axes[0, 1].scatter(x, y2)
95axes[1, 0].bar(categories, values)
96axes[1, 1].hist(data, bins=30)
97```
98
99**Mosaic layout (flexible, label-based):**
100
101```python
102fig, axes = plt.subplot_mosaic([['left', 'right_top'],
103 ['left', 'right_bottom']],
104 figsize=(10, 8))
105axes['left'].plot(x, y)
106axes['right_top'].scatter(x, y)
107axes['right_bottom'].hist(data)
108```
109
110**GridSpec (maximum control):**
111
112```python
113from matplotlib.gridspec import GridSpec
114
115fig = plt.figure(figsize=(12, 8))
116gs = GridSpec(3, 3, figure=fig)
117ax1 = fig.add_subplot(gs[0, :]) # Top row, all columns
118ax2 = fig.add_subplot(gs[1:, 0]) # Bottom two rows, first column
119ax3 = fig.add_subplot(gs[1:, 1:]) # Bottom two rows, last two columns
120```
121
122### 4. Select Plot Types
123
124| Plot Type | Use Case | Example Call |
125|-----------|----------|--------------|
126| Line | Time series, trends | `ax.plot(x, y, linewidth=2, linestyle='--', marker='o', color='blue')` |
127| Scatter | Correlations | `ax.scatter(x, y, s=sizes, c=colors, alpha=0.6, cmap='viridis')` |
128| Bar | Categorical comparisons | `ax.bar(categories, values, color='steelblue', edgecolor='black')` |
129| Horizontal bar | Long labels | `ax.barh(categories, values)` |
130| Histogram | Distributions | `ax.hist(data, bins=30, edgecolor='black', alpha=0.7)` |
131| Heatmap | Matrix data | `im = ax.imshow(matrix, cmap='coolwarm', aspect='auto')` then `plt.colorbar(im, ax=ax)` |
132| Contour | 3D data on 2D | `contour = ax.contour(X, Y, Z, levels=10)` then `ax.clabel(contour, inline=True, fontsize=8)` |
133| Box | Statistical distributions | `ax.boxplot([data1, data2, data3], labels=['A', 'B', 'C'])` |
134| Violin | Distribution densities | `ax.violinplot([data1, data2, data3], positions=[1, 2, 3])` |
135
136For specialized plot types beyond the table, use the official gallery: https://matplotlib.org/stable/gallery/index.html
137
138### 5. Apply Styling and Customization
139
140**Color specification methods:**
141
142- Named colors: `'red'`, `'blue'`, `'steelblue'`
143- Hex codes: `'#FF5733'`
144- RGB tuples: `(0.1, 0.2, 0.3)`
145- Colormaps: `cmap='viridis'`, `cmap='plasma'`, `cmap='coolwarm'`
146
147**Style sheets:**
148
149```python
150plt.style.use('seaborn-v0_8-darkgrid')
151print(plt.style.available) # List all available styles
152# Common: 'ggplot', 'bmh', 'fivethirtyeight', 'seaborn-v0_8-darkgrid'
153```
154
155**rcParams for global defaults:**
156
157```python
158plt.rcParams['font.size'] = 12
159plt.rcParams['axes.labelsize'] = 14
160plt.rcParams['axes.titlesize'] = 16
161plt.rcParams['xtick.labelsize'] = 10
162plt.rcParams['ytick.labelsize'] = 10
163plt.rcParams['legend.fontsize'] = 12
164plt.rcParams['figure.titlesize'] = 18
165```
166
167**Text and annotations:**
168
169```python
170ax.text(x, y, 'annotation', fontsize=12, ha='center')
171ax.annotate('important point', xy=(x, y), xytext=(x+1, y+1),
172 arrowprops=dict(arrowstyle='->', color='red'))
173```
174
175For colormap and style-sheet options, prefer perceptually uniform maps (`viridis`, `plasma`, `cividis`) and the official cheatsheets: https://matplotlib.org/cheatsheets/
176
177### 6. Save and Export Figures
178
179```python
180# High-resolution PNG for presentations/papers
181plt.savefig('figure.png', dpi=300, bbox_inches='tight', facecolor='white')
182
183# Vector format for publications (scalable)
184plt.savefig('figure.pdf', bbox_inches='tight')
185plt.savefig('figure.svg', bbox_inches='tight')
186
187# Transparent background
188plt.savefig('figure.png', dpi=300, bbox_inches='tight', transparent=True)
189```
190
191**Key parameters:**
192
193| Parameter | Purpose | Recommended Value |
194|-----------|---------|-------------------|
195| `dpi` | Resolution | 300 for publications, 150 for web, 72 for screen |
196| `bbox_inches='tight'` | Remove excess whitespace | Always use |
197| `facecolor='white'` | Ensure white background | Use with dark themes |
198| `transparent=True` | Transparent background | For overlays |
199
200### 7. Create 3D Plots
201
202```python
203from mpl_toolkits.mplot3d import Axes3D
204
205fig = plt.figure(figsize=(10, 8))
206ax = fig.add_subplot(111, projection='3d')
207
208# Surface plot
209ax.plot_surface(X, Y, Z, cmap='viridis')
210
211# 3D scatter
212ax.scatter(x, y, z, c=colors, marker='o')
213
214# 3D line plot
215ax.plot(x, y, z, linewidth=2)
216
217ax.set_xlabel('X Label')
218ax.set_ylabel('Y Label')
219ax.set_zlabel('Z Label')
220```
221
222### 8. Confirm Unfamiliar APIs
223
224Look up method signatures on the Matplotlib API index (https://matplotlib.org/stable/api/index.html) rather than guessing `Axes`/`Figure` parameters. Gallery examples at https://matplotlib.org/stable/gallery/index.html cover specialized plot types.
225
226### 9. Organize Reusable Plot Code
227
228```python
229def create_analysis_plot(data, title):
230 """Create standardized analysis plot."""
231 fig, ax = plt.subplots(figsize=(10, 6), constrained_layout=True)
232
233 ax.plot(data['x'], data['y'], linewidth=2)
234
235 ax.set_xlabel('X Axis Label', fontsize=12)
236 ax.set_ylabel('Y Axis Label', fontsize=12)
237 ax.set_title(title, fontsize=14, fontweight='bold')
238 ax.grid(True, alpha=0.3)
239
240 return fig, ax
241
242fig, ax = create_analysis_plot(my_data, 'My Analysis')
243plt.savefig('analysis.png', dpi=300, bbox_inches='tight')
244```
245
246## Pitfalls
247
2481. **Overlapping elements** — Use `constrained_layout=True` at figure creation or call `fig.tight_layout()` before saving. Do not use both together.
2492. **State confusion with pyplot interface** — The pyplot state machine tracks the "current" figure/axes implicitly. Use the OO interface (`fig, ax = plt.subplots()`) to avoid ambiguity in production code.
2503. **Memory leaks with many figures** — Always close figures explicitly with `plt.close(fig)` when generating many plots in a loop. Unclosed figures accumulate in memory.
2514. **Font warnings** — If fonts are missing, suppress warnings by setting `plt.rcParams['font.sans-serif'] = ['DejaVu Sans']` or install the required font package.
2525. **DPI confusion** — `figsize` is in inches, not pixels. Final pixel dimensions: `pixels = dpi * inches`. A `(10, 6)` figure at 300 dpi produces a 3000×1800 image.
2536. **Rainbow colormaps (jet)** — Not perceptually uniform; can misrepresent data. Use `viridis`, `plasma`, `inferno`, or `cividis` instead.
2547. **Large dataset file size** — For scatter/line plots with many points, pass `rasterized=True` to reduce PDF/SVG file size. Downsample dense time series before plotting.
2558. **`show()` blocks in scripts** — `plt.show()` blocks execution in non-interactive scripts. Call `savefig()` before `show()` to ensure the file is written.
2569. **Style name changes** — Seaborn styles were renamed in matplotlib 3.6+ (e.g., `'seaborn-darkgrid'` → `'seaborn-v0_8-darkgrid'`). Use `plt.style.available` to check valid names.
257
258## Verification
259
260### Check Installation
261
262```powershell
263python -c "import matplotlib; print(matplotlib.__version__)"
264```
265
266Expected output (version may differ):
267
268```
2693.9.0
270```
271
272### Verify a Plot Renders and Saves
273
274```powershell
275python -c "import matplotlib.pyplot as plt; fig, ax = plt.subplots(); ax.plot([1,2,3,4]); plt.savefig('test_plot.png', dpi=150, bbox_inches='tight'); print('OK')"
276```
277
278Expected output:
279
280```
281OK
282```
283
284Verify the file exists:
285
286```powershell
287Test-Path .\test_plot.png
288```
289
290Expected output:
291
292```
293True
294```
295
296### Verify Available Styles
297
298```powershell
299python -c "import matplotlib.pyplot as plt; print(plt.style.available)"
300```
301
302### Verify Backend (Non-Interactive / Headless)
303
304```powershell
305python -c "import matplotlib; matplotlib.use('Agg'); import matplotlib.pyplot as plt; print(matplotlib.get_backend())"
306```
307
308Expected output:
309
310```
311Agg
312```
313
314## Related Skills
315
316- **numpy** — Array generation and numerical data feeding into plots
317- **pandas** — DataFrame-based plotting and data manipulation
318- **seaborn** — High-level statistical visualizations built on matplotlib
319
320## Additional Resources
321
322- Official documentation: https://matplotlib.org/
323- Gallery: https://matplotlib.org/stable/gallery/index.html
324- Cheatsheets: https://matplotlib.org/cheatsheets/
325- Tutorials: https://matplotlib.org/stable/tutorials/index.html
326
327## Limitations
328
329- Use this skill only when the task clearly matches the scope described above.
330- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
331- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.