--- name: matplotlib description: "Foundational plotting library. Create line plots, scatter, bar, histograms, heatmaps, 3D, subplots, export PNG/PDF/SVG, for scientific visualization and publication figures." --- # 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: 1. **Figure** - The top-level container for all plot elements 2. **Axes** - The actual plotting area where data is displayed (one Figure can contain multiple Axes) 3. **Artist** - Everything visible on the figure (lines, text, ticks, etc.) 4. **Axis** - The number line objects (x-axis, y-axis) that handle ticks and labels ### Two Interfaces **1. pyplot Interface (Implicit, MATLAB-style)** ```python 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 **2. Object-Oriented Interface (Explicit)** ```python 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 ### 1. Basic Plot Creation **Single plot workflow:** ```python 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() ``` ### 2. Multiple Subplots **Creating subplot layouts:** ```python # 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 ``` ### 3. Plot Types and Use Cases **Line plots** - Time series, continuous data, trends ```python ax.plot(x, y, linewidth=2, linestyle='--', marker='o', color='blue') ``` **Scatter plots** - Relationships between variables, correlations ```python ax.scatter(x, y, s=sizes, c=colors, alpha=0.6, cmap='viridis') ``` **Bar charts** - Categorical comparisons ```python ax.bar(categories, values, color='steelblue', edgecolor='black') # For horizontal bars: ax.barh(categories, values) ``` **Histograms** - Distributions ```python ax.hist(data, bins=30, edgecolor='black', alpha=0.7) ``` **Heatmaps** - Matrix data, correlations ```python im = ax.imshow(matrix, cmap='coolwarm', aspect='auto') plt.colorbar(im, ax=ax) ``` **Contour plots** - 3D data on 2D plane ```python contour = ax.contour(X, Y, Z, levels=10) ax.clabel(contour, inline=True, fontsize=8) ``` **Box plots** - Statistical distributions ```python ax.boxplot([data1, data2, data3], labels=['A', 'B', 'C']) ``` **Violin plots** - Distribution densities ```python ax.violinplot([data1, data2, data3], positions=[1, 2, 3]) ``` For comprehensive plot type examples and variations, refer to `references/plot_types.md`. ### 4. 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:** ```python 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:** ```python 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:** ```python 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`. ### 5. Saving Figures **Export to various formats:** ```python # 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 ### 6. Working with 3D Plots ```python 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 ### 1. 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 ### 2. 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 ### 3. 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 ### 4. 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 ### 5. 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 ### 6. 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 ### 7. Code Organization ```python # 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:** ```bash python scripts/plot_template.py ``` ### `style_configurator.py` Interactive utility to configure matplotlib style preferences and generate custom style sheets. **Usage:** ```bash 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 1. **Overlapping elements**: Use `constrained_layout=True` or `tight_layout()` 2. **State confusion**: Use OO interface to avoid pyplot state machine issues 3. **Memory issues with many figures**: Close figures explicitly with `plt.close(fig)` 4. **Font warnings**: Install fonts or suppress warnings with `plt.rcParams['font.sans-serif']` 5. **DPI confusion**: Remember that figsize is in inches, not pixels: `pixels = dpi * inches` ## Additional Resources - Official documentation: https://matplotlib.org/ - Gallery: https://matplotlib.org/stable/gallery/index.html - Cheatsheets: https://matplotlib.org/cheatsheets/ - Tutorials: https://matplotlib.org/stable/tutorials/index.html